Create GitHub Issue from Ticket
Convert a local markdown ticket into a GitHub Issue with full content preservation, label management, cross-reference resolution, and workflow phase sub-issues.
Invocation
The user provides:
- Ticket identifier: bare number (
0039a), full filename stem (0039a_energy_tracking_diagnostic_infrastructure), or with.mdextension
Example: /create-issue 0040b
Workflow Overview
1. RESOLVE -> Find the ticket file in tickets/
2. PARSE -> Extract title, metadata, and body sections
3. CLASSIFY -> Determine ticket kind: Feature (epic) vs Work (leaf)
4. CHECK -> Search for existing issue by ticket label (idempotency)
5. LABELS -> Create type, ticket, phase labels if missing
6. BUILD -> Format issue body from template
7. CROSSREF -> Resolve internal ticket links to issue numbers
8. CREATE -> Create or update the GitHub Issue
9. PHASES -> (Work tickets only) Create phase sub-issues and link them
10. PARENT -> Update parent issue's subticket task list
11. REPORT -> Show URL, labels, phases, and summary
Step 1: Resolve Ticket File
Find the ticket file in tickets/:
- If the argument contains
.md, look fortickets/{argument}directly - Otherwise, glob for
tickets/{argument}*.md - If multiple matches, prefer exact prefix match (e.g.,
0040matches0040_not0040a_) - If still ambiguous, list matches and ask the user to clarify
Read the matched file.
Step 2: Parse Ticket
The project has two ticket header formats. Detect and parse both:
New Format (Ticket NNNN)
Header line: # Ticket NNNN: Title Text
Metadata appears as bold key-value pairs below the Status section:
**Current Phase**: value
**Created**: value
**Type**: value
**Prototype**: Yes | No
**Parent Ticket**: [NNNN_name](filename.md)
**Dependencies**: [NNNN](filename.md)
**Blocks**: [NNNN](filename.md)
Old Format (Feature Ticket)
Header line: # Feature Ticket: Title Text
Metadata appears in a ## Metadata section:
## Metadata
- **Created**: value
- **Priority**: value
- **Estimated Complexity**: value
- **Target Component(s)**: value
Fields to Extract
| Field | Source (New) | Source (Old) | Required |
|---|---|---|---|
ticket_id | From header NNNN | From filename prefix | Yes |
title | After : in # Ticket NNNN: | After : in # Feature Ticket: | Yes |
current_phase | **Current Phase**: | Derive from Status checkboxes | Yes |
created | **Created**: | **Created**: in Metadata | No |
type | **Type**: | None (use enhancement) | No |
prototype | **Prototype**: (Yes/No) | None (default Yes) | No |
parent | **Parent Ticket**: link | None | No |
dependencies | **Dependencies**: / **Depends On**: links | ## Related Tickets | No |
blocks | **Blocks**: links | None | No |
Section Extraction
Extract content from these sections (if present):
## Overviewor## Summaryor## Motivation## Requirements## Implementation Approach## Test Plan## Acceptance Criteria## Subtickets## Files to Create/Modifyor## Files## Workflow Log
Status Derivation
If **Current Phase**: is not present, derive from the Status checkbox list — the last checked item indicates the current phase.
Step 3: Classify Ticket
Determine the ticket kind: Feature (epic/parent), Work (leaf), or Investigation (debug).
Feature Ticket (Epic)
A ticket is a Feature if ANY of these are true:
Typefield contains(Parent)— e.g.,Implementation (Parent),Debug Investigation (Parent)- The ticket has a
## Subticketssection with a table of child tickets - The ticket body is primarily a tracking document for child work items
Feature tickets:
- Get child work tickets as sub-issues (from the Subtickets table)
- Do NOT get workflow phase sub-issues
- Get the
featurelabel
Investigation Ticket (Debug)
A ticket is an Investigation if ANY of these are true:
Typefield containsInvestigation(but NOT(Parent)) — e.g.,Investigation,Debug Investigation- The ticket has a
## Hypothesis Spaceor## Problem Statementsection - The ticket has a
## Suspect Codeor## Files to Investigatesection
Investigation tickets:
- Get debug workflow phase sub-issues (Investigate, Diagnose, Fix, Verify)
- May be a sub-issue of a parent Feature ticket
- Get the
type:investigationlabel
Work Ticket (Leaf)
All other tickets are Work tickets. These represent actual units of work that go through the design-to-implementation workflow.
Work tickets:
- Get workflow phase sub-issues (Design, Math, Prototype, Implementation)
- May be a sub-issue of a parent Feature ticket
Step 4: Check for Existing Issue
Search for an existing issue with the ticket label:
bash1gh issue list --label "ticket:{ticket_id}" --state all --json number,title,state --limit 1
- If found and
--state open: offer to update the existing issue - If found and
--state closed: report that the issue already exists and is closed; ask if user wants to reopen and update - If not found: proceed to create
Also check for existing phase sub-issues (for Work and Investigation tickets):
bash1# Work ticket phases 2gh issue list --label "ticket:{ticket_id}" --label "phase:design" --state all --json number --limit 1 3gh issue list --label "ticket:{ticket_id}" --label "phase:math" --state all --json number --limit 1 4gh issue list --label "ticket:{ticket_id}" --label "phase:prototype" --state all --json number --limit 1 5gh issue list --label "ticket:{ticket_id}" --label "phase:implementation" --state all --json number --limit 1 6 7# Investigation ticket phases 8gh issue list --label "ticket:{ticket_id}" --label "phase:investigate" --state all --json number --limit 1 9gh issue list --label "ticket:{ticket_id}" --label "phase:diagnose" --state all --json number --limit 1 10gh issue list --label "ticket:{ticket_id}" --label "phase:fix" --state all --json number --limit 1 11gh issue list --label "ticket:{ticket_id}" --label "phase:verify" --state all --json number --limit 1
Only check the phases relevant to the ticket kind. Skip creating any phase sub-issue that already exists.
Step 5: Create Labels
Check and create labels as needed using gh label create. See references/label-mapping.md for the full mapping.
Required labels for every issue:
- Ticket label:
ticket:{ticket_id}(color#0E8A16) — idempotency key - Type label: derived from the
Typemetadata field
For Feature tickets:
3. Feature label: feature (color #FBCA04)
For Work tickets, create phase labels:
3. phase:design (color #C2E0C6)
4. phase:math (color #F9D0C4) — only if math phase applies
5. phase:prototype (color #FEF2C0) — only if prototype phase applies
6. phase:implementation (color #BFD4F2)
For Investigation tickets, create debug phase labels:
3. phase:investigate (color #D4C5F9)
4. phase:diagnose (color #F9D0C4)
5. phase:fix (color #C2E0C6)
6. phase:verify (color #BFD4F2)
Create each label only if it doesn't already exist:
bash1gh label create "ticket:{ticket_id}" --color "0E8A16" --description "Ticket {ticket_id}" --force 2gh label create "type:{type}" --color "{color}" --force 3gh label create "phase:design" --color "C2E0C6" --description "Design phase" --force
Use --force to avoid errors if the label already exists.
Step 6: Build Issue Body
Use the template from references/body-template.md.
Rules:
- Omit empty sections entirely — do not include section headers with no content
- Acceptance Criteria: Convert
- [ ] **AC1**: textor- [x] textto GitHub task list format- [ ] text/- [x] text - Subtickets (Feature tickets only): Build a task list of children
- Workflow Phases (Work and Investigation tickets): Include a task list of phase sub-issues (populated after Step 9)
- Workflow Log: Wrap in
<details>collapsible - Max body length: GitHub limits issue body to ~65535 chars. If body exceeds 60000 chars, truncate the Workflow Log section and add a note
Subticket Task List (Feature Tickets)
For Feature tickets with a ## Subtickets section:
- Parse the subticket table for ticket IDs and titles
- For each subticket, check if a GitHub issue exists:
gh issue list --label "ticket:{child_id}" --state all --json number,title --limit 1 - Format:
- Has issue:
- [ ] #{issue_number} - {title} - No issue yet:
- [ ] {title} _(ticket: {child_id}, no issue yet)_ - If the child ticket's phase indicates completion, use
- [x]instead
- Has issue:
Workflow Phases Section (Work and Investigation Tickets)
For Work and Investigation tickets, include a ## Workflow Phases section with placeholders. This section is updated after phase sub-issues are created in Step 9.
Work tickets:
markdown1## Workflow Phases 2 3- [ ] #{design_issue} Design 4- [ ] #{math_issue} Math Formulation 5- [ ] #{prototype_issue} Prototype 6- [ ] #{impl_issue} Implementation
Omit the Math line if math phase doesn't apply. Omit the Prototype line if prototype phase doesn't apply.
Investigation tickets:
markdown1## Workflow Phases 2 3- [ ] #{investigate_issue} Investigate 4- [ ] #{diagnose_issue} Diagnose 5- [ ] #{fix_issue} Fix 6- [ ] #{verify_issue} Verify
Step 7: Resolve Cross-References
Scan the issue body for internal ticket links in these patterns:
[NNNN](NNNN_name.md)— markdown link to another ticket[NNNN_name](NNNN_name.md)— full name linkticket NNNNorTicket NNNN— plain text reference
For each referenced ticket:
- Check if a GitHub issue exists:
gh issue list --label "ticket:{ref_id}" --state all --json number --limit 1 - If found: replace the link with
#N(the GitHub issue number) - If not found: keep the original text but append
_(no issue yet)_
Track and report all link resolutions in Step 11.
Step 8: Create or Update Main Issue
Create New Issue
bash1gh issue create \ 2 --title "{title}" \ 3 --body "{body}" \ 4 --label "ticket:{ticket_id}" \ 5 --label "type:{type}" \ 6 [--label "feature"]
Capture the issue number from the output URL.
Update Existing Issue
bash1gh issue edit {issue_number} \ 2 --title "{title}" \ 3 --body "{body}"
Also ensure all labels are applied:
bash1gh issue edit {issue_number} --add-label "ticket:{ticket_id},type:{type}"
Close Completed Issues
If the ticket's status indicates completion (phase contains "Complete" or "Merged"), close the issue after creation:
bash1gh issue close {issue_number} --reason "completed"
Step 9: Create Phase Sub-Issues (Work and Investigation Tickets)
Skip this step entirely for Feature tickets.
9a: Determine Applicable Phases
Work tickets get these phases:
- Design — always
- Math Formulation — only if math is detected (see detection rules below)
- Prototype — only if prototype is needed (see detection rules below)
- Implementation — always
Investigation tickets get these phases:
- Investigate — always (instrument, reproduce, gather evidence)
- Diagnose — always (hypothesis elimination, root cause identification)
- Fix — always (implement the fix)
- Verify — always (regression testing, sanitizer validation)
9b: Math Phase Detection (Work Tickets Only)
Include the Math Formulation phase if ANY of these are true:
- The ticket body contains keywords:
physics,collision,inertia,quaternion,tensor,eigenvalue,impulse,friction,torque,angular,kinetic energy,potential energy,Lagrangian,Jacobian,numerical stability,convergence - A file exists at
docs/designs/{ticket_name}/math-formulation.md - The ticket's
## Requirementssection contains LaTeX-style math (backtick blocks with equations,½,ω,∑, etc.)
Where {ticket_name} is the full filename stem without .md (e.g., 0040b_split_impulse_position_correction).
9b2: Prototype Phase Detection (Work Tickets Only)
Include the Prototype phase unless the ticket explicitly opts out. Check in this order:
- If the ticket has a
**Prototype**:metadata field set toNo(case-insensitive), skip the Prototype phase - If the
**Prototype**:field isYesor absent, include the Prototype phase (default behavior)
This allows ticket authors to opt out of prototyping for straightforward work like API refactors, renames, or simple bug fixes where there are no design assumptions to validate.
9c: Create Each Phase Sub-Issue
For each applicable phase, create a sub-issue:
bash1gh issue create \ 2 --title "[Phase] {title}" \ 3 --body "{phase_body}" \ 4 --label "ticket:{ticket_id}" \ 5 --label "phase:{phase}"
Work ticket phase titles:
[Design] Split Impulse Position Correction[Math] Split Impulse Position Correction[Prototype] Split Impulse Position Correction[Implementation] Split Impulse Position Correction
Investigation ticket phase titles:
[Investigate] Collision Energy Stabilization Debug[Diagnose] Collision Energy Stabilization Debug[Fix] Collision Energy Stabilization Debug[Verify] Collision Energy Stabilization Debug
Phase Sub-Issue Body Content
See references/phase-templates.md for the body content of each phase sub-issue. Work and Investigation tickets use different templates.
9d: Link Phase Sub-Issues to Parent
After creating each phase sub-issue, link it as a sub-issue of the main ticket issue using the GitHub GraphQL API:
bash1# Get the node ID of the main issue 2PARENT_ID=$(gh issue view {main_issue_number} --json id -q '.id') 3 4# Get the node ID of the phase sub-issue 5CHILD_ID=$(gh issue view {phase_issue_number} --json id -q '.id') 6 7# Link as sub-issue (use -F for GraphQL variables, -f for query) 8gh api graphql -F parentId="$PARENT_ID" -F childId="$CHILD_ID" -f query=' 9mutation AddSubIssue($parentId: ID!, $childId: ID!) { 10 addSubIssue(input: { 11 issueId: $parentId 12 subIssueId: $childId 13 }) { 14 issue { id } 15 subIssue { id } 16 } 17}'
If the GraphQL API fails (e.g., sub-issues not enabled for the repo), fall back to including the phase issues as a task list in the main issue body.
9e: Update Main Issue Body with Phase Links
After creating all phase sub-issues, update the main issue's ## Workflow Phases section to include the actual issue numbers:
Work tickets:
markdown1## Workflow Phases 2 3- [ ] #42 Design 4- [ ] #43 Math Formulation 5- [ ] #44 Prototype 6- [ ] #45 Implementation
Omit Math and/or Prototype lines if those phases don't apply.
Investigation tickets:
markdown1## Workflow Phases 2 3- [ ] #42 Investigate 4- [ ] #43 Diagnose 5- [ ] #44 Fix 6- [ ] #45 Verify
bash1gh issue edit {main_issue_number} --body "{updated_body}"
Step 10: Update Parent Issue
If the ticket has a **Parent Ticket**: field:
- Find the parent's GitHub issue:
gh issue list --label "ticket:{parent_id}" --state all --json number,body --limit 1 - If the parent issue exists and is a Feature ticket:
- Find the
## Subticketssection in the parent body - Replace the line for this child ticket with the linked version:
- [ ] #{new_issue} - {title} - Use
gh issue edit {parent_number} --body "{updated_body}"
- Find the
- Link this issue as a sub-issue of the parent (same GraphQL as Step 9d)
If the parent issue doesn't exist yet, skip this step and note it in the report.
Step 11: Report
Print a summary:
Issue created: #{number} — {title}
URL: {url}
Kind: Feature | Work | Investigation
Labels: ticket:{id}, type:{type}, [feature]
Workflow phases created: (Work and Investigation tickets)
Work:
- #42 [Design] {title}
- #43 [Math] {title}
- #44 [Prototype] {title}
- #45 [Implementation] {title}
Investigation:
- #42 [Investigate] {title}
- #43 [Diagnose] {title}
- #44 [Fix] {title}
- #45 [Verify] {title}
Sub-issue linking: success | fallback to task list
Cross-references resolved:
- ticket 0038 -> #12
- ticket 0040a -> #15
- ticket 0040d (no issue yet)
Parent update:
- Updated #{parent} subticket list with #{number}
- Linked as sub-issue of #{parent}: success | skipped
Error Handling
Ticket file not found
- List all files in
tickets/that start with the given prefix - If none match, report "No ticket found matching '{input}'"
gh not authenticated
- If any
ghcommand fails with auth error, tell the user to rungh auth login
Label creation fails
- Use
--forceflag which updates existing labels rather than failing - If
gh label createstill fails, report the error and continue without the label
Sub-issue API not available
- If the GraphQL
addSubIssuemutation fails, fall back to task list references in the issue body - Report that sub-issue linking was skipped and why
Parent issue body too large to parse
- If the parent body can't be reliably modified, skip the parent update and report it
Phase sub-issue already exists
- If a phase sub-issue with the matching
ticket:{id}+phase:{phase}labels already exists, skip creating it - Use the existing issue number in the Workflow Phases section
References
- See
references/label-mapping.mdfor label naming conventions and color codes - See
references/body-template.mdfor the issue body template - See
references/phase-templates.mdfor phase sub-issue body templates