feat(.claude): pr-roadmap-link skill — lock slug at PR-create time#129
Merged
Conversation
Companion to the `roadmap-tracking` skill (which picks a slug at feature START). This new skill fires at PR-CREATE time and lays down two attribution mechanisms per spec §3.3: 1. `Roadmap-Item: <slug>` trailer at the bottom of the PR body 2. `roadmap/<slug>` label on the PR So when the operator later runs `release-promote.mjs --roadmap-item-slug` for the release that ships the PR, they can read the slug off the PR directly instead of reconstructing it from git history. Triggers on "open PR" / "create PR" / "gh pr create" phrases or when an agent is about to invoke `gh pr create --base next` / `--base main`. Skips for docs/chore/refactor/style branches, when the user says "no roadmap" / "untracked", or when the PR body already carries the trailer. Skill flow: 1. Gathers context in parallel (branch name, commits, diff, public roadmap items, .claude/session-roadmap-slug if the `roadmap-tracking` skill stashed one). 2. Synthesizes a recommendation in priority order (session-slug stash, branch-name substring match, commit-message hint, no recommendation). 3. AskUserQuestion with recommendation first (link existing / pick from list / create new / skip). 4. On link: injects trailer + creates `roadmap/<slug>` label if missing + adds label to `gh pr create --label` args. 5. After PR creation, surfaces a one-line operator instruction: "When you cut the release, pass `--roadmap-item-slug <slug>`." Wiring assumptions: gh CLI authenticated, repo is TheCodeSaiyan/StarStats (hardcoded for now), `Roadmap-Item:` trailer format matches release-promote.mjs's regex. Pairs with memory entry [[release-slug-per-release]] and the existing [[roadmap-tracking]] skill.
6 tasks
ntatschner
pushed a commit
that referenced
this pull request
May 28, 2026
The roadmap-tracking chain ends with the operator typing
`--roadmap-item-slug <slug>` on the release-promote command. That's
the last manual step — reconstruct "which roadmap item did this
release ship work for?" from human memory at release time, after
the fact. Fragile across reviewer hand-offs.
Replace that manual lookup with discovery: scan PRs merged between
the previous track tag and the release's target SHA, extract their
`roadmap/<slug>` labels (planted by the `pr-roadmap-link` skill at
PR-create time), and use the unique slug as the tag annotation
automatically.
Resolution priority (printed at promote time so the operator sees
the chosen path):
1. Explicit `--roadmap-item-slug <slug>` — wins, no discovery.
2. `--no-auto-slug` flag — skip discovery; unsigned tag.
3. Auto-discover (default):
- 0 slugs in range → no annotation (status quo)
- 1 slug → use it; log the discovery source
- >1 slugs → fail loud; demand explicit choice
Discovery details:
- Finds the previous track tag via `previousTrackTagBelow`
(channel-agnostic within the same track; rc.2 finds beta.2,
new minor's alpha.1 finds previous live).
- `gh pr list --state merged --base next --search merged:>{date}
--json number,mergeCommit,labels` — coarse date filter, then
narrows by `git merge-base --is-ancestor` to PRs whose merge
commit is in (prevTag, targetSha].
- `parseSlugsFromPrLabels` extracts unique `roadmap/<slug>`
suffixes from the PR labels.
- Network/auth failures degrade gracefully: any gh error skips
discovery (returns null), and the caller treats that the same
as "no slug to annotate" — release never blocks on the
discovery hop.
Two new pure functions exported for testing:
- `parseSlugsFromPrLabels(prs)` — dedupes slugs across PRs;
tolerates both gh's object-label shape and string-label shape.
- `previousTrackTagBelow(tagList, track, currentVersion)` —
track-scoped, channel-agnostic; returns the highest tag of the
same track strictly below currentVersion.
13 new tests cover the pure parts; the IO glue is exercised via
the existing live release flow.
Pairs with the `pr-roadmap-link` skill (PR #129). Together they
close the loop: pick slug at feature start → confirm at PR time →
auto-flow at release time → server records the channel transition.
The operator's only remaining decision is "is this PR tracked, and
which slug?" — exactly the kind of intent only a human knows.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
.claude/skills/pr-roadmap-link/SKILL.md— fires at PR-create time, asks "which roadmap item does this PR ship work for?", injectsRoadmap-Item: <slug>trailer +roadmap/<slug>label per spec §3.3.roadmap-trackingskill (PR feat(roadmap): operator tooling — drafts publisher, project normalizer, auto-publish, tracking skill #113) which picks the slug at feature START. This new skill confirms / locks the slug at PR-CREATE time so the slug travels with the PR for later release attribution.Why
After we deleted
vars.ROADMAP_ITEM_SLUG(placeholder was stale; see memory entryrelease-slug-per-release), the convention became: pass--roadmap-item-slug <slug>torelease-promote.mjsper release. But the slug decision was being deferred to release time, which makes the operator reconstruct "which roadmap item did this release ship?" from git history at release time — fragile, especially across reviewer hand-offs.Locking the slug onto the PR via the spec-defined trailer + label means the operator just reads it off the PR being shipped. Two-sentence summary at release time becomes one curl.
Trigger semantics
Fires when an agent is about to
gh pr create --base next(or--base main), unless:docs//chore//style//refactor//release//revert/chore:/docs:/style:/test:/ci:Roadmap-Item:trailer (idempotent re-runs)Interaction map
superpowers:brainstorming(feature scoping)roadmap-tracking(slug at feature start — writes.claude/session-roadmap-slug)commit-commands:commit-push-pr/superpowers:finishing-a-development-branch/ manualgh pr createTest plan
namefield matches dir name (pr-roadmap-link)description:includes explicit trigger + skip phrasesRoadmap-Item: <slug>exactly (two newlines before, nothing on the trailer line)No runtime impact; safe to merge before / after the rest of the in-flight PRs (#128 etc.). Only affects how future PRs are framed.