Skip to content

Migrate ticket-display headings to use ticket_ref #464

Description

@williamthorsen

Problem

Several skill output formats render a ticket reference in human-facing headings, and each site re-derives the display form on its own. Today the rule "if ticket_ref_prefix == '#', prepend #; else use ticket_id as-is" is implicit at every site:

  • summarize-change: # {TICKET} {title} (line ~44) — {TICKET} is an undocumented placeholder.
  • review-change: # Code review: {TICKET}: {description} (line ~66, branch scope).
  • review-change: # Commit review: {TICKET} [{WORK_TYPE}] - {description} (line ~143, commit scope).
  • respond-to-review: # Change summary: {TICKET}: {description} (line ~84).
  • create-ticket: # {ticket_id}: {title} (line ~139) — uses {ticket_id} literally, which silently produces # 461: Foo on GitHub-style projects (missing the # sigil). Latent bug.

#461 introduced ticket_ref to get-session-context as the canonical display form. Now that it exists, all five sites should consume it.

Context

ticket_ref is the rendered display form: '#' + ticket_id when ticket_ref_prefix == '#', equal to ticket_id for Jira-style IDs, and null when no ticket is in session. It is exposed by get-session-context and consumed by create-pr (for the body's Closes line, shipped in #461). Heading sites are the next-largest cluster of consumers.

Solution

  1. Reader sites (summarize-change, review-change ×2 templates, respond-to-review): in the step that calls get-session-context, add ticket_ref to the obtained fields.
  2. Writer site (create-ticket): after step 5 assigns the new ticket's ticket_id, compute ticket_ref using the same logic as get-session-context: if ticket_ref_prefix == '#', then ticket_ref = '#' + ticket_id; otherwise ticket_ref = ticket_id. Both inputs are already in scope from step 1; no new lookup is needed. get-session-context is not the source here because the ticket ID doesn't exist when create-ticket is invoked.
  3. Replace the implicit display-form placeholder with {ticket_ref}:
    • summarize-change: # {TICKET} {title}# {ticket_ref} {title}.
    • review-change (both scopes): {TICKET}{ticket_ref}.
    • respond-to-review: {TICKET}{ticket_ref}.
    • create-ticket: # {ticket_id}: {title}# {ticket_ref}: {title}. Fixes the latent bug where the heading on GitHub-style projects was missing the # sigil.
  4. Document the null case for each reader site: when ticket_ref is null (no ticket on the branch), omit the {ticket_ref} portion so the heading reads naturally without it. Not applicable to create-ticket, which always assigns or auto-generates an ID.
  5. Where the skill has a worked example or narrative, update it to reference ticket_ref rather than implicitly hand-rolling #.

YAML frontmatter (ticket_id: '461') remains unchanged — frontmatter is machine-readable and uses the storage form. File paths (tickets/{ticket_id}/) also remain unchanged — # is invalid in paths.

Out of scope

  • Other display contexts not enumerated above. They're migrated as they're identified.
  • Title-prefix decoration for PRs/commits (e.g., pr.ticket_prefix with {id} template substitution). Tracked separately.

Acceptance criteria

  • All five sites use {ticket_ref} in their heading templates. The four reader sites (summarize-change, review-change, respond-to-review) obtain it from get-session-context; create-ticket computes it locally as '#' + ticket_id when ticket_ref_prefix == '#' (else ticket_id) after the remote ticket is assigned.
  • Each reader site documents the null case (no ticket → heading without the {ticket_ref} portion).
  • create-ticket's heading produces # #461: Foo on GitHub-style projects (where it previously produced # 461: Foo).
  • Worked examples and narrative in each skill reference ticket_ref rather than hand-rolled # prepending.

Depends on

Metadata

Metadata

Labels

featureAdded or improved external functionalityscope:agents

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions