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
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-ticketwritesticket_url— so the field staysnulleven after a full URL is supplied once, and later sessions can't reuse it.Context
ticket_urlfield, seeded tonullat compose time and written only viaderive-session-context --set-ticket-url.design-and-plan,review-branch, and other ticket-consuming skills resolve a URL in-context but never persist it.#idbecausegh issue viewreturns the URL; Jira has no equivalent path.scm,project_slug,default_branch) are already authored inpreferences.yamland cached in the manifest. The base URL follows that established pattern.Proposed solution
Add a
ticket.base_urlpreference (org-stable, e.g.https://org.atlassian.net/browse/) as the source of truth, surfaced into the branch manifest asticket_base_urlso 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 storedticket_url, else constructbase_url + stored ticket id. Persist the full URL via--set-ticket-urlwhenever 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 viewand needs no base URL. The base-URL mechanism targets platforms where a URL can't otherwise be reconstructed.pr_urlshares the same null-seed pattern but is out of scope here.Acceptance criteria
Must have
ticket.base_urlis supported inpreferences.yaml(schema and resolution) and surfaced in the branch manifest asticket_base_url.ticket_url, else constructed from base plus stored ticket id.ticket_urlregardless of resolution path (full URL, bare id,gh-fetch, or no-arg construction).ticket.base_urlset.ticket-source-resolution.mdare updated forticket.base_url, including usage examples.