Story Statement
As a maintainer merging any open PR
I want origin/main to be green on the code-host-routing.test.ts AC4 full-catalog audit
So that every PR's merge-ref CI reflects that PR's own quality instead of inheriting a failure from main
Where: packages/knowledge-hub/dataset/.skills/capability/assess-cost/SKILL.md (Step 8 wording) vs. the audit regex in packages/knowledge-hub/src/conformance/code-host-routing.test.ts (PR_FROM_PM_TOOL).
Epic Context
Parent Epic: none — cross-cutting CI/gate regression, collision between two independently merged stories.
Status: Todo
Priority: P0 (Must-Have) — main is red, so every open PR's pull_request merge ref is red.
Status Workflow
- Todo: Story is created but not yet refined
- Refined: Story is detailed, estimated, and ready for development
- In Progress: Story is actively being developed
- Done: Story delivered and accepted
User Value
User Benefit: a red check on a PR means something about that PR again.
Business Impact: unblocks the merge gate for the whole open-PR set; removes the "is this mine or main's?" triage cost from every review.
Visible UI Value: n/a (CI) — demonstrable as a green CI check on main and on any rebased PR.
Rough Sizing
Story Points: XS(1)
Confidence: High
Reasoning: one sentence to reword (plus its .claude/skills/ mirror), or one tempering clause in the regex. The decision of WHICH is the only open question.
Initial Scope
Likely In Scope
- Resolve the failure: either reword
assess-cost/SKILL.md Step 8 so the PR read is routed explicitly, or temper PR_FROM_PM_TOOL for the the PM tool / code host (both-sides-named) shape.
- Keep both copies in step (dataset source +
.claude/skills/pair-capability-assess-cost/SKILL.md) per the mirror-equality guard.
Likely Out of Scope
Open Questions
- Is
from the PM tool / code host a genuine conflation (fix the prose) or a legitimate both-sides-named read the audit should tolerate (fix the regex)? The regex already tempers on code[- ]host appearing INSIDE the gap; here it appears after the PM tool, so the temper does not fire.
Acceptance Criteria
AC1 — the audit is green on main
Given origin/main at or after the fix
When pnpm --filter @pair/knowledge-hub test runs
Then code-host-routing.test.ts → "AC4 — no skill doc in the catalog conflates a PR with the PM tool (full-catalog grep)" passes with an empty offender list.
AC2 — the routing intent is preserved, not silenced
Given whichever side is changed
When the fix lands
Then assess-cost Step 8 still states that the merged-PR list is read from the code host and the item state from the PM tool, and the audit still fails on a genuine conflation (a regression case pins whichever shape was tempered).
AC3 — both copies stay in step
Given the dataset SKILL.md is edited
When the mirror guards run
Then .claude/skills/pair-capability-assess-cost/SKILL.md matches, and skills:conformance / docs:staleness stay green.
Definition of Done Expectations
Dependencies
Story Dependencies: #236 (introduced the audit, landed as ADR-018), #388/#399 (introduced the assess-cost report-mode wording).
Epic Dependencies: none.
Notes
Found during the independent review of PR #411 (story #407) — not a defect of that PR, whose own head is green on every gate locally and merges cleanly into main.
Failure, verbatim (build job → @pair/knowledge-hub#test):
FAIL src/conformance/code-host-routing.test.ts > code-host / PM-tool split — no skill assumes the two coincide (#236, AC4 audit)
> AC4 — no skill doc in the catalog conflates a PR with the PM tool (full-catalog grep)
AssertionError: expected [ 'capability/assess-cost/SKILL.md' ] to deeply equal []
Offending sentence — capability/assess-cost/SKILL.md, Step 8:
Read the window's merged PRs — closed PRs whose merge date falls inside the window — from the PM tool / code host
First red commit: f1e581b7 (#388). Still red at 768e8a25 (#391) and 8f8956bd (#408) — i.e. three merges have landed on a red main.
Why nothing caught it pre-merge: the audit is a full-catalog grep, so it is only tripped by the combination of #236's regex and #388's prose — neither PR's own branch contained both. File-level disjointness analysis does not catch it; this is the same behavioural-collision class PR #411's body flags for its own #406 coupling.
Story Statement
As a maintainer merging any open PR
I want
origin/mainto be green on thecode-host-routing.test.tsAC4 full-catalog auditSo that every PR's merge-ref CI reflects that PR's own quality instead of inheriting a failure from
mainWhere:
packages/knowledge-hub/dataset/.skills/capability/assess-cost/SKILL.md(Step 8 wording) vs. the audit regex inpackages/knowledge-hub/src/conformance/code-host-routing.test.ts(PR_FROM_PM_TOOL).Epic Context
Parent Epic: none — cross-cutting CI/gate regression, collision between two independently merged stories.
Status: Todo
Priority: P0 (Must-Have) —
mainis red, so every open PR'spull_requestmerge ref is red.Status Workflow
User Value
User Benefit: a red check on a PR means something about that PR again.
Business Impact: unblocks the merge gate for the whole open-PR set; removes the "is this mine or main's?" triage cost from every review.
Visible UI Value: n/a (CI) — demonstrable as a green
CIcheck onmainand on any rebased PR.Rough Sizing
Story Points: XS(1)
Confidence: High
Reasoning: one sentence to reword (plus its
.claude/skills/mirror), or one tempering clause in the regex. The decision of WHICH is the only open question.Initial Scope
Likely In Scope
assess-cost/SKILL.mdStep 8 so the PR read is routed explicitly, or temperPR_FROM_PM_TOOLfor thethe PM tool / code host(both-sides-named) shape..claude/skills/pair-capability-assess-cost/SKILL.md) per the mirror-equality guard.Likely Out of Scope
assess-costreport mode (assess-cost report mode — deploy/billing telemetry integration for deploy-match #399 territory).Open Questions
from the PM tool / code hosta genuine conflation (fix the prose) or a legitimate both-sides-named read the audit should tolerate (fix the regex)? The regex already tempers oncode[- ]hostappearing INSIDE the gap; here it appears afterthe PM tool, so the temper does not fire.Acceptance Criteria
AC1 — the audit is green on
mainGiven
origin/mainat or after the fixWhen
pnpm --filter @pair/knowledge-hub testrunsThen
code-host-routing.test.ts→ "AC4 — no skill doc in the catalog conflates a PR with the PM tool (full-catalog grep)" passes with an empty offender list.AC2 — the routing intent is preserved, not silenced
Given whichever side is changed
When the fix lands
Then
assess-costStep 8 still states that the merged-PR list is read from the code host and the item state from the PM tool, and the audit still fails on a genuine conflation (a regression case pins whichever shape was tempered).AC3 — both copies stay in step
Given the dataset
SKILL.mdis editedWhen the mirror guards run
Then
.claude/skills/pair-capability-assess-cost/SKILL.mdmatches, andskills:conformance/docs:stalenessstay green.Definition of Done Expectations
main)Dependencies
Story Dependencies: #236 (introduced the audit, landed as ADR-018), #388/#399 (introduced the
assess-costreport-mode wording).Epic Dependencies: none.
Notes
Found during the independent review of PR #411 (story #407) — not a defect of that PR, whose own head is green on every gate locally and merges cleanly into
main.Failure, verbatim (
buildjob →@pair/knowledge-hub#test):Offending sentence —
capability/assess-cost/SKILL.md, Step 8:First red commit:
f1e581b7(#388). Still red at768e8a25(#391) and8f8956bd(#408) — i.e. three merges have landed on a redmain.Why nothing caught it pre-merge: the audit is a full-catalog grep, so it is only tripped by the combination of #236's regex and #388's prose — neither PR's own branch contained both. File-level disjointness analysis does not catch it; this is the same behavioural-collision class PR #411's body flags for its own #406 coupling.