You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#372 (PR #405) ships the coverage-baseline ratchet and documents it in the adopter-facing KB — the flag, the push-not-PR trigger, the bot-PR landing, the credential. But the capability is pair-internal, and nothing tells an adopter so:
the logic lives in packages/knowledge-hub/src/tools/coverage-baseline-ratchet.ts, not among the shipped provider-agnostic assets (coverage-gate.sh, tier-resolve.sh);
/pair-capability-setup-gates never asks about the nested Coverage baseline commit-back flag, never records it, and never emits the CI step.
So an adopter who sets Coverage baseline commit-back: enabled gets a silent no-op — the worst shape of failure for an opt-in: the config says on, the docs say what it does, nothing happens, and nothing complains.
Found by the independent review of PR #405 (finding M4). #405 closes the honesty gap by stating the pair-internal scope in the guideline and the config example. This story closes the capability gap.
Scope
Ship the ratchet as a provider-agnostic asset alongside coverage-gate.sh, or define the extension point through which an adopter's pipeline invokes it. The decision matters: coverage-gate.sh is shell and provider-agnostic by design, whereas the ratchet is a TypeScript module in a pair-internal package — porting versus exposing is an ADR-worthy call, not an implementation detail.
/pair-capability-setup-gates: ask about the nested flag (only when the parent Coverage guardrail is enabled), record it, and emit the step when it is on.
#372's own AC set is about the ratchet's behaviour (monotonic, terminating, PR-not-push, degrade-to-warning), and all six are met. The adopter path is a distinct deliverable with its own decision (asset vs extension point) and its own surface (setup-gates interview + generated pipeline). Widening #372 to cover it would have meant editing setup-gates/SKILL.md, a file two currently-parked PRs (#389, #390) already modify — a three-way contention for a one-line change, in a PR whose disjointness is a stated business rule.
The framework default stays disabled throughout. Nothing here turns the ratchet on for anyone; it makes turning it on actually do something.
Classification
risk:yellow · cost:green · coupling: not assessed
Matrix — per dimension
Dimension
Tier
Source
Note
Service/domain criticality
yellow
KB default
no Criticality Table declared ⇒ Medium (D21)
Change/diff risk
yellow
file ownership
setup-gates/SKILL.md is modified by #389and#390; the guideline/asset pair by #405
Business impact
yellow
subdomain class
Integration & Process Standardization (Supporting) — but this is the adopter-facing surface, so a silent no-op is a credibility cost, not just an internal one
Security relevance
yellow
credential
the adopter must provision a write credential; documenting the wrong scope is an authorization error on their repo, not ours
Coupling balance
not assessed
absent
decided by T-1 (asset vs extension point)
Acceptance Criteria
Given-When-Then:
Given an adopter with Coverage guardrail: enabled When/pair-capability-setup-gates runs Then it asks about Coverage baseline commit-backonly then — the nested flag is never offered for a guardrail that is off
Given the adopter answers enabled When the pipeline is generated Then the commit-back step is emitted, and the generated step is the same shape pair runs — not a second implementation that can drift from it
Given the adopter answers disabled, or is never asked When the pipeline is generated Then no step is emitted and behaviour is byte-identical to today
Default stays disabled everywhere. This story makes enabling it work; it turns it on for nobody.
One implementation, not two. Whatever mechanism T-1 chooses, the adopter's step and pair's own step must run the same logic. A ported copy is a drift source.
Least privilege documented as the adopter's own: contents: write + pull requests: write, no protection bypass. The credential lives in their repo, so the scope is guidance, not configuration we control.
Adopter's base branch is protected — the bot-PR shape already handles it; the generated step must not assume an unprotected base.
Adopter's CI is not GitHub Actions — the guideline is provider-agnostic; state plainly what is Actions-specific rather than implying portability the step does not have.
Definition of Done
All acceptance criteria implemented and verified
T-1's decision recorded as an ADR (it changes what pair ships, not just how)
Conformance covers the caveat removal, so a stale caveat cannot survive
T-1 gates everything: whether the step invokes a shipped asset or a declared entry point changes what T-3 asks and what T-4 writes. T-5 is independent of the mechanism but must not land before T-2, or the caveat is removed while still true.
Problem
#372 (PR #405) ships the coverage-baseline ratchet and documents it in the adopter-facing KB — the flag, the push-not-PR trigger, the bot-PR landing, the credential. But the capability is pair-internal, and nothing tells an adopter so:
packages/knowledge-hub/src/tools/coverage-baseline-ratchet.ts, not among the shipped provider-agnostic assets (coverage-gate.sh,tier-resolve.sh);/pair-capability-setup-gatesnever asks about the nestedCoverage baseline commit-backflag, never records it, and never emits the CI step.So an adopter who sets
Coverage baseline commit-back: enabledgets a silent no-op — the worst shape of failure for an opt-in: the config says on, the docs say what it does, nothing happens, and nothing complains.Found by the independent review of PR #405 (finding M4). #405 closes the honesty gap by stating the pair-internal scope in the guideline and the config example. This story closes the capability gap.
Scope
coverage-gate.sh, or define the extension point through which an adopter's pipeline invokes it. The decision matters:coverage-gate.shis shell and provider-agnostic by design, whereas the ratchet is a TypeScript module in a pair-internal package — porting versus exposing is an ADR-worthy call, not an implementation detail./pair-capability-setup-gates: ask about the nested flag (only when the parentCoverage guardrailis enabled), record it, and emit the step when it is on.setup-gates/SKILL.md:199(both corpora) that reads "automated commit-back is story Coverage baseline auto commit-back — CI persists/ratchets the baseline (opt-in, on top of #282) #372" — true until [US-372] feat: coverage baseline auto commit-back — monotonic ratchet as a bot PR, opt-in and off by default #405 merges, wrong after.tier-aware-pipeline.mdandcoverage-config-example.md(both corpora).contents: write+pull requests: write, no protection bypass) and what happens without it (warning, verdict untouched — AC6 of Coverage baseline auto commit-back — CI persists/ratchets the baseline (opt-in, on top of #282) #372).Why it is not part of #372
#372's own AC set is about the ratchet's behaviour (monotonic, terminating, PR-not-push, degrade-to-warning), and all six are met. The adopter path is a distinct deliverable with its own decision (asset vs extension point) and its own surface (
setup-gatesinterview + generated pipeline). Widening #372 to cover it would have meant editingsetup-gates/SKILL.md, a file two currently-parked PRs (#389, #390) already modify — a three-way contention for a one-line change, in a PR whose disjointness is a stated business rule.Dependencies
setup-gates/SKILL.md, owned by [US-236] feat: code host separate from PM tool (WoW override) — GitHub + Linear reference case #389 and [US-234] feat: PR state flow (gate≠review) + pair review as required check #390 while they are open. Do not enter a batch before those merge.Notes
The framework default stays
disabledthroughout. Nothing here turns the ratchet on for anyone; it makes turning it on actually do something.Classification
risk:yellow·cost:green· coupling: not assessedMatrix — per dimension
setup-gates/SKILL.mdis modified by #389 and #390; the guideline/asset pair by #405Acceptance Criteria
Given-When-Then:
Given an adopter with
Coverage guardrail: enabledWhen
/pair-capability-setup-gatesrunsThen it asks about
Coverage baseline commit-backonly then — the nested flag is never offered for a guardrail that is offGiven the adopter answers
enabledWhen the pipeline is generated
Then the commit-back step is emitted, and the generated step is the same shape pair runs — not a second implementation that can drift from it
Given the adopter answers
disabled, or is never askedWhen the pipeline is generated
Then no step is emitted and behaviour is byte-identical to today
Given the ratchet is reachable by an adopter
When they read the guideline and the config example
Then the pair-internal caveats added by Coverage baseline auto commit-back — CI persists/ratchets the baseline (opt-in, on top of #282) #372 are gone — a caveat that outlives the limitation it describes is worse than none
Given
setup-gates' NotesWhen read after Coverage baseline auto commit-back — CI persists/ratchets the baseline (opt-in, on top of #282) #372 merges
Then the stale "automated commit-back is story Coverage baseline auto commit-back — CI persists/ratchets the baseline (opt-in, on top of #282) #372" line is corrected — it is true only until that merge
Given the adopter has not provisioned
COVERAGE_RATCHET_TOKENWhen the generated step runs
Then it warns naming the missing credential and the gate's verdict is unchanged — Coverage baseline auto commit-back — CI persists/ratchets the baseline (opt-in, on top of #282) #372's AC6 must hold on the generated step too, not only on pair's own
Business Rules
disabledeverywhere. This story makes enabling it work; it turns it on for nobody.contents: write+pull requests: write, no protection bypass. The credential lives in their repo, so the scope is guidance, not configuration we control.Edge Cases
Definition of Done
pnpm quality-gategreen; PR followspr-template.mdTask Breakdown
setup-gates: the nested question, gated on the parent flag, recorded in the adoptionsetup-gates: emit the step when enabled; nothing when not#372noteDependency Graph
T-1 gates everything: whether the step invokes a shipped asset or a declared entry point changes what T-3 asks and what T-4 writes. T-5 is independent of the mechanism but must not land before T-2, or the caveat is removed while still true.
AC Coverage