--- name: publish description: "Publish Seed specification as GitHub Issues for team-based project management" --- # /ouroboros:publish Convert a Seed specification into structured GitHub Issues for team workflows. ## Usage ``` ooo publish [seed_path] /ouroboros:publish [seed_path] ``` **Trigger keywords:** "publish to github", "create issues from seed", "seed to issues" ## Instructions When the user invokes this skill: ### Step 1: Prerequisite Check **1a. Verify `gh` CLI is installed:** ```bash command -v gh >/dev/null 2>&1 && echo "OK" || echo "MISSING" ``` If missing, tell the user: ``` GitHub CLI (gh) is not installed. Install it: https://cli.github.com/ ``` Stop. **1b. Verify `gh` is authenticated:** ```bash gh auth status ``` If not authenticated, tell the user: ``` GitHub CLI is not authenticated. Run: gh auth login ``` Stop. ### Step 2: Locate the Seed Ouroboros stores seeds in `~/.ouroboros/seeds/`: - **Interview seeds**: `~/.ouroboros/seeds/{seed_id}.yaml` (YAML) - **PM seeds**: `~/.ouroboros/seeds/pm_seed_{id}.json` (JSON) Determine the Seed source in this priority order: 1. **Explicit path argument**: If the user provided a file path (`.yaml` or `.json`), read it directly 2. **Most recent seed file**: Search for the most recent seed in the standard location: ```bash ls -t ~/.ouroboros/seeds/*.yaml ~/.ouroboros/seeds/*.json 2>/dev/null | head -5 ``` If multiple seeds exist, present the top candidates via AskUserQuestion and let the user choose. 3. **Conversation context**: If `ooo seed` or `ooo pm` was just run in this conversation and the seed path was reported, use that path. If no seed is found: ``` No Seed found. Run `ooo seed` or `ooo pm` first to generate a specification. ``` Stop. ### Step 3: Parse the Seed Detect the file format by extension and parse accordingly: **For YAML seeds** (from `ooo interview` + `ooo seed`): Read the YAML file and extract: - `goal` → Epic title and description - `constraints` → Listed in Epic body - `acceptance_criteria` → Checklist items in Epic + distributed to Task issues - `ontology_schema` → Documentation section in Epic - `evaluation_principles` → Quality criteria reference - `exit_conditions` → Definition of Done - `metadata.ambiguity_score` → Confidence indicator - `metadata.seed_id` → Used for duplicate detection **For JSON seeds** (from `ooo pm`): Read the JSON file and extract fields using the actual `PMSeed` schema: | PMSeed field | Maps to | |-------------|---------| | `pm_id` | Seed identifier (for duplicate detection) | | `product_name` | Epic title prefix | | `goal` | Epic Goal section | | `constraints` | Epic Constraints section (array of strings) | | `success_criteria` | Acceptance Criteria checklist (array of strings) | | `user_stories` | User Stories section (array of `{persona, action, benefit}`) | | `deferred_items` | Deferred Items section (array of strings) | | `decide_later_items` | Open Questions section (array of strings) | | `assumptions` | Assumptions section (array of strings) | Format user stories as: "As a **{persona}**, I want to **{action}**, so that **{benefit}**." If any field is missing or empty, omit that section from the Epic body rather than failing. ### Step 4: Detect Repository **4a. Attempt auto-detection from current directory:** ```bash gh repo view --json nameWithOwner -q '.nameWithOwner' 2>/dev/null ``` **4b. Present the target repo choice via AskUserQuestion:** If auto-detection succeeded: ```json { "questions": [{ "question": "Publish Seed as GitHub Issues to this repository?", "header": "Target Repository", "options": [ {"label": "", "description": "Use current repository"}, {"label": "Other", "description": "I'll specify a different owner/repo"} ], "multiSelect": false }] } ``` If auto-detection failed (not in a git repo): ```json { "questions": [{ "question": "Which GitHub repository should the issues be created in? (format: owner/repo)", "header": "Target Repository" }] } ``` If the user chose "Other", ask: ```json { "questions": [{ "question": "Enter the target repository (format: owner/repo):", "header": "Target Repository" }] } ``` Store the resolved repository as `TARGET_REPO`. **All subsequent `gh` commands MUST include `-R `** to ensure they target the correct repository. ### Step 5: Duplicate Check Before creating issues, check if this seed was already published: ```bash gh issue list -R --label "ouroboros" --state all --search "" --limit 5 --json number,title,state ``` The search uses the seed's unique identifier (`metadata.seed_id` for YAML seeds, `pm_id` for JSON seeds). This works because Step 7 persists the identifier in the Epic body (see the `Seed ID` field in the Epic template). If matching issues are found, warn the user via AskUserQuestion: ```json { "questions": [{ "question": "Found existing Ouroboros issues that may be from the same seed:\n\n\n\nCreate new issues anyway?", "header": "Duplicate Warning", "options": [ {"label": "Create anyway", "description": "Proceed with new issues"}, {"label": "Cancel", "description": "Do not create duplicate issues"} ], "multiSelect": false }] } ``` If "Cancel": Stop. ### Step 6: Plan Issue Structure Before creating issues, present the planned structure to the user for review. **6a. Break down acceptance criteria into Task groups:** Analyze the acceptance criteria and group them into logical implementation units. Each unit becomes a Task issue. Use your understanding of the domain to create meaningful groupings (e.g., group by feature area, layer, or dependency order). **6b. Present the plan via AskUserQuestion:** ```json { "questions": [{ "question": "Here's the planned issue structure:\n\n**Epic**: \n\n**Tasks**:\n1. \n2. \n3. \n\nProceed with creating these issues?", "header": "Issue Plan", "options": [ {"label": "Create issues", "description": "Publish to GitHub now"}, {"label": "Modify plan", "description": "I want to adjust the structure first"} ], "multiSelect": false }] } ``` If "Modify plan": Ask what to change, adjust, and re-present. ### Step 7: Create GitHub Issues **IMPORTANT**: Every `gh` command in this step MUST include `-R `. **Issue number extraction**: `gh issue create` outputs a URL like `https://github.com/owner/repo/issues/42`. Extract the issue number by parsing the trailing digits: ```bash EPIC_URL=$(gh issue create -R --title "..." --label "..." --body "...") EPIC_NUM=$(echo "$EPIC_URL" | grep -o '[0-9]*$') ``` Apply the same extraction pattern for every Task issue created. **7a. Create labels (if they don't exist):** ```bash gh label create "ouroboros" -R --description "Created by Ouroboros publish" --color "6f42c1" 2>/dev/null || true gh label create "epic" -R --description "Epic / parent issue" --color "0075ca" 2>/dev/null || true gh label create "task" -R --description "Implementation task" --color "008672" 2>/dev/null || true ``` **7b. Create the Epic issue:** ```bash gh issue create -R \ --title "[Epic] " \ --label "ouroboros,epic" \ --body "$(cat <<'BODY' ## Goal ## Constraints ## Acceptance Criteria - [ ] - [ ] - ... ## Ontology | Field | Type | Description | |-------|------|-------------| | | | | ## Evaluation Principles | Principle | Weight | Description | |-----------|--------|-------------| | | | | ## Exit Conditions --- **Seed ID**: `` | **Ambiguity Score**: | **Seed**: `` *Generated by [Ouroboros](https://github.com/Q00/ouroboros) via `ooo publish`* BODY )" ``` Capture the Epic issue number from the output. **7c. Create Task issues (one per implementation unit):** For each task: ```bash gh issue create -R \ --title "[Task] " \ --label "ouroboros,task" \ --body "$(cat <<'BODY' Parent: # ## Scope ## Acceptance Criteria - [ ] - [ ] ## Test Checklist - [ ] - [ ] - [ ] ## Pass Criteria --- *Part of [Epic] # | Generated by [Ouroboros](https://github.com/Q00/ouroboros) via `ooo publish`* BODY )" ``` **7d. Update Epic with task links:** After all tasks are created, add a comment to the Epic: ```bash gh issue comment -R --body "$(cat <<'BODY' ## Implementation Tasks - [ ] # - [ ] # - [ ] # Track overall progress by checking off tasks as their issues are closed. BODY )" ``` ### Step 8: Summary Present the results: ``` Published to : # [Epic] ├── # [Task] ├── # [Task] └── # [Task] View: https://github.com//issues/ ``` Then suggest next steps: ``` Next steps: - Assign tasks to team members on GitHub - Use GitHub Projects board for tracking - Run `ooo run` for AI-assisted implementation of individual tasks ``` ## Notes - **No MCP required**: This skill works entirely through `gh` CLI - **Non-destructive**: Creates new issues only, never modifies existing ones - **Cross-repo support**: All `gh` commands use `-R `, so seeds can be published to any repository the user has write access to - **Works with both seed formats**: YAML seeds from `ooo seed` and JSON seeds from `ooo pm` are both supported — the parser auto-detects format by file extension ## RFC #1392 State Breadcrumb Footer Your final response MUST end with exactly one breadcrumb footer line: ``` ◆ → next: ``` Derive `` from live session state via `ouroboros_session_status` when that MCP projection is available; otherwise derive it from this skill's actual outcome. Never use a linear `Step N of M` footer because Ouroboros is an evolutionary loop. When the next action is genuinely a choice, list 2-3 honest options in the `next:` clause. The breadcrumb line must be the last line of the response.