Skip to content

[US-351] feat: bootstrap Phase 3.6 — guided authoring of the Criticality Table / Overrides delta - #422

Open
rucka wants to merge 7 commits into
mainfrom
feature/US-351-bootstrap-criticality
Open

[US-351] feat: bootstrap Phase 3.6 — guided authoring of the Criticality Table / Overrides delta#422
rucka wants to merge 7 commits into
mainfrom
feature/US-351-bootstrap-criticality

Conversation

@rucka

@rucka rucka commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

PR Information

PR Title: [US-351] feat: bootstrap Phase 3.6 — guided authoring of the Criticality Table / Overrides delta
Story/Epic: #351 — Guided authoring of the Criticality Table / Overrides delta in bootstrap/quickstart (parent epic #208)
Type: Feature
Priority: P2 (Nice-to-Have)
Labels: risk:yellow

Summary

What Changed

Adds a new /pair-process-bootstrap Phase 3.6: Classification Delta, positioned immediately after Phase 3.5 (Domain Modeling) so the candidate rows for tech/risk-matrix.md's ## Criticality Table are proposed from the subdomains/bounded contexts Phase 3.5 just mapped, rather than asked cold.

  • Step 3.6.0 — Whole-phase precondition: checks the quality model is installed (skipped — quality model not installed) and then that the file parses; a malformed risk-matrix.md skips both steps (skipped — file malformed) and continues at Phase 4 — the file is never rewritten over a parse the phase does not trust, and a write into it would be silently inert (§6 falls back to KB defaults entirely).
  • Step 3.6.1 — Criticality Table (optional): one up-front "author the table at all?" gate (a list to prune, not a form to complete), then one recommendation at a time for the rows the developer kept. Rows are keyed by what the read side resolves — the deployable owning the touched files — with bounded contexts/subdomains supplying candidate names and recommended values. Both prompts disclose that a service left out of an existing table resolves to conservative High. Values are recommended by the H/M/L criterion quality-model §6 owns — the step applies it, never re-defines it — including on the degraded (no domain model) path.
  • Step 3.6.2 — Overrides (optional): the two override families (thresholds §3.1, per-tier reviewer counts/SLAs §4) asked separately, each recommending the KB default; the reviewer/SLA prompt renders the Review enforcement value Step 3.2 recorded instead of assuming one.
  • Both steps are idempotent (skip if the section already exists), write only when confirmed, using the same propose-then-write-if-confirmed / config-registry pattern /pair-capability-classify uses for its ## Tag Projection self-write — not routed through /pair-capability-record-decision. The one deliberate divergence (a decline is not recorded, unlike classify's Active: none) is stated in the phase and in the ADL.
  • Quick mode asks nothing and writes nothing here: no safe default exists for a project's criticality map, so the resolved default is "no delta, KB defaults apply" (declared in quick-mode-defaults.md, cascade tier because nothing is resolved from any tier).
  • Step 4.3's summary gains a per-section Classification: line (criticality: … , overrides: …, or a whole-phase skipped — quick mode | file malformed | quality model not installed).
  • Quality model §6 owns the read side, in three rules: the Key namespace (what a diff resolves to as its service/domain — the deployable / workspace / top-level path scope), its multi-key resolution (a change touching several deployables takes the highest criticality among them, an unlisted one contributing the conservative High — without it the tier flips between runs on identical code, since tier = max of dimensions), its refinement-time resolution (the story's declared scope; a story naming no deployable falls to the file-absent default, not to unlisted⇒High), and Choosing a value (the H/M/L criterion, moved here from the skill so both authoring routes reason the same way). §6's two delta bullets also point at the guided path. Root, dataset mirror, website mirror, and risk-matrix-example.md aligned.
  • Skill version bumped 0.6.0 → 0.7.0 (new phase + changed output shape + touched sub-doc).

Why This Change

tech/risk-matrix.md holds up to three independent sections (quality-model §6). ## Tag Projection already had a guided authoring path (/pair-capability-classify, self-proposed on first run). The other two — ## Criticality Table and ## Overrides — had none: a project could only hand-copy them from risk-matrix-example.md. This closes that gap, at the one point in the flow where a domain model already exists to propose rows from — cheaper and more accurate than asking cold, and strictly non-blocking: the file stays optional by design (D21), and no Definition of Done may come to require these sections.

Story Context

User Story: As a team bootstrapping a pair project, I want a guided flow to author the ## Criticality Table and ## Overrides delta of tech/risk-matrix.md, so that the two adoption-delta sections that shape classification have a guided authoring path instead of being hand-copied from the example asset.

Acceptance Criteria: All 7 ACs covered —

  1. Guided question-set offered after Phase 3.5 for both sections, one recommendation at a time.
  2. Sections written via the same propose-then-write-if-confirmed pattern as classify's Tag Projection self-write, not through /pair-capability-record-decision.
  3. Decline/skip ⇒ nothing written, degrades to KB defaults, non-blocking.
  4. Already-authored sections are detected and never re-proposed (idempotent).
  5. Phase 3.5 output (mapped subdomains/contexts) drives the candidate rows, each with a recommended criticality and reason; developer confirms/edits.
  6. Phase 3.5 skipped or empty ⇒ degrade to repository-derived candidates; an empty answer stays valid (and writes no section).
  7. $mode: quick ⇒ asks nothing, writes nothing, reported once in the Step 4.3 summary.

Changes Made

Implementation Details

  • New Phase 3.6 in .claude/skills/pair-process-bootstrap/SKILL.md (+ dataset mirror): Steps 3.6.0 (parse precondition), 3.6.1 (Criticality Table), 3.6.2 (Overrides), each with check → skip → act → verify.
  • Reachability: Phase 3.5's exits (not installed / already populated / normal completion) and Step 3.2's already-configured skip route into 3.5/3.6 instead of jumping to Phase 4.
  • Quick-mode delta declared in quick-mode-defaults.md (+ dataset mirror).
  • Idempotency + graceful-degradation sections extended: 7th "detecting prior work" check (authored sections only — a decline is deliberately not recorded), three whole-phase skip reasons.
  • Quality model §6: Key namespace rule + pointers to the guided path (root, dataset, quality-model.mdx); risk-matrix-example.md states the keying rule in-file.
  • Discoverability: skills-guide.md § Adoption Files gains the tech/risk-matrix.md row (two writers, section ownership as the invariant); quality-gates-configuration.mdx names the guided path.
  • Two ADLs recorded, each backed by conformance assertions.
  • Record kept in sync with the code: the positioning ADL's Decision 1 now states what shipped (rows keyed by the deployable, catalogs supplying candidate names/values, an empty answer valid while a rowless table is refused) and cross-references the keying ADL; AC6's wording on Guided authoring of the Criticality Table / Overrides delta in bootstrap/quickstart #351 amended for the same reason.

Files Changed

  • Modified — skill (both copies, version 0.6.00.7.0):
    • .claude/skills/pair-process-bootstrap/SKILL.md · packages/knowledge-hub/dataset/.skills/process/bootstrap/SKILL.md
    • .claude/skills/pair-process-bootstrap/quick-mode-defaults.md · packages/knowledge-hub/dataset/.skills/process/bootstrap/quick-mode-defaults.md
  • Modified — knowledge base (root + dataset mirror):
    • .pair/knowledge/guidelines/quality-assurance/quality-model.md (§6: key namespace, multi-deployable + refinement-time resolution, Choosing a value criterion, guided-path pointers)
    • .pair/knowledge/assets/risk-matrix-example.md · .pair/knowledge/assets/bootstrap-checklist.md
    • .pair/knowledge/how-to/02-how-to-complete-bootstrap-checklist.md · .pair/knowledge/skills-guide.md
  • Modified — website:
    • apps/website/content/docs/reference/quality-model.mdx · apps/website/content/docs/reference/quality-gates-configuration.mdx
  • Modified — tests: packages/knowledge-hub/src/conformance/bootstrap.test.ts (comment)
  • Added:
    • .pair/adoption/decision-log/2026-08-11-criticality-delta-is-authored-after-domain-modeling.md
    • .pair/adoption/decision-log/2026-08-11-criticality-rows-are-keyed-by-the-deployable-a-diff-resolves-to.md
    • packages/knowledge-hub/src/conformance/bootstrap-classification-delta.test.ts

Testing

Test Coverage

  • Unit/Conformance Tests: bootstrap-classification-delta.test.ts (933 lines, 57 tests) asserts: phase position and reachability, the parse precondition's ordering/verify/continuation, both steps present, quick-mode delta + cascade tier, no inline schema restatement, write path = classify's propose-then-write-if-confirmed (not /pair-capability-record-decision) with the decline divergence disclosed, idempotency, degradation paths, the key namespace (skill and quality-model §6), the H/M/L recommendation mapping, the unlisted⇒High disclosure inside both prompts, the rendered Review enforcement value, the per-section summary slots + all three whole-phase values, the §6 multi-deployable / refinement-time / criterion-ownership rules, and seven cross-document rot guards (quality-model §5/§6 ×4, classify Step 5, skills-guide.md, how-to-02 Phase 2.6, the positioning ADL's Decision 1).
  • Regression: full @pair/knowledge-hub suite green, incl. check:links.

Test Results

Test Suite: ✅ Passing — 1376/1376 (32 files, @pair/knowledge-hub)
Linting:    ✅ Clean (lint · ts:check · prettier:check · mdlint:check)
Build:      ✅ Passing (@pair/knowledge-hub)
Repo gates: ✅ skills:conformance (41 skills) · docs:staleness (41 skills, 9 commands) · hygiene:check

Testing Strategy

  • Happy Path: Phase 3.5 output present → both sections proposed and written on confirmation.
  • Edge Cases: no distinct services/domains (empty answer ⇒ no section, never a rowless table); risk-matrix.md absent (created with only confirmed sections); malformed file (reported, never rewritten, phase skipped whole); ## Tag Projection already present (left untouched).
  • Quick mode / no-TTY: asks nothing, writes nothing, pinned by dedicated conformance tests.

Quality Assurance

Code Quality Checklist

  • Follows the guided/quick and propose-then-write-if-confirmed conventions established by /pair-capability-classify
  • Schema referenced (quality-model §3.1/§4/§6), never restated inline — asserted by conformance test
  • No debugging code; dataset is the edited source, mirror regenerated; KB root ↔ dataset copies byte-identical

Reviewer Guide

Review Focus Areas

  1. Read-side rules (quality-model §6): the key namespace, the highest-of rule for a change touching several deployables, the refinement-time resolution, and the H/M/L Choosing a value criterion now all live in §6 — confirm the write side (Step 3.6.1) only applies them, and that the criterion has exactly one definition.
  2. Business Logic Validation: all 7 ACs map onto the SKILL.md steps; the two ADLs match the implementation.
  3. Adoption Compliance: the write path genuinely reuses classify's pattern (registry write, not /pair-capability-record-decision) and ## Tag Projection is never touched.
  4. Idempotency & reachability: a re-run on an authored file proposes nothing per section; no exit path of Phase 3.5 / Step 3.2 jumps over Phase 3.6.

Testing the Changes

cd packages/knowledge-hub
pnpm test           # full suite incl. check:links — expect 1376 passed
pnpm lint && pnpm ts:check

Key Test Scenarios

  1. Fresh project, complete Phase 3.5, observe Phase 3.6 propose rows keyed by deployable, with a recommended value and reason.
  2. Re-run bootstrap on a project whose risk-matrix.md already has ## Criticality Table — verify no re-proposal; on a malformed file — verify the whole phase skips and nothing is written.
  3. Run $mode: quick — verify zero questions asked and Classification: skipped — quick mode in the Step 4.3 summary.

Dependencies & Related Work

Related PRs


Type emphasis: Feature → user impact + technical decisions.

rucka added 4 commits August 11, 2026 08:18
…on delta

- Phase 3.6 exists between Phase 3.5 and Phase 4, one step per owned section
- rows proposed from the 3.5 domain model, repo-derived fallback, empty valid
- write path = classify's propose-then-write-if-confirmed, never /record-decision
- opt-in: declining writes nothing, no HALT, no DoD requires the sections
- idempotent on an authored file, reports (never rewrites) a malformed one
- quick mode asks nothing and writes nothing; delta declared in quick-mode-defaults
- schema referenced from quality-model 3.1/4/6, never restated inline

RED: 23 failing, 5 negative guards already green.

Refs: #351
…delta

- new Phase 3.6 after 3.5: rows proposed FROM the mapped subdomains/contexts,
  each with a recommended criticality + reason; confirm or edit, never invent
- 3.5 skipped/empty => candidates from the repo (workspaces, deployables);
  no distinct services => single scope; an empty table stays a valid answer
- written with classify's propose-then-write-if-confirmed registry pattern
  (quality-model 5), never through /record-decision; Tag Projection untouched
- opt-in and non-blocking: declining writes nothing, KB defaults apply (D21),
  no HALT added, no DoD may require the sections
- idempotent per section; a malformed risk-matrix.md is reported, not rewritten
- quick mode asks/writes nothing (no delta is the resolved default) — declared
  in quick-mode-defaults.md and in the checklist's deliberately-absent list
- Step 4.3 summary gains a Classification line; mirrors regenerated

GREEN: 28 assertions + 44 pre-existing bootstrap ones.

Refs: #351
…estration flow

- ADL: position after domain modeling, registry write path (not
  /record-decision), quick mode writes no delta; alternatives incl. Step 3.1
  placement and a heuristic quick-mode map, both rejected with reasons
- how-to-02 gains Phase 2.6 pointing at bootstrap Phase 3.6 — the how-to is the
  orchestration flow of record, a phase living only in the skill would be drift
- deliberately NOT added to the how-to Final Quality Checklist: absence of the
  delta is a supported steady state, not an unchecked box

Refs: #351
…aviour

- CI/piped stdin has nothing to interview: bootstrap already downgrades to
  quick, so the phase asks nothing and writes nothing — stated in the phase,
  not left implicit in the global no-TTY rule
- assertion added; mirror regenerated

Refs: #351
@rucka rucka added the risk:yellow Classification: medium risk tier label Aug 11, 2026
@rucka

rucka commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator Author

Verdict

risk:yellow · cost:greenCHANGES-REQUESTED — AC1 is only partly met (Step 3.6.2 asks a compound question), the malformed-file guard sits behind the already-authored skip so a distrusted file can still be written to, and the skill version: was not bumped for a new phase.

Open findings: 11. 3 Major, 7 Minor, 1 Question. 10 are actionable in this PR; 1 (Q1) is by design and needs only a confirmation.

PR: [#422] · Author: rucka · Reviewer: independent reviewer agent · Date: 2026-08-11 · Story: [US-351] · Type: feature

Classification matrix — per dimension
Dimension Tier Source Note
Service/domain criticality yellow KB default .pair/adoption/tech/risk-matrix.md declares ## Tag Projection only — no ## Criticality Table ⇒ Medium default (D21)
Change/diff risk yellow diff footprint +489/-0, 10 files, markdown + 1 test file, purely additive — but the surface is pair-process-bootstrap, the entry point every new project runs
Business impact yellow subdomain class Setup/onboarding mechanics — Collaborative Workflow (Core); matches repo precedent for skill-authoring work (#411, #404)
Security relevance green manual read (/assess-security n/a) No executable surface beyond a read-only conformance test; no input handling, auth, secrets or output rendering
Coupling balance green manual read (/assess-coupling n/a) No new cross-context integration. One new writer on an existing shared file (tech/risk-matrix.md) — see M6

Tier = max(assessed) = yellow — confirms the story's refinement-time risk:yellow, no raise. Cost = green. Review value is a floor (D17): confirmed, not lowered.

🟡 tier requirements (quality-model §4, KB defaults — no ## Overrides in this repo): 1 reviewer · 1 working day SLA · standard checklist · reviewer approval. Gate checks for 🟡: lint + type + build + unit — all green.

Assessments

Security — Input validation

Verdict: green — the diff adds no input-handling surface; the only executable file reads fixed repo-relative paths.

Details

/pair-capability-assess-security was not run as a separate capability in this review; a manual read of the diff was performed instead, as the degradation path prescribes. Inputs touched: none. bootstrap-classification-delta.test.ts reads six known files via readFileSync(join(__dirname, ...)) with no dynamic path component.

Security — Output handling

Verdict: green — no rendering, encoding or serialization surface in the diff.

Security — Authentication

Verdict: green — not applicable; no auth surface touched.

Security — Authorization

Verdict: green — not applicable; no access-control surface touched.

Security — Introduced vulnerabilities

Verdict: green — 0 introduced, 0 pre-existing on the touched surfaces.

Details

The new phase writes two sections into an adoption file the developer explicitly confirms, and never copies the example asset wholesale. secret-scan on head f397c7b is green.

Cost

Verdict: cost:green — documentation + one conformance test; no infra, no provider, no runtime path.

Details

/pair-capability-assess-cost not run as a capability. The only cost-shaped signal is interview length in guided mode (see m8 — the per-row loop is unbounded by the size of the Phase 3.5 catalog). Quick mode adds zero questions, which the conformance test pins. cost is not projected as a tag in this repo (Active: risk).

Architecture (Coupling)

Verdict: green — no new integration; the one structural change is a second writer on an already-shared file, documented in the ADL but not in the writers registry (M6).

Details
  • Integration strength: shared persistent state (tech/risk-matrix.md) — now written by both /pair-capability-classify (§5, ## Tag Projection) and /pair-process-bootstrap Phase 3.6 (## Criticality Table, ## Overrides). Section ownership is disjoint and stated explicitly in both steps, so the two writers cannot clobber each other.
  • Socio-technical distance: same repo, same corpus — low.
  • Volatility: the schema is owned by quality-model.md §3.1/§4/§6 and referenced, never restated (asserted by test) — the right direction.
  • Balance: acceptable. The residual is discoverability, not coupling: nothing in the writers registry records that this file has two writers (M6), and nothing pins the cross-document anchor the phase relies on (m9).

Details

Findings by severity

Critical (must fix before merge)

  • none.

Major (should fix before merge)

  • packages/knowledge-hub/dataset/.skills/process/bootstrap/SKILL.md:4 (and the regenerated .claude/skills/pair-process-bootstrap/SKILL.md:4) — version: stays 0.6.0 while the PR adds a whole new phase (3.6) with two steps and changes the Output Format shape (a new Classification: line). Both sources of the convention say this is at least a minor bump: skill-conventions/README.md § "Skill version: frontmatter — when to bump""New/removed/renamed argument, algorithm step or phase; changed routing, HALT set, or output shape ⇒ minor" and "a new algorithm step is always at least a minor even when the step is optional" — and apps/website/content/docs/contributing/writing-skills.mdx:211"minor … when a skill gains … a new or removed phase". The same section also states that a change to a sub-doc with no frontmatter (quick-mode-defaults.md, also touched here) bumps the owning SKILL.md. Impact: a caller or adopter cannot tell from the version which copy of bootstrap they have, which is precisely what the convention exists to prevent. Recommendation: bump the dataset frontmatter to 0.7.0 and regenerate the mirror (pair update) — the transform preserves version verbatim, so both copies must read the same value.

  • …/bootstrap/SKILL.md:255-257 (Step 3.6.1 items 1-3) — the malformed-file guard runs after the already-authored skip, so it can be bypassed. Concrete failure: tech/risk-matrix.md contains a ## Criticality Table heading whose table is unparseable. Item 1 matches the heading, item 2 fires (already authored) and hands control to Step 3.6.2 — item 3's parse check is never reached. Step 3.6.2 then finds no ## Overrides, interviews the developer, and writes into the file the phase declared it does not trust, directly contradicting item 3 ("Never rewrite a file over a parse this phase does not trust") and the phase-level degradation entry (SKILL.md:387, which states the rule for Phase 3.6 as a whole). Worse, the write is silently inert: per quality-model §6 a malformed file "falls back to KB defaults entirely… exactly as if the whole file were absent", so the developer's confirmed overrides resolve to nothing while appearing to be recorded. Recommendation: hoist the parse check to a phase-level precondition ahead of both steps' presence checks (e.g. a Step 3.6.0 or the first item of the phase preamble, reporting skipped — file malformed for the whole phase), and add a conformance assertion that the malformed guard precedes the per-section **Check** in the step order.

  • …/bootstrap/SKILL.md:282-286 (Step 3.6.2 item 3, the blockquote) — the prompt bundles both override families into one compound question ("Any path or threshold that should always classify higher than its size suggests? And do the per-tier reviewer counts and SLAs … match how this team actually reviews?"), contradicting AC1 ("one recommendation at a time"), the phase's own Interview style line (SKILL.md:251) and item 3's own prose ("offer the two override families … one recommendation at a time"). Step 3.6.1's blockquote is correctly per-row, so the two steps are also inconsistent with each other. An executor copying the illustrated prompt verbatim — which is what a blockquote in this corpus is for — asks the compound question. The conformance test cannot catch this: bootstrap-classification-delta.test.ts:120-124 only greps the phase body for the literal string one recommendation at a time. Recommendation: split into two blockquotes (threshold overrides, then reviewer-count/SLA overrides), each with its own recommendation and its own confirm/skip, and add an assertion that Step 3.6.2 carries two >-blockquote questions rather than one.

Minor (consider)

  • …/bootstrap/SKILL.md:342 (Output Format, Classification: line) — the line offers a single slot (criticality: N rows, overrides: N | declined | already authored | skipped — quick mode | skipped — file malformed) but both steps carry their outcome into it independently (SKILL.md:272 and :290). A mixed run — criticality authored with 3 rows, overrides already authored, or criticality declined and overrides authored — has no representable form, so the reporter must pick one and drop the other. Suggestion: make the line per-section, e.g. Classification: criticality: 3 rows | overrides: already authored, and keep the whole-phase values (skipped — quick mode, skipped — file malformed) as the only single-slot cases.

  • apps/website/content/docs/reference/quality-gates-configuration.mdx:20 — the Criticality Table / Overrides row's "How to enable" cell still reads as hand-authoring only ("Add the section(s) to tech/risk-matrix.md…"), while the sibling Tag Projection row explicitly names its guided path ("classify writes the risk declaration for you on first run when you confirm"). After this PR the two rows are asymmetric and the user-facing catalog never mentions the capability the story adds — which is exactly the story's success metric ("a project can author both sections without opening risk-matrix-example.md"). docs:staleness cannot catch this (it pins counts and links only). Suggestion: extend that cell with "or answer bootstrap's Phase 3.6, which proposes the rows from your domain model".

  • .pair/knowledge/skills-guide.md:255-262 (§ Adoption Files, and its dataset mirror) — the writers table has no row for tech/risk-matrix.md at all. The omission is pre-existing (/pair-capability-classify writes ## Tag Projection and is unlisted), but this PR makes the file's writer set plural, and the ADL's own consequence — "Any future writer of the same file inherits the same split" — is not discoverable anywhere a reader would look for it. Suggestion: add the row (Classification delta | tech/risk-matrix.md | /pair-capability-classify, /pair-process-review | /pair-capability-classify (Tag Projection), /pair-process-bootstrap (Criticality Table, Overrides)) in the dataset and regenerate.

  • …/bootstrap/SKILL.md:280-286 (Step 3.6.2) — the reviewer-count/SLA question does not say those overrides only bind a merge when Review enforcement: enabled, which bootstrap's own Step 3.2 defaults to disabled (quality-model §4: "Disabled, the review still runs and publishes its verdict … nothing is a required check"). A developer answering "our team reviews with 2 people at red" minutes after accepting Review enforcement: disabled can reasonably believe they just configured a merge gate. Suggestion: one clause in the prompt — the counts and SLAs are what the review reports per tier, and become merge-binding only with Review enforcement: enabled.

  • …/bootstrap/SKILL.md:262-268 (Step 3.6.1 item 5) — the per-row interview has no upfront "author this table at all?" gate and no bound. Phase 3.5 is the one place map-subdomains/map-contexts run at $scope: all, so the candidate list is a full catalog; on a project with 8 subdomains and 5 contexts the guided path emits up to 13 prompts. The escape hatch exists ("or skip the table entirely") but only inside the first row's question, so the default reading is "work through the list". This is the story's own team concern ("a guided flow that runs by default can quietly turn an optional file into an implied requirement"). Suggestion: ask once whether to author the table before entering the row loop, and state that the offer is a list to prune, not a form to complete.

  • packages/knowledge-hub/src/conformance/bootstrap-classification-delta.test.ts:127-154 — the AC2 assertions pin the pattern only inside bootstrap's own body: three lowercase greps (propose-then-write-if-confirmed, registry, classify) plus a "does not route through record-decision" regex. Nothing pins the other end of the reference — that quality-model.md still defines that pattern under that name in a section numbered §5, and that /pair-capability-classify still implements it in its Step 5. Rename either and the phase's central claim, plus the DoD item "write path reuses classify's pattern — verified by test, not by resemblance", silently rots while the suite stays green (check:links validates the link target, not the anchor or the wording). Suggestion: add two cross-document assertions — quality-model.md contains propose-then-write-if-confirmed under a ## 5. heading, and classify/SKILL.md's Step 5 still writes ## Tag Projection.

  • …/bootstrap/SKILL.md:259 (Step 3.6.1 item 4, first bullet) — "the mapped subdomains and bounded contexts are the candidate rows" offers two catalogs at different granularities into one key space with no de-duplication or precedence rule. The Criticality Table is keyed by service/domain (payments, marketing-site in quality-model §6) and classify resolves "a service listed High in the Criticality Table"; a subdomain and its bounded context very often share a name, so the offer can produce two rows with the same key — and per classify's rule a service not listed resolves to conservative High, so a near-miss key is not a harmless duplicate. Suggestion: state which catalog supplies the key (contexts are the closer analogue of a deployable/service), and that a subdomain whose name a context already covers is offered once, not twice.

Questions

  • .pair/knowledge/how-to/02-how-to-complete-bootstrap-checklist.md:88-96 — the new Phase 2.6 section was added to the phase flow, but the file's Final Quality Checklist was not extended, although it does carry a line for the sibling optional phase ("Domain model bootstrapped via … or explicitly skipped"). Reading this as deliberate — a checklist line, even one ending "or explicitly declined", is the mechanism by which an optional file starts to feel expected, which is the story's stated team concern and the ADL's "Absence stays legitimate" constraint (D21) — so the omission looks correct and the two files the conformance test guards (definition-of-done.md, definition-of-ready-and-done.md) are deliberately left clean. Confirm the intent, so a later contributor does not "fix" it. (Also noting the Phase 2.6 vs skill Phase 3.6 numbering offset is the file's pre-existing convention — Phase 2.5 ↔ skill Phase 3.5 — and is correct as written.)
Positive feedback
  • Genuinely test-first. 8d9c8538 lands the conformance suite alone with RED: 23 failing, 5 negative guards already green in the message; 73f2a834 turns it green. The only test edits made during GREEN were prettier reflow and a tightening fix — split('## HALT Conditions')[1] was slicing the whole rest of the file (so the Graceful Degradation entry would have tripped the assertion); scoping it to the HALT list with .split(/^## /m)[0] is the correct assertion, not a weakened one.
  • Negative assertions where they matter. carries no inline copy of the Criticality Table schema or its tier values and carries no inline copy of the per-tier reviewer/SLA table (§4) pin the "reference, never restate" business rule as something a future edit cannot violate, rather than as prose nobody checks. the Definition of Done guidelines do not require the sections pins "absence stays legitimate" across both DoD documents and both mirrors.
  • The mirror is genuinely regenerated, not hand-patched. Diffing the root delta against the dataset delta yields only the expected transform output: skill-name prefixing (/classify/pair-capability-classify) and the ./ link normalization, which matches all 14 pre-existing quick-mode-defaults.md links in each copy. bootstrap-checklist.md and how-to-02 are consistent across both trees too.
  • Quick mode is argued, not asserted. The "no safe default exists, and a fabricated criticality map would silently shape every future tier" reasoning appears in the phase, in quick-mode-defaults.md, in the checklist's deliberately absent list and in the ADL's rejected alternatives (core ⇒ High, generic ⇒ Low"a plausible heuristic, which is what makes it dangerous") — and the checklist anchor is pinned by test in both trees. That is the right place for that argument.
  • The ADL earns its place: five rejected alternatives, each with the specific reason, including the one a reviewer would otherwise have to ask about (why not /pair-capability-record-decision, why not a standalone author-risk-matrix capability). It conforms to adl-template.md field-for-field, and its "no dataset mirror" claim checks out (the dataset decision-log holds 1 seed entry against the root's 33).
Functionality & requirements (AC coverage)
AC Verdict Evidence
AC1 — guided question-set for both sections, one recommendation at a time ⚠️ partial Both sections are offered (SKILL.md:253, :276) and 3.6.1 is genuinely per-row; 3.6.2 asks a compound question — see Major 3
AC2 — written via classify's propose-then-write-if-confirmed / config-registry pattern, not /pair-capability-record-decision SKILL.md:249 states both halves explicitly; asserted by 4 tests (m9 notes the assertion is one-sided)
AC3 — decline/skip ⇒ nothing written, KB defaults, non-blocking SKILL.md:271, :289; HALT list verified free of the phase by a negative assertion
AC4 — already-authored sections detected, never re-proposed Per-section **Check**/**Skip** in both steps + a 7th Idempotent Re-invocation entry (SKILL.md:371). ⚠️ the malformed interaction with this skip is Major 2
AC5 — Phase 3.5 output drives candidate rows, each with recommendation + reason, developer confirms/edits SKILL.md:259; m10 flags the missing subdomain/context key rule
AC6 — 3.5 skipped/empty ⇒ repository-derived candidates; empty table valid SKILL.md:260-261
AC7$mode: quick asks nothing, writes nothing, reported once in the Step 4.3 summary Both steps' Quick mode notes, the quick-mode-defaults.md row, the checklist anchor, and the no-TTY resolution (SKILL.md:251) — 6 assertions

Edge cases from the story, checked one by one: no distinct services ⇒ single scope ✅ · overrides empty ⇒ KB defaults ✅ · file absent ⇒ created with confirmed sections only, never a copy of the example ✅ · malformed ⇒ reported, not rewritten ⚠️ (bypassable — Major 2) · ## Tag Projection untouched ✅ (stated in both steps) · no TTY ⇒ quick behaviour ✅.

Testing & quality gates

Re-run independently on head f397c7b in a detached worktree:

Gate Result
vitest run (@pair/knowledge-hub, full suite) PASS — 1348/1348, 32 files (29 of them the new file)
bootstrap-classification-delta.test.ts alone PASS — 29/29
check:links (dataset + .pair/knowledge) PASS — all markdown links valid, 0 patched
skills:conformance PASS — 41 skills conformant
prettier-check + markdownlint-check (knowledge-hub) PASS
code-hygiene:check PASS — no violations
pre-push-gate:check (composition) PASS — check-mode only
CI on f397c7b build success, secret-scan success

🟡 gate set (lint + type + build + unit) is green, so nothing caps the verdict mechanically. tsc --noEmit in the throwaway worktree reports TS6306 on packages/content-ops — a worktree artifact (composite project references with symlinked node_modules, unbuilt sibling), not a PR defect; CI's ts:check passes on the same commit.

Coverage of the new assertions is adequate for a prose artifact: 29 assertions across positioning, both question sets, the write path, opt-in/non-blocking, idempotency, quick mode, schema non-restatement, the Step 4.3 summary and the mirror. Two gaps are recorded as m9 (no cross-document anchor pin) and inside Major 3 (one recommendation at a time is grepped as a literal, so the compound prompt passes).

Adoption compliance
  • Degradation level: 4 — neither /pair-capability-verify-adoption nor /pair-capability-assess-stack was run as a capability in this review; the check below is the inline one.
  • Dependencies: none added. No package.json touched, so tech-stack.md needs no update and no /pair-capability-assess-stack pass is owed.
  • Patterns: the phase follows the corpus conventions — check → skip → act → verify per step, **Quick mode**: delta per step with the canonical resolution in quick-mode-defaults.md, schema referenced not restated, degradation entries added rather than a new HALT. The fallback tier on the new quick-mode-defaults.md row matches the precedent set by the Review enforcement row ([US-234] feat: PR state flow (gate≠review) + pair review as required check #390), which is likewise a declared safe default absent from the checklist's per-type table.
  • ADR/ADL: 2026-08-11-criticality-delta-is-authored-after-domain-modeling.md records all three decisions (position, write path, quick-mode behaviour), conforms to adl-template.md, uses a valid Category (Convention Adoption), and its Adoption Impact claim (no adoption file changes, no dataset mirror) is accurate. No missing-ADR HALT condition applies — this is a convention application, not a new architectural decision.
  • One non-conformity: the version: bump the skill-conventions guideline requires — Major 1.
Tech debt

/pair-capability-analyze-debt not run as a capability; the items below come from the manual read and are surfaced, not blocking.

  • Documentation debt (small, this PR) — the two registry/catalog surfaces that now under-describe reality: the docs-site knob catalog (m5) and the KB writers table (m6). Both are one-cell/one-row edits.
  • Test debt (small, this PR) — one-sided conformance: the pattern reuse is pinned only on the consumer side (m9).
  • Pre-existing, not introducedtech/risk-matrix.md has never appeared in the skills-guide writers table even though /pair-capability-classify writes it. Worth folding into m6 while the file is being touched, rather than tracking separately.

No item here is large enough to warrant its own story, and none of them justify TECH-DEBT as a verdict on their own.

Documentation
  • Skill documentation updated — new Phase 3.6, the two degradation entries, the 7th idempotency check, the Step 4.3 summary line, both copies.
  • How-to updated — 02-how-to-complete-bootstrap-checklist.md gains Phase 2.6, in both trees, with the file's existing numbering offset respected.
  • KB asset updated — bootstrap-checklist.md's deliberately absent list, both trees, pinned by test.
  • Decision recorded — ADL, template-conformant.
  • User-facing docs site not updated — the quality-gates-configuration.mdx knob row still describes hand-authoring only (m5).
  • Skill version not bumped — Major 1; the convention treats the version as part of the documentation contract ("a reader can tell which copy they have").
  • n/a — no API, no architecture diagram, no migration affected.
Performance & deployment
  • No hot path touched — the change is markdown plus one file-reading test; the suite runs in ~2s.
  • Reversible by construction — the new phase writes nothing unless confirmed, adds no HALT, and creates no schema. Rolling it back removes an offer; it cannot leave a project in a state that fails to classify.
  • Note: the one unbounded cost is interview length in guided mode (m8), not runtime.

Review conduct: 🟡 standard checklist depth (quality-model §4) — sections with nothing to say are stated briefly rather than expanded. pair-review check: not published — advisory (Review enforcement: disabled in tech/way-of-working.md; this review is delivered as a PR comment by an independent reviewer agent, per code-review-template's delivery note). Merge remains the human gate.

…ne question per family

- parse check hoisted out of Step 3.6.1 into Step 3.6.0 (whole-phase precondition):
  a malformed-but-headed section could otherwise read as "already authored" and let
  Step 3.6.2 write into a file §6 makes silently inert
- Step 3.6.2 split into two blockquotes (thresholds; reviewer counts/SLAs), the second
  saying the counts bind a merge only with `Review enforcement: enabled`
- Step 3.6.1: single up-front "author the table at all?" gate before the row loop
  (list to prune, not a form to complete); bounded contexts supply the key, subdomains
  de-duplicated against them (an unlisted/near-miss key resolves to conservative High)
- Output Format `Classification:` is per-section, so a mixed run is representable
- version 0.6.0 → 0.7.0 (new phase step + changed output shape + sub-doc touched)
- skills-guide § Adoption Files gains the `tech/risk-matrix.md` row (section ownership)
- quality-gates-configuration.mdx names the guided path in "How to enable"
- 6 new conformance assertions (all fail on the pre-fix content) + 2 cross-document
  rot guards: quality-model §5 still defines the pattern, classify Step 5 still writes
  `## Tag Projection`

Refs: #351
…dered enforcement value, empty-answer semantics

- quality-model §6 gains the Key namespace rule (deployable owning the touched
  files) so the write side keys what the read side queries; catalogs demoted to
  candidate/value sources. New ADL, example asset + website mirror aligned.
- criticality criterion stated in its own terms (blast radius / exposure / data
  sensitivity / uptime) with an explicit H/M/L mapping — no longer read off the
  subdomain class, which §3.1 already spends on Business impact.
- reviewer/SLA prompt renders `Review enforcement: [recorded value]` with both
  branches, instead of asserting the `disabled` default.
- "empty is valid" now means no section written; a rowless table is refused.
- gate + per-row prompts disclose that an unlisted service resolves to High.
- `skipped — quality model not installed` added to the summary line.
- decline-is-not-recorded divergence from classify documented (phase + ADL).
- Phase 3.5 / Step 3.2 exits route into 3.6 instead of past it.
- checklist no longer claims the file stays absent after a quick run.
- test helper escapes every dot; prose assertions de-brittled to alternations.

Refs: #351
…ion, criterion moved to the model

§6 keyed a diff to "the deployable that owns the touched files" (singular) and
covered only the single-deployable repo. A change touching several deployables —
the normal monorepo diff — resolved by whichever key the executor picked, and
since tier = max(dimensions) the whole tier flipped between runs on identical
code. §6 now takes the HIGHEST criticality among the touched deployables, with
an unlisted one contributing the conservative High; and it resolves the key at
refinement time too (story's declared scope; a story naming none falls to the
file-absent default, not to unlisted⇒High).

The H/M/L criterion moves out of the skill into §6 (Choosing a value) — model
semantics, so both authoring routes reason the same way; Step 3.6.1 cites it.
Step 3.6.0 gains the quality-model-installed check its own Verify now admits as
the third whole-phase state. Degraded (no domain model) rows are recommended by
the same criterion instead of offered bare. The render-it directive moves out of
the developer-facing blockquote into item 4's prose. ADL #1 Decision 1 reworded
to what shipped (deployable keys, empty ANSWER valid, rowless table refused) and
cross-references the keying ADL. New guards: multi-deployable + refinement-time
§6 rules, §6-owns-the-criterion, how-to-02 Phase 2.6, ADL Decision 1, Step 3.6.0
third state, degraded-path recommendation; two brittle prose assertions widened.

Refs #351
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr-state:to-be-reviewed risk:yellow Classification: medium risk tier

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant