Skip to content

Resolve and persist ticket URLs for bare or omitted references #888

Description

@williamthorsen

Problem

Resolving a ticket on a non-GitHub platform (Bitbucket SCM with Jira issues) requires pasting the full ticket URL into every skill invocation: a bare ticket id can't be expanded to a URL because the org-stable base URL is stored nowhere. Separately, resolved ticket URLs are never persisted to the branch manifest — only create-ticket writes ticket_url — so the field stays null even after a full URL is supplied once, and later sessions can't reuse it.

Context

  • The branch manifest already has a ticket_url field, seeded to null at compose time and written only via derive-session-context --set-ticket-url.
  • design-and-plan, review-branch, and other ticket-consuming skills resolve a URL in-context but never persist it.
  • GitHub works from a bare #id because gh issue view returns the URL; Jira has no equivalent path.
  • Preference-derived values (scm, project_slug, default_branch) are already authored in preferences.yaml and cached in the manifest. The base URL follows that established pattern.

Proposed solution

Add a ticket.base_url preference (org-stable, e.g. https://org.atlassian.net/browse/) as the source of truth, surfaced into the branch manifest as ticket_base_url so skills read it from the interface they already consult — not hand-set in the manifest, which would create a second source of truth that can drift from the preference.

Resolve a ticket URL in this order within ticket-consuming skills: a full URL given is used directly; a bare id is expanded to base_url + id; with nothing given, use the manifest's stored ticket_url, else construct base_url + stored ticket id. Persist the full URL via --set-ticket-url whenever it resolves by any path, so later sessions reuse it with no argument. An explicitly supplied URL takes precedence over a constructed one.

GitHub is unaffected: it continues to resolve via gh issue view and needs no base URL. The base-URL mechanism targets platforms where a URL can't otherwise be reconstructed. pr_url shares the same null-seed pattern but is out of scope here.

Acceptance criteria

Must have

  • ticket.base_url is supported in preferences.yaml (schema and resolution) and surfaced in the branch manifest as ticket_base_url.
  • A bare ticket reference passed to a ticket-consuming skill resolves to a full URL via the base.
  • With no ticket reference, a skill resolves the URL from the manifest — stored ticket_url, else constructed from base plus stored ticket id.
  • A successfully resolved ticket URL is persisted to the manifest ticket_url regardless of resolution path (full URL, bare id, gh-fetch, or no-arg construction).
  • An explicitly supplied URL takes precedence over a constructed one.
  • GitHub resolution continues to work without ticket.base_url set.
  • New and modified behavior is covered by tests.
  • Documentation, help text, the preferences schema, and ticket-source-resolution.md are updated for ticket.base_url, including usage examples.

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