Skip to content

[US-278] feat: bootstrap quick mode — a second resolution depth, guided stays the default - #408

Merged
rucka merged 13 commits into
mainfrom
feature/US-278-quickstart-bootstrap-path
Jul 31, 2026
Merged

[US-278] feat: bootstrap quick mode — a second resolution depth, guided stays the default#408
rucka merged 13 commits into
mainfrom
feature/US-278-quickstart-bootstrap-path

Conversation

@rucka

@rucka rucka commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

PR Information

Story: #278 · Epic: #213 · Type: Feature · Priority: High (P0) · Assignee: @rucka

Classification

risk:yellow · cost:green — criticality 🟡 (KB default, no criticality table) · diff risk 🟡 (5 workspaces, shared KB asset) · business impact 🟡 (both touched subdomains Supporting) · security 🟢 · coupling 🟢 balanced. Tier = max(dimensions) = 🟡. Backfilled at review time (round 1): the refinement-time matrix was missing from both the story and this PR, so automation read it as red (fail-safe, quality-model §3.2).

Matrix
Dimension Value Why
Service/domain criticality 🟡 tech/risk-matrix.md declares no criticality table → KB default medium
Change/diff risk 🟡 touches shared KB assets + 5 workspaces; no schema, no contract break, no infra provisioning
Business impact 🟡 AI Development Process Automation + Documentation & Onboarding, both Supporting
Security relevance 🟢 docs/skill/QA artifacts only, no authn/authz, no secrets, no untrusted input
Coupling balance 🟢 balanced — one skill declares a delta on an existing KB convention, no new integration
Cost class 🟢 no paid SDK, no API key, no IaC, no LLM call added

Gate set for 🟡: lint + type + build + unit — all green locally (pnpm quality-gate, 22 + 12 turbo tasks).

Summary

What Changed

/pair-process-bootstrap gains a second resolution depth, selected by $mode: quick — an opinionated default setup instead of the full Phase 0–4 interview. Guided stays the declared default: absent $mode, nothing changes.

  • SKILL.md (+43/−8 dataset, +38/−3 mirror) — the quick entry, composing the Guided/Quick Setup Convention's cascade.
  • quick-mode-defaults.md (new, +53, mirrored) — the disclosed per-adopter delta: which decision points are defaultable, which cascade tier fills each, and which are still asked.
  • ADL 2026-07-31-bootstrap-quick-is-a-depth-not-a-skill.md.
  • Docs — new getting-started/bootstrap-quick-mode.mdx (+70), cross-linked from quickstart.mdx, registered in meta.json.
  • QA — new CP9-quickstart-onboarding.md (+142) for the epic's own <10-minute KPI; CP5 page count updated.

Why This Change

The epic's KPI is time to first workable story on an empty repo, target <10 minutes. The guided interview is the right default for a team that wants to decide each point, and the wrong one for a team that wants to start.

Story Context

As a new team adopting pair I want a Quickstart path in bootstrap So that setup takes minutes instead of the full guided interview, while the complete guided bootstrap remains available.

AC1 <10 min, no interview · AC2 guided unchanged when not requested · AC3 follows the #276 convention exactly, no bespoke resolution · AC4 every default is a normal, editable adoption file.

Changes Made

Implementation Details

The shape was a real decision, and the convention did not settle it. #276 (merged, PR #349) fixes the selector direction, the four-tier cascade (explicit argument > project state > saved preferences > hardcoded fallback) and the non-interactive safety rule, but explicitly leaves which mode is the default to each adopter — and its two shipped adopters declare opposite defaults (pair package → quick, the assess-* family → guided). So bootstrap had to declare its own rather than inherit one. It declares guided.

Three constraints follow, each asserted in conformance:

  1. No second skill, no second entry point — one skill, one catalog row, one frontmatter description. Both depths run the same phases, compose the same skills, write the same files. (This is also why no skills-catalog.mdx row changed, keeping the PR off a file four parked PRs touch.)
  2. No bespoke resolution order — bootstrap composes the convention's cascade and declares only its delta in the disclosed sibling.
  3. No quick-mode-only output — every file quick mode writes is a normal adoption file in the normal location, with no marker. An accepted default is editable exactly like a decided one (AC4).

Two decisions stay asked in quick mode, because no KB value is safe: the PM tool (organisational, not technical) and the tech stack when the repo is genuinely empty. This is the story's own edge case — quick mode reduces questions to the genuinely-defaultable ones, it does not eliminate every question unconditionally.

Files Changed

  • Added: quick-mode-defaults.md (×2 corpora, +68 each), the ADL (+53), bootstrap-quick-mode.mdx (+74), CP9-quickstart-onboarding.md (+185), bootstrap.test.ts (+502)
  • Modified: bootstrap/SKILL.md (×2), .pair/knowledge/assets/bootstrap-checklist.md (×2 corpora — new § Quick-Mode Per-Project-Type Defaults, the fallback tier's KB anchor; the largest single change here), guided-quick-setup.md (×2 — bootstrap listed as a third adopter), contributing/writing-skills.mdx (the skill version bump rule), getting-started/index.mdx (one bullet in "Choose your path"), quickstart.mdx, meta.json, docs.e2e.test.ts, CP5, qa/README.md

Testing

Test Coverage

bootstrap.test.ts42 assertions (26 at first push, +13 in review round 1, +3 in round 2), the original set written test-first and verified RED before any implementation existed, all green. They pin the three ADL constraints rather than the prose: one entry point, no bespoke cascade, no marker on quick-mode output.

Test Results

  • pnpm quality-gate green (exit 0) — 22 + 12 turbo tasks, re-run after each review round.
  • Conformance 42/42; whole @pair/knowledge-hub suite 560 green.
  • Relative links verified by hand, every .md/.mdx target resolved on this branch. Doing this explicitly because pnpm quality-gate does not check markdown links — that check is an e2e test (ci.yml:120, inside the build job), outside the local gate set, and a sibling PR shipped two dead links past a green local gate this week.
  • The new page is registered in all three places that must agree: meta.json (nav), docs.e2e.test.ts (page list), CP5 (manual completeness).

Quality Assurance

Review Areas

  • Is guided the right default for bootstrap? The convention permits either; this PR argues guided because bootstrap is the one skill whose output is the project's adopted decisions. Reversible, but it is a declared position, not an accident.
  • Are the two still-asked decisions the right two? Adding a third weakens the <10-minute KPI; removing one guesses something organisational.
  • The two disclosed deviations (quick-mode-defaults.md § Disclosed deviations): $mode: guided accepted as a loud no-op, and — added in review round 2 — Path A's confirmation round suppressed on composed assess-* skills in quick mode. Without the second one, "asks no questions" is false the moment more than zero assess-* skills are installed. The alternative (a first-class non-interactive signal on the assess-* family) touches eight skills plus the cascade convention and is left to its own story.

Notes for reviewers

AC1's <10-minute claim is validated by a manual timed scenario (CP9), not by an automated test. The story asked for exactly that, and it cannot be honestly asserted in CI — but it means the headline number rests on someone running CP9, not on this PR being green.

Dependencies & Related Work

Closes #278

🤖 Generated with Claude Code

rucka added 9 commits July 31, 2026 09:42
- 25 RED tests over dataset/.skills/process/bootstrap/** + root mirror
- Cover selector/$mode + guided declared default (AC1/AC2)
- Cover composition of the Guided/Quick Setup Convention, no bespoke resolution (AC3)
- Cover per-decision defaultability doc, adoption-file sameness (AC4), edge cases
- Cover guided-path anchors (no regression), mirror equality, timed CP + docs
- Task: T1 — identify defaultable vs still-asked bootstrap decisions (RED)

Refs: #278
- $mode selector, guided declared default, absent => guided unchanged (AC1/AC2)
- composes the Guided/Quick Setup Convention cascade, no bespoke order (AC3)
- quick-mode-defaults.md: per-decision defaultability + still-asked (PM tool, undetectable stack)
- same adoption files/format as guided (AC4); no-TTY safety + HALT on unresolvable input
- root mirror ported (SKILL.md + sibling)
- MT-CP901..905: empty project -> first workable story, stopwatch protocol, <10 min target
- MT-CP903 asserts adoption files are normal (no quick-mode-only marker)
- MT-CP904 guided-default regression, MT-CP905 no-TTY never hangs
- registered in the suite index + maintenance checklist
- new getting-started page: depth comparison, the two still-asked questions,
  cascade tiers, no quick-mode-only output, CI/no-TTY behaviour
- registered in getting-started/meta.json nav and CP5 page list
- quickstart.mdx (CLI install) cross-links it; guided stays the default there
Records the #276 application: $mode selector, guided as bootstrap's declared
default, no bespoke resolution order, no quick-mode-only output. Alternatives
(separate skill / quick-as-default / third partial depth) rejected with reasons.
Adding the bootstrap-quick-mode URL without bumping the Getting Started
count and the 60->61 total left CP5 self-contradictory.
Registering the page in meta.json alone leaves it outside the 200/title
smoke list and the prev/next circularity sweep.
- RED: convention still says "two shipped adopters" post-#278
- Assert both copies (dataset + root KB) enumerate bootstrap
- Task: T2 — quick-mode entry per the Guided/Quick Setup Convention

Refs: #278
- GREEN: enumeration named only pair package + assess-*
- bootstrap declares guided default, quick via $mode; delta stays in the skill
- Both copies (root KB + dataset) kept identical
- Task: T2 — quick-mode entry per the Guided/Quick Setup Convention

Refs: #278
@rucka rucka self-assigned this Jul 31, 2026
@github-actions
github-actions Bot temporarily deployed to Website Preview July 31, 2026 08:39 Inactive
The file was committed before prettier ran on it, so it would have landed on
main unformatted and added to the existing drift. Formatting only — no
assertion changed.

Two unrelated pair-cli test files that prettier also rewrote were deliberately
left out: that drift pre-dates this story and belongs to #394 (pre-push gate
should run the formatters in write-mode), not to a bootstrap PR.

Refs #278

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions
github-actions Bot temporarily deployed to Website Preview July 31, 2026 09:04 Inactive
@rucka

rucka commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator Author

Verdict

risk:yellow · cost:greenCHANGES-REQUESTED — quick mode is well-shaped and well-documented, but as written SKILL.md still runs the guided approval round at Step 3.1 and plain (Path C) assess-* at Step 2.2, so the delivered artifact does not yet satisfy AC1's "no interview"; the fallback tier also names a KB source that does not hold the values it claims.

PR: [#408] · Author: rucka · Reviewer: independent reviewer agent · Date: 2026-07-31 · Story: [US-278] · Type: feature (docs/skill-definition)

Classification matrix — per dimension
Dimension Tier Source Note
Service/domain criticality 🟡 yellow KB default (tech/risk-matrix.md has no table) Medium is the documented default when the criticality table is absent
Change/diff risk 🟡 yellow diff footprint 15 files across 5 workspaces + the shared KB convention doc; no runtime code
Business impact 🟡 yellow subdomain class adoption-guidelines / how-to-knowledge are both Supporting
Security relevance 🟢 green /assess-security (manual read — see Assessments) prose + one conformance test; no security-sensitive surface
Coupling balance 🟢 green /assess-coupling ($scope: diff, manual read) one new documentation dependency (skill → shared KB convention), stable, balanced

Tier = max(assessed) = 🟡 yellow. Cost = highest detected signal = green.

No drift note emitted on purpose. Story #278 carries no refinement-time classification and the PR carries neither a matrix nor a risk:* label, so automation treats it as red (fail-safe, quality-model §3.2). Review computed yellow; a review never lowers a dimension silently, so the reduction is recorded as a finding (Minor, below) rather than as a downgrade.

Assessments

Security — Input validation

Verdict: green — no input surface in the diff; the only executable file is a conformance test that reads repo files with readFileSync on constants.

Details
  • packages/knowledge-hub/src/conformance/bootstrap.test.ts builds every path from __dirname + literals — no path traversal, no external input.
  • All other 14 files are markdown/MDX/JSON documentation.

Security — Output handling

Verdict: green — no output encoding surface; the new MDX page renders static prose and fenced text blocks, no dangerouslySetInnerHTML, no components.

Details
  • bootstrap-quick-mode.mdx uses only markdown primitives, matching the getting-started house style (no Callout usage anywhere in that section).

Security — Authentication

Verdict: green — no authentication path touched.

Security — Authorization

Verdict: green — no access-control path touched.

Security — Introduced vulnerabilities

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

Details
Severity Category File:location Introduced / pre-existing Recommendation
none

No secrets, credentials, dependencies, or network calls added. Note the behavioural rule quick mode introduces: $mode: quick writes adoption files without a per-document approval round. That is deliberate and scoped to the developer's own repo — not a security finding.

Cost

Verdict: cost:green — no cost signal in the diff.

Details
Signal Class Provider Note
paid-SDK import green none
API-key env var green none
IaC / provisioning green none
cron / queue green none
LLM calls green quick mode reduces conversational turns vs. guided

Architecture (Coupling)

Verdict: green — balanced: one new documentation dependency from pair-process-bootstrap onto the shared guided-quick-setup.md convention.

Details
  • Integration strength: model/contract reuse by reference (the cascade is cited, not restated) — the deliberately weaker of the two options, and the right one here.
  • Socio-technical distance: same repo, same owner — minimal.
  • Volatility: the convention landed one week ago (Guided/Quick Setup Convention — unify interactive vs default resolution across setup skills #276) but is now referenced by three adopters; the shape is stabilising rather than churning.
  • Balance rule: weak integration + low distance + low-to-moderate volatility ⇒ balanced. No decoupling action warranted.
  • The reverse edge (convention doc now enumerates bootstrap) is intentional and guarded by a test that fails on the stale "two shipped adopters" phrasing — a nice touch.

Details

Findings by severity

Critical (must fix before merge)

  • none

Major (should fix before merge)

  • .claude/skills/pair-process-bootstrap/SKILL.md:118-127, 158-171 — Two of the three biggest question-bearing steps have no **Quick mode**: note, so an agent executing SKILL.md with $mode: quick will still interview. Step 3.1 keeps 3. Act: Present key decisions with rationale for developer review. / 4. Act: Iterate on feedback until approved. for each of five adoption documents, and Step 2.2 composes assess-* with no $choice — and the assess-* family's declared default is guided (Path C, full assessment), so plain composition is an interview per installed skill. The intended behaviour exists only in the disclosed sibling (quick-mode-defaults.md:31,32) and in CP9:65 ("no per-document approval round"), i.e. the test and the manual CP assert a behaviour the skill never states. Every other question-bearing step (1.2, 2.3, 3.2, 4.2, 4.3) did get an inline note, so the pattern breaks exactly where the cost is highest. Impact: AC1 ("no interview") is not met by the delivered artifact; the ~10-minute target is unreachable. Suggested fix: add the two missing one-line **Quick mode**: notes (after Step 2.2 and after Step 3.1, mirroring the existing five), and qualify the guided-only HALT condition Adoption file generation rejected (Phase 3) at SKILL.md:278 as guided-only.
  • .claude/skills/pair-process-bootstrap/quick-mode-defaults.md:22 — The hardcoded fallback tier is declared as "the per-project-type defaults in bootstrap-checklist.md — a KB value, never one invented here", but that asset contains no per-type defaults for four of the five sections. bootstrap-checklist.md has per-type values only for the core architectural pattern (lines 57-59); its Tech Stack / UX-UI / Infrastructure / Way-of-Working sections (lines 145-307) are question checklists (- [ ] Frontend Framework + Version), not values. The only complete per-type values are the three "Context-Specific Examples" (lines 340-470), which are project-specific worked examples (a Next.js portfolio, a SaaS analytics platform, an enterprise CRM) — using Example 1's stack as the Type A default would be wrong for, say, a Python CLI, and Example 1 also names a PM tool (Filesystem), directly contradicting line 42's "no KB value is safe" for the PM tool. Impact: for four of five adoption sections quick mode has nothing to resolve from, so it will either invent values (violating "never one invented here" and AC3's "no bespoke Quickstart-specific resolution logic") or ask (violating AC1). Suggested fix: name the exact anchor in bootstrap-checklist.md that constitutes the fallback per section; where none exists, either add a per-type defaults table to the KB asset or move that section into the still-asked set.
  • .claude/skills/pair-process-bootstrap/quick-mode-defaults.md:28,45 · qa/release-validation/CP9-quickstart-onboarding.md:5,30,38-40,65 — The PRD is a third question-generating input in the AC1 scenario, and neither the still-asked set nor the timed CP accounts for it. Phase 0 is BLOCKING and composes /pair-process-specify-prd when the PRD is missing or a template (SKILL.md:54) — an interactive, iterative-review skill. MT-CP901 establishes a genuinely empty project (git init + $CLI install, so PRD.md is a template) and MT-CP902 starts the stopwatch immediately before $mode: quick, then asserts "Bootstrap asked no question outside the two still-asked decisions above". As written, MT-CP902 will always fail that assertion, and the full PRD authoring session falls inside the measured <10-minute window. quick-mode-defaults.md:45 ("Everything else in the table above resolves without a question") is false for the Phase 0 row, and the docs page's "Expect at most two questions" (bootstrap-quick-mode.mdx:27) is wrong on an empty repo. Suggested fix: add "a populated .pair/adoption/product/PRD.md" to CP9's preconditions (or an explicit MT-CP900 that authors it outside the stopwatch), and name the PRD as a precondition/third still-asked input in quick-mode-defaults.md, SKILL.md:43 and the docs page.
  • apps/website/content/docs/getting-started/meta.json:3-10 · apps/website/e2e/landing.e2e.test.ts:75-77 — Inserting bootstrap-quick-mode between quickstart and quickstart-solo silently voids an existing e2e test. landing.e2e.test.ts:76 is commented "Use prev/next to go to Quickstart: Solo" and does page.locator('a', { hasText: 'Quickstart: Solo' }).last().click(); the Quickstart page's footer next link is now "Bootstrap Quick Mode", so .last() resolves to the sidebar link instead. The URL assertion still passes (same destination), so the prev/next guarantee disappears with a green suite — and this is outside the local gate (e2e runs in CI's build job), which is exactly the failure mode called out in the PR description. Suggested fix: either order bootstrap-quick-mode after the quickstart-{solo,team,org} trio in meta.json, or retarget the test at the real footer next link (a:has-text("Next"), the shape docs.e2e.test.ts:978 already uses).

Minor (consider)

  • .claude/skills/pair-process-bootstrap/quick-mode-defaults.md:20-21 — Tier 2 and tier 3 overlap, making tier 3 unreachable. project state is defined as "what is already on disk: .pair/adoption/**, …" and saved or inferred preferences as "the ADLs/ADRs in .pair/adoption/decision-log/" — but decision-log/ is under .pair/adoption/**, and project state outranks preferences. The reference precedent (pair package: cliFlags > packageJson > gitConfig > preferences > hardcoded) keeps preferences as a genuinely distinct store. Suggested fix: scope the project-state row to exclude decision-log/, or point the preferences row at a user/session-level store.
  • .pair/adoption/decision-log/2026-07-31-bootstrap-quick-is-a-depth-not-a-skill.md:43 — The ADL claims "the conformance test's per-decision anchors fail if a phase is added without one". They do not: bootstrap.test.ts:146-157 only asserts the defaults doc contains the substrings PRD, categoriz, assess-, quality gate, PM tool, domain model. Adding a new bootstrap phase with no quick-mode row leaves the suite green. A future author will rely on a safety net that does not exist. Suggested fix: soften the ADL sentence to what is actually guarded, or make the test derive its anchor set from SKILL.md's ### Step/## Phase headings and require a matching row.
  • PR [US-278] feat: bootstrap quick mode — a second resolution depth, guided stays the default #408 (metadata) · .pair/adoption/tech/risk-matrix.md:5-9 — The project declares Active: risk and "the full classification matrix is … written to every card/PR body", but this PR has no risk:* label and no matrix in its body (nor does story Quickstart path in bootstrap — opinionated one-command setup #278). Automation therefore reads it as red (fail-safe). Suggested fix: apply risk:yellow (the review-computed tier above) and paste the matrix line + <details> into the PR description; ideally backfill the story's refinement-time classification so the drift check has a baseline.
  • apps/website/content/docs/getting-started/index.mdx:30-35 — The story's DoD asks for the docs page "cross-linked from Getting Started". The cross-link landed on quickstart.mdx and the page is in the section nav, but the Getting Started index's "Choose your path" list — the section's actual discoverability surface — does not mention it. The PR description says index.mdx was avoided to stay parallel-safe with [US-230] feat: pair-process-brainstorm — 3 phases, parametrized ($root, orientation) #387; that is a merge-ordering concern, and a one-bullet addition is a trivial conflict to resolve. Suggested fix: add the bullet here, or state explicitly in the PR that it is handed to [US-230] feat: pair-process-brainstorm — 3 phases, parametrized ($root, orientation) #387.
  • .pair/knowledge/guidelines/technical-standards/ai-development/skill-conventions/guided-quick-setup.md:25 (+ dataset mirror) — With bootstrap added, the enumeration is 3 adopters of which two declare guided; "The shipped adopters declare opposite defaults" now reads oddly (the deleted word was "two", which was what made "opposite" scan). Suggested fix: "The shipped adopters do not agree on a default …" or "…declare differing defaults".
  • packages/knowledge-hub/src/conformance/bootstrap.test.ts:47-57, 225-238 — The SKILL.md mirror assertion duplicates coverage that src/tools/skill-md-mirror.test.ts already provides data-driven for every dataset skill, byte-for-byte, through the real pair update copy pipeline (buildInstalledSkillMd). The local toMirror helper uses only applyKnownMirrorTransforms (skill-reference + SKILL.md link-path rewrites) — not the pipeline's generic link rewriter — which is why it needs neutralizeSameDirDotSlash (:57) and why the dataset's directory links had to lose their trailing slashes in this PR (…/adoption/tech/…/adoption/tech, five lines) to match. The slash edits are harmless and arguably align the source with the "authored to be transform-correct" convention, but the weaker approximation is a maintenance trap. Suggested fix: keep only the genuinely-additive assertion — the sibling doc (quick-mode-defaults.md) is not covered by the SKILL.md-only guard — and drive it from skill-md-mirror.ts's real pipeline, or extend that guard to non-SKILL.md files in a skill dir (the better fix, since pair-process-review's siblings are unguarded today too) — which is exactly the scope of the already-refined tech-debt: extend mirror-equality guard to all root skill artifacts (sub-docs + references) #384. Dropping the local approximation now would leave quick-mode-defaults.md with no mirror coverage at all until tech-debt: extend mirror-equality guard to all root skill artifacts (sub-docs + references) #384 lands, so the right call is to leave it and let tech-debt: extend mirror-equality guard to all root skill artifacts (sub-docs + references) #384 supersede it (its T-6 reconciles these very artifacts). (non-actionable — Deferred to tech-debt: extend mirror-equality guard to all root skill artifacts (sub-docs + references) #384)
  • qa/release-validation/CP9-quickstart-onboarding.md:59 · :65MT-CP902 step 4 pulls "/pair-next … until one user story exists in the tracker" into the stopwatch. Reaching a story with acceptance criteria routes through /pair-process-plan-* and /pair-process-refine-story, whose Phase 0 is a grill interview — more interactive turns than bootstrap itself, inside a window whose expected result asserts no questions beyond two. Suggested fix: either state that post-bootstrap planning turns are counted and expected (and drop "no question outside the two" to bootstrap-only, which the sentence already nearly says), or split the measurement into bootstrap-elapsed and story-elapsed.
  • qa/release-validation/CP5-website-docs-completeness.md:16-19, 99-108README.md:100 says "add a changelog entry at the bottom of the affected CP file"; CP5 was modified (page count 60→61) without one. CP5 has no ## Changelog section at all, and CP9 is the first CP to add one — so this matches existing practice more than it violates it, but the rule now has a same-PR counter-example. Suggested fix: add a two-line ## Changelog to CP5, or relax the README rule to "CP files that have a Changelog".
  • apps/pair-cli/src/commands/kb-info/version-check{,-formatter}.test.ts — Running pnpm quality-gate on this branch leaves these two files modified by prettier:fix (verified locally: gate exits 0 but the worktree is dirty afterwards). Pre-existing drift, unrelated to this story, already tracked. (non-actionable — Deferred to [tech-debt] Pre-push quality-gate runs prettier:fix/mdlint:fix repo-wide in WRITE mode — authors bypass the hook #394)

Questions

  • .claude/skills/pair-process-bootstrap/SKILL.md:4version: 0.5.0 is unchanged although the skill gains a new public argument and a second execution depth. History shows the frontmatter version is bumped on some feature changes (0.4.1 → 0.5.0 in assess-* skills are output-only; record-decision is the sole adoption writer (no scan-mode) #224) and not on others (pair-process-review stayed 0.7.0 through [US-228] feat: verdict-first code-review template (security + cost + architecture, 30s budget) #376), and no convention doc covers it. Is skill version meant to track behavioural additions? If yes, this needs a bump; if no, it would be worth writing that down so reviewers stop asking.
  • .claude/skills/pair-process-bootstrap/SKILL.md:34 — The Arguments table documents $mode as accepting both guided and quick, while the convention fixes the selector as pointing at the non-default mode only (guided-quick-setup.md:22). Accepting an explicit guided is harmless and arguably useful for scripts that want to be loud about it — is that a deliberate, documented deviation, or should the accepted value set be quick only?
Positive feedback
  • Genuinely test-first, and provable from history: cf1175bf (RED conformance guard) precedes c4ed62f1 (implementation) as separate commits, and the same discipline is repeated for the convention-adopter enumeration (c41dad71 RED → 2dd2eaa7 GREEN). The tests pin the three ADL constraints rather than the prose.
  • The shape decision is recorded, not assumed. The ADL states bootstrap's declared default and why the convention could not supply one (its two shipped adopters disagree), and rejects three alternatives with reasons — including the pair package shape, which was the tempting one.
  • The convention doc was updated in both copies with a guard against going stale: asserting not.toMatch(/two shipped adopters/i) is a much better test than asserting the new sentence, because it fails the next adopter too.
  • CP9 is a real measurement, not a vibe: explicit T0/T1 protocol, "human think-time counts", a breakdown demanded on failure, plus a guided-default regression (MT-CP904) and the no-TTY edge case (MT-CP905) in the same critical path.
  • MT-CP903 tests the negative (grep -rniE "quick[- ]mode|generated by quick" .pair/adoption/) — the right way to assert AC4's "no quick-mode-only marker".
  • The PR description flags its own weakest point (the <10-minute number rests on someone running CP9, not on the PR being green) instead of leaving the reviewer to find it.
  • Docs-page registration is complete in all three inventories that must agree (meta.json, docs.e2e.test.ts ×2 lists, CP5), and CP5's (6 pages)/60/Total: 60 counters were all bumped consistently — the exact class of self-contradiction that usually gets missed.
Functionality & requirements (AC coverage)
AC Verdict Evidence
AC1 — quick mode ⇒ first workable story <10 min, standard gates + PM defaults, no interview not met by the artifact SKILL.md still specifies the guided per-document approval round (Step 3.1) and plain guided-default assess-* composition (Step 2.2) in quick mode (Major 1); the PRD authoring session sits inside the measured window on the target scenario (Major 3). The <10 min number itself is honestly deferred to CP9 rather than asserted — that part is fine.
AC2 — guided unchanged when quick is not requested ✅ met Every guided phase/step is untouched; additions are **Quick mode**: sentences after each step plus a new ## Arguments / ## Resolution Depth pair. Guarded by bootstrap.test.ts (9 phase/step anchors + the three verbatim guided questions) and by MT-CP904. Only incidental edit: five directory links lost a trailing slash in the dataset copy (semantically identical, link-checker clean).
AC3 — follows the #276 convention exactly, no bespoke resolution ⚠️ partial Structurally correct: the cascade is cited not restated, the selector points at the non-default depth, non-interactive safety takes the convention's fall-back-to-quick branch, and the deviation ("not every question disappears") is documented under its own heading as the convention's edge-case rule requires. But the hardcoded fallback tier resolves to a KB source that does not contain the claimed values (Major 2), so in practice four of five sections have no convention-sourced default to take.
AC4 — every default is a normal, editable adoption file ✅ met Asserted in quick-mode-defaults.md, SKILL.md, the docs page, bootstrap.test.ts (normal adoption file + no quick-mode-only), and validated behaviourally by MT-CP903 (negative grep + a hand edit that must survive).

Edge cases from the story: already-configured project ✅ (delegated to each composed capability's own detection, stated in both docs). A required decision with no safe default is still asked ✅ for the PM tool and the undetectable stack — ❌ for the PRD, which is the same class of decision and is not listed (Major 3).

Testing & quality gates
  • Quality gates: PASS — independently re-run on 95083917 in a detached worktree: pnpm quality-gate exit 0, turbo 22 successful, 22 total + 12 successful, 12 total, hygiene check clean. pnpm --filter @pair/knowledge-hub test: 544 tests / 23 files, all green, including the 26 new bootstrap.test.ts assertions and the 54-test data-driven per-skill mirror guard. check:links clean over both the dataset and .pair/knowledge.
  • Coverage: conformance-test coverage is proportionate for a skill-definition change and correctly placed — packages/knowledge-hub/src/conformance/bootstrap.test.ts is a new target artifact, so a new file is right per the per-artifact ADL (no prior conformance file targeted bootstrap).
  • Gaps: (a) the e2e suite is not in the local gate, and this PR changes docs nav in a way an existing e2e test depends on (Major 4) — that test's guarantee is not re-verified by anything the author or I can run locally; (b) bootstrap.test.ts:146 is a keyword-containment check, not the per-phase completeness guard the ADL claims (Minor); (c) .claude/skills/** markdown links are outside check:links scope — I verified the new root-side link targets by hand (bootstrap-checklist.md, guided-quick-setup.md, ./quick-mode-defaults.md) and they resolve; the ./ prefix on the sibling link matches the pipeline output convention already visible in pair-process-review's siblings.
Adoption compliance
  • Degradation level: 4 (/verify-adoption and /assess-stack not installed) — verified inline instead.
  • No dependencies added, so tech-stack.md needs no change. No architectural pattern touched.
  • ADR/ADL: present and correctly typed. 2026-07-31-bootstrap-quick-is-a-depth-not-a-skill.md sits in .pair/adoption/decision-log/ with Category: Convention Adoption (the most-used category in that directory, 9 occurrences) and carries the full sibling heading set including ## Adoption Impact. Not mirrored into the dataset — correct, and the file says why. No missing-ADR HALT.
  • Conformance-test placement follows 2026-07-18-conformance-test-per-file-not-per-story (per target artifact, not per story).
  • Deviation to note: .pair/adoption/tech/risk-matrix.md declares Active: risk and requires the matrix in every card/PR body; neither the story nor the PR carries it (Minor).
Tech debt
  • Sibling skill files have no mirror-equality guard. skill-md-mirror.test.ts is SKILL.md-only; quick-mode-defaults.md, assess-orchestration.md, degradation-levels.md, merge-and-cascade.md are all unguarded by the real pipeline. This PR works around it with a weaker local transform + a ./-neutralizing regex. Worth a card: extend the data-driven guard to every file in a dataset skill dir, then delete the local approximation. Already refined and worktree-active as tech-debt: extend mirror-equality guard to all root skill artifacts (sub-docs + references) #384 (its AC-1 names process/bootstrap/* sub-docs explicitly), so this PR's local approximation is a stopgap by design, not new debt. (surfaced, not blocking)
  • bootstrap-checklist.md has no per-project-type defaults table. Quick mode's fallback tier needs one (see Major 2). If the fix chosen is "add the table", that is plausibly its own story rather than an edit inside this PR — say so explicitly if you route it that way.
  • Pre-existing prettier drift in two pair-cli test files — already tracked as [tech-debt] Pre-push quality-gate runs prettier:fix/mdlint:fix repo-wide in WRITE mode — authors bypass the hook #394.
Documentation
  • Skill docs: SKILL.md + disclosed sibling, both corpora, mirror-verified. Progressive disclosure respected (the per-decision table is not inlined).
  • Docs site: new getting-started/bootstrap-quick-mode.mdx (frontmatter shape and no-Callout house style match its siblings), registered in meta.json, both e2e page lists, and CP5. Cross-linked from quickstart.mdx; not from the Getting Started index's "Choose your path" list (Minor).
  • KB convention doc updated in both copies to enumerate the third adopter.
  • Not updated, and correctly so: skills-catalog.mdx and the frontmatter description (the ADL's "no catalog row moves" constraint), and how-to/02 (the no-skills manual path, where a skill argument has no meaning).
  • Inaccurate as written: "Expect at most two questions" (bootstrap-quick-mode.mdx:27) — see Major 3.
Performance & deployment
  • No hot path, no queries, no allocations — documentation and one file-reading test.
  • Rollback: reverting the commit restores guided-only behaviour; the change is additive by construction (absent $mode ⇒ unchanged Phases 0-4), so no staged rollout or flag is needed. The one non-additive edge is the docs nav reorder, which is what makes Major 4 worth fixing before merge rather than after.

Independent review. Read only story #278, the PR (description + diff) and the branch code in a detached worktree pinned to 95083917; no author working context consulted.

Resolves every finding on PR #408.

Major:
- SKILL.md: quick-mode notes added to Step 2.2 (compose assess-* with Path A
  $choice, never plain — family default is guided) and Step 3.1 (no
  per-document approval round); Phase 1/3 HALT conditions marked guided-only.
- KB asset: new `bootstrap-checklist.md` § Quick-Mode Per-Project-Type
  Defaults — the fallback tier now points at real per-type values for
  architecture/infra/observability/ux-ui/way-of-working. No stack, no PM tool
  row (project state or asked); worked examples ruled out as a default source.
- PRD is a precondition, not a default: stated in SKILL.md,
  quick-mode-defaults.md and the docs page; CP9 gains MT-CP902 (PRD authored
  outside the stopwatch), timed test renumbered MT-CP903 with bootstrap/story
  splits.
- meta.json: bootstrap-quick-mode moved after the quickstart trio, so
  Quickstart's footer next is Quickstart: Solo again (landing e2e stays
  meaningful); nav order pinned in conformance.

Minor / questions:
- cascade tiers disjoint (project state excludes decision-log/).
- ADL softened to what the suite actually guards; suite now derives the
  interview-marker check per step section.
- CP5 gains a Changelog; getting-started/index.mdx cross-links the page.
- convention wording: adopters "do not agree on a default".
- skill `version` 0.5.0 → 0.6.0 and the bump rule written down in
  contributing/writing-skills.mdx.

risk:yellow · quality gates: PASS (22 + 12 turbo tasks, conformance 39/39)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions
github-actions Bot temporarily deployed to Website Preview July 31, 2026 10:26 Inactive
@rucka rucka added the risk:yellow Classification: medium risk tier label Jul 31, 2026
Path A is $choice + a confirmation round; 8 composed assess-* skills would
mean up to 8 questions inside a depth that claims none. Quick mode now
suppresses that round, disclosed as a per-adopter deviation beside the
explicit-guided no-op, asserted in conformance and in CP9 MT-CP903.

Also: testing + AI sections of tech-stack.md get fallback rows (they are
separate assess-* invocations); Step 2.3 list back to uniform bold;
MT-CP906 gets its own project + PRD setup; interview markers now catch
Step 4.3's own approval phrasing; ADL emphasis + checklist emphasis churn
reverted to underscores (24 lines, both corpora).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@rucka

rucka commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator Author

In response to #408 (comment) (the first review comment).

Escalating to a human — round 3 does not converge

Round 3 re-reviewed the already-converged round-2 state (01f964f0) and found 6 new actionable findings (1 Major + 4 Minor + 1 Questions), all still open. No new fix commit this round: the Major finding is the same defect class round 2 just fixed (a composed skill's own unconditional approval round leaking into "quick mode asks nothing"), now recurring in a different surface that the round-2 guard structurally cannot see — that recurrence plus an untracked-scope call (finding 5) is what's being escalated rather than auto-fixed a 3rd time.

Rounds so far (per the working log — full detail in .pair/working/reviews/278.md)

  • Round 1 (67e02fd0) — 13 findings (4 Major + 7 Minor + 2 Questions), all resolved. Quick-mode notes added to Steps 2.2/3.1, the fallback tier given a real KB anchor, the PRD reframed as a precondition, nav-order regression fixed + pinned in conformance, plus 9 minor/question items (cascade-tier overlap, ADL safety-net claim, risk label/matrix, docs cross-link, wording, CP9 timing split, CP5 changelog, version bump, $mode: guided no-op).
  • Round 2 (01f964f0) — 9 findings (1 Major + 7 Minor + 1 Questions), all resolved. The Major finding routed assess-* through Path A's confirmation round inside "asks no questions" in Step 2.2 — fixed by suppressing Path A's confirmation as a disclosed deviation (ADL + quick-mode-defaults.md § Disclosed deviations + CP9 assertion), plus 8 minor/question fixes (Step 2.3 emphasis consistency, testing/AI-tooling defaults named explicitly, MT-CP906 preconditions, INTERVIEW_MARKERS gap, ADL markdownlint, checklist formatter churn revert, PR description staleness, AC1 wording amended on the story).
  • Round 3 (this round, HEAD 01f964f0, no new commit) — re-review found the same defect class recurring in a new surface. Not fixed — escalated below.

Still-open findings (round 3)

  1. [Major] Phase 3.5 (the composed /pair-capability-map-subdomains + /pair-capability-map-contexts calls) has no **Quick mode**: note, and both composed skills carry their own unconditional developer-approval round (map-subdomains/SKILL.md:97,99, map-contexts/SKILL.md:108,110) — falsifying "at most two questions" (bootstrap-quick-mode.mdx:29), "everything else resolves without a question" (quick-mode-defaults.md:60), and CP9 MT-CP903's "no question outside the two still-asked decisions" (CP9:98). Sub-case: map-contexts/SKILL.md:151's HALT-on-unbalanced+volatile relationship contradicts quick-mode-defaults.md:48's "never blocking". Same defect class and same fix shape as round 2's Major finding (a step note + a disclosed-deviation entry + one assertion + one CP line) — locations: SKILL.md:204-220 + dataset mirror, quick-mode-defaults.md:48,60 + dataset mirror, bootstrap-quick-mode.mdx:29, CP9:98.
  2. [Minor] quick-mode-defaults.md:68 (+ dataset mirror) attributes already-configured gate-registry detection to /pair-capability-setup-gates, which bootstrap never composes (absent from the Composed Skills table; Step 3.2 does that detection itself).
  3. [Minor] SKILL.md:305 (+ dataset mirror) Graceful Degradation bullet ("assess-* skills not installed: … ask developer for manual decisions") is not depth-qualified, contradicting Step 2.2's own quick-mode note that the manual-assessment path also asks nothing in quick mode.
  4. [Minor] PR description's Summary → What Changed first bullet still shows stale line counts (+40/+30 vs actual +43/+38 dataset / mirror per git diff origin/main...HEAD --numstat) — same staleness class as round-1 finding 8.
  5. [Minor] The deferred "first-class non-interactive signal on the assess-* family" fix (ADL:40, quick-mode-defaults.md:19) has no tracked issue number, and finding 1 above extends the same gap to the map-* family — strengthens the case for filing one tracked story now rather than carrying it as an undated disclosed deviation.
  6. [Questions] Both story Quickstart path in bootstrap — opinionated one-command setup #278 QA DoD items (timed onboarding test, guided-mode regression) are unchecked, and CP9 is designed/registered but not executed — so AC1's <10-minute KPI is unmeasured at merge, and MT-CP903 as currently written asserts behaviour finding 1 shows to be currently unreachable.

Convention for continuation

Per the loop convention: any further rework or re-review — including manual out-of-band rounds — should be funneled into the working log .pair/working/reviews/278.md (append), not posted as standalone PR comments. The next orchestrated run on this story continues this same cycle; its eventual convergence will synthesize ONE final remediation comment and minimize this one plus the round-2 intermediate state (never the first-review comment above).

Note for whoever picks this up: the working log is an untracked file living only in the persistent authoring worktree ../pair-worktrees/278 — that worktree must be preserved until merge, or the audit trail (rounds 1-3 detail) is lost. This comment and the first-review comment remain on the PR regardless, and the first-review comment's marker still prevents a duplicate first review on the next run.

Do NOT merge — open findings above, plus the two escalation questions in finding 1 (fix-in-this-PR vs. deferred with a filed issue) and finding 6 (CP9 gates merge or runs post-merge), need a human call.

… ask

Round 3's Major finding, and it is the SAME defect class round 2 fixed, in a
surface round 2's guard structurally cannot see: Phase 3.5 composes
/map-subdomains and /map-contexts, and BOTH end in an unconditional
"Approve or adjust?". So "at most two questions" was false again, two questions
further on.

Why the round-2 guard missed it: that guard derives "question-bearing" steps
from a step's OWN text — a blockquote question, an ask-N rule, an approval
round. Phase 3.5's steps contain none of those; the questions live inside the
skills it composes. A caller-side note cannot see the next composed skill that
asks, which is exactly why the real fix is a non-interactive signal on the
composed families — filed as #410, and referenced from both deviations.

- SKILL.md Phase 3.5: quick-mode note, both corpora
- quick-mode-defaults.md: disclosed deviations go from two to three; the Phase
  3.5 cascade row no longer claims "never blocking"
- ONE GATE KEPT DELIBERATELY: /map-contexts HALTs on an unbalanced + volatile
  relationship offered with neither mitigation nor acceptance. Quick mode does
  NOT suppress it — writing a domain model that records a coupling risk nobody
  judged is worse than one more question. Documented in the skill, the sibling,
  the docs page and CP9's MT-CP903, and pinned so a future "ask nothing at all"
  change cannot silently swallow it.
- bootstrap-quick-mode.mdx: the rarer third case stated instead of "two"
- CP9 MT-CP903: the map-* rounds added to the no-question assertion, with the
  HALT named as the one admissible exception

Minor — quick-mode-defaults.md attributed gate-registry detection to
/setup-gates, which bootstrap never composes (Step 3.2 does it). The Graceful
Degradation bullet for missing assess-* skills was not depth-qualified, and read
as if the manual path asks in quick mode too.

NOT touched, deliberately: map-subdomains/SKILL.md and map-contexts/SKILL.md are
modified by PR #387. Editing them would destroy this PR's zero-collision
property, which is its main merit at the merge gate. The fix is caller-side, as
round 2's was; #410 does it properly once #387 has merged.

Both mirrors REGENERATED with the real transform rather than hand-ported: my
hand-port drifted by one character (the pipeline prepends `./` to a same-dir
link) and #352's mirror-equality guard caught it. The sibling was regenerated
through applyKnownMirrorTransforms for the same reason.

44 conformance assertions, 98 with the mirror suite. `pnpm quality-gate` green.
All new relative links verified to resolve on this branch.

Refs #278 · #410

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions
github-actions Bot temporarily deployed to Website Preview July 31, 2026 11:39 Inactive
@rucka

rucka commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator Author

Remediation report — PR #408 · story #278

Synthesis across three review rounds. 28 findings total (6 Major · 18 Minor · 4 Questions) → 0 open actionable findings, with one item that is genuinely the human's call, stated at the end rather than resolved.

Head at verification: f15478b4 · pnpm quality-gate green (22 + 12 tasks) · conformance 44, 98 with the mirror suite · every new relative link verified to resolve on this branch.

Round Commit Findings Outcome
1 67e02fd0 13 (4 Major · 7 Minor · 2 Q) all resolved
2 01f964f0 9 (1 Major · 7 Minor · 1 Q) all resolved
3 f15478b4 6 (1 Major · 4 Minor · 1 Q) 5 resolved, 1 escalated (below)

The finding that matters, and why it recurred

Rounds 2 and 3 found the same defect class in two different surfaces: a composed skill's own unconditional approval round leaking into a depth that claims to ask nothing.

  • Round 2 — Step 2.2 composed the assess-* family through Path A, whose cascade steps 3-4 ask for confirmation. Up to eight questions.
  • Round 3 — Phase 3.5 composes /map-subdomains and /map-contexts, and both end in "Approve or adjust?". Two more.

Why round 2's guard could not see round 3's instance, which is the interesting part: that guard derives "question-bearing steps" from a step's own text — a blockquote question, an ask-N rule, an approval round — and then requires a quick-mode note on each. Phase 3.5's steps contain none of those. The questions live inside the skills it composes. A caller-side note structurally cannot see the next composed skill that asks.

So the fix applied here is, honestly, another surface-specific patch: Phase 3.5 gets its note, deviation 3 is disclosed, and a new assertion pins it. That closes the known instance and nothing more. The real fix is a first-class non-interactive signal on the composed families — filed as #410, referenced from both deviations, and blocked on #387 (which owns both map-* skills).

One gate kept, deliberately

/map-contexts HALTs on a relationship that is both unbalanced and volatile when neither a mitigation nor an explicit acceptance is offered. Quick mode does not suppress it. Accepting it silently would write a domain model recording a coupling risk nobody judged — worse than one more question. The quick-mode-defaults.md Phase 3.5 row therefore no longer claims "never blocking", and there is an assertion that fails if a future "ask nothing at all" change swallows this gate.

Round 3 — the rest

# Finding Outcome
2 quick-mode-defaults.md attributed gate-registry detection to /setup-gates, which bootstrap never composes (absent from the Composed Skills table; Step 3.2 does it) Fixed — attribution split: PM check is /setup-pm's, the gate-registry check is Step 3.2's
3 The Graceful Degradation bullet for missing assess-* skills was not depth-qualified, so it read as if the manual path asks in quick mode too — contradicting Step 2.2's own note Fixed — qualified guided-only, with the quick-mode behaviour named
4 PR description carried stale line counts Fixed — measured at head: SKILL.md +43/−8 dataset, +38/−3 mirror
5 The deferred non-interactive-signal fix had no tracked issue, and round 3 widened the gap from one family to two Fixed#410 filed, assigned, on the board, and cited from both disclosed deviations

Two things my own work got wrong, caught by the guards

  1. The mirror drifted by one character. I hand-ported the Phase 3.5 note and wrote ](quick-mode-defaults.md) where the real pipeline emits ](./quick-mode-defaults.md) — it prepends ./ to a same-dir link when the file moves. tech-debt: extend mirror-equality guard to per-skill SKILL.md pairs (all 36 skills) #352's mirror-equality guard caught it and printed expected-vs-actual. Both mirrors are now regenerated with the real transform instead of hand-ported, which is the correct method and what I should have used from the start.
  2. The sibling mirror had two spurious blank lines from the same hand-porting. Caught by the sibling-parity assertion this PR itself introduced.

Both are arguments for the guard this story ships against the author who ships it — which is the better kind of evidence.

⛔ Needs your call, not mine — AC1 is unmeasured at merge

Round 3's Question, and I am not resolving it by fiat:

  • Story Quickstart path in bootstrap — opinionated one-command setup #278's two QA DoD items — the timed onboarding test and the guided-mode regression — are unchecked, and CP9 is designed and registered but has never been executed.
  • So AC1's "<10 minutes" is unverified at merge. The PR body already states the KPI rests on a manual scenario rather than CI; what it cannot decide is whether that scenario gates the merge or runs after it.
  • Related: MT-CP903 asserted behaviour that round 3's Major showed to be currently unreachable. That assertion is now corrected, but correcting an assertion is not the same as running it.

Two honest options: run CP9 before merging (buys the headline number, costs a manual pass on an empty repo), or merge and run it after, accepting that the <10-minute claim is a design intent until someone times it. The second is defensible — nothing else in the PR depends on the number — but it should be a decision, not an omission.

Verdict: everything actionable is resolved; TECH-DEBT rather than APPROVED is the honest label, carrying #410 (the structural fix) and the unmeasured KPI to the merge gate as named, accepted items.

rucka added a commit that referenced this pull request Jul 31, 2026
…es re-anchored, wrappers deduped

Guard (pre-push-gate-composition.ts):
- expansion tolerates runner flags and npm/yarn: `pnpm -s format`, `pnpm -w format`,
  `npm run format` all reached the write-mode formatter with a green guard, because the
  captured "script name" was the flag and the body was never scanned.
- offender list made symmetric per tool: bin alias / .sh entrypoint / raw CLI write flag
  (`prettier-fix`, `markdownlint-fix`, `prettier --write`, `markdownlint --fix`) — the
  prettier `.sh` form used to walk straight past a list that named markdownlint's.
- guard-present check requires RUNNING it (`referencesScript`), so `echo gate:composition`
  no longer satisfies it.
- docstring: offenders come back in the offender list's order, not the gate's.

Wrappers:
- ignore assembly extracted per tool (`bin/_ignore-args.sh`, `bin/_ignore-file.sh`); check
  and fix now share one source of the invariant instead of four copies.
- prettier args assembled positionally, so a repo path containing a space no longer
  word-splits into a bogus pattern (prettier exited 2 on every push for that contributor).
- root .gitignore re-anchored to the cwd for markdownlint (`_reanchor-gitignore.awk`): it
  resolves patterns against the cwd, git against the ignore file's dir, so a path-anchored
  entry (`apps/website/gen/`) would have blocked every push from that package.
- cwd/git-root de-dup compares canonical paths (`pwd -P`), same structure in both tools.

Coverage + caching:
- new smoke test `format-ignore-delegation.sh` (both tools, check and fix, gitignored vs
  not, plus a path with a space) — verified RED against the pre-fix wrappers; wired into
  the CI list.
- turbo.json `globalDependencies`: the ignore sources are inputs of cacheable tasks, so a
  .gitignore edit no longer replays a stale PASS/FAIL.

ADL: Context now cites the incidents actually observed (PRs #388, #408, #411 — three in
two days, with story+branch each) and records the re-anchoring, the shared helpers, the
smoke coverage and the globalDependencies.

Refs: #394
rucka added a commit that referenced this pull request Jul 31, 2026
…transform

`main` went red the moment #387 and #406 were both on it, and neither PR was
wrong. #387 (brainstorm's new `resume.md` / `parametrization.md` siblings) was
green before #406 widened the mirror-equality guard beyond `SKILL.md`; #406 was
green before those siblings existed. Merging them in EITHER order produces this
failure, so no single PR's CI could have caught it.

The cause is mine: I hand-ported those siblings to the root mirror in #387
instead of regenerating them through the real transform.

- `parametrization.md` — a missing blank line before `## $domain-placed`.
- `resume.md` — SUBSTANTIVE, not cosmetic. The hand-port applied the
  skill-reference rewrite to a FILE NAME, shipping the handoff key as
  `.pair/working/pair-process-brainstorm-<root-id | theme-slug>.md` where the
  dataset says `.pair/working/brainstorm-<root-id | theme-slug>.md`. The real
  transform does not rewrite it — it is a working-file name, not a skill
  reference — so the shipped mirror documented a different handoff key than its
  authoring source. A resume reading one and a write using the other never meet.
- `SKILL.md` + the dataset twin — emphasis style. Surfaced only while fixing the
  above, and its cause is the defect #394 fixes: the gate's `mdlint:fix` runs in
  WRITE mode, so my own gate run rewrote the DATASET's emphasis markers, leaving
  the mirror behind. The manual gate passed because it was reformatting as it
  ran; the pre-push hook then compared the rewritten dataset against the
  untouched mirror. Kept the gate's formatting (it is this repo's authority) and
  realigned the mirror.

Third time today a hand-ported mirror drifted from the transform (#408 by one
`./`, #411 likewise). The lesson is applied on the open branches: regenerate,
never hand-port.

`pnpm quality-gate` green — knowledge-hub 715 tests, mirror guard 82.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@rucka
rucka merged commit 8f8956b into main Jul 31, 2026
3 checks passed
rucka added a commit that referenced this pull request Jul 31, 2026
Test-first: the guard was written and verified RED against the repo's own
package.json before the gate changed.

The gate ran `prettier:fix` and `mdlint:fix` REPO-WIDE in write mode, and the
gate is the pre-push hook. The decisive problem is not noise, it is
uselessness: at pre-push THE COMMITS ALREADY EXIST, so a write-mode formatter
rewrites the working tree and cannot fix what is being pushed. Its output goes
nowhere unless the author notices and amends — so the author either sweeps
unrelated reformats into the next commit or pushes with `--no-verify`, and once
bypassing is routine the hook asserts nothing.

Observed three times in two days: #388 was pushed with --no-verify after the
hook reformatted two unrelated pair-cli test files; the same two files were
swept into #411 by a `git add -A` and had to be reverted; and they were
excluded by hand from #408.

- `format` — the explicit fix command (was the gate's write-mode step)
- `format:check` — what the gate runs now
- `gate:composition` — a tested module that reads the root package.json and
  fails if a write-mode formatter is ever put back. The regression is a
  one-word edit away and its symptom looks like author error rather than
  tooling behaviour, which is why a comment would not have been enough.
- `**/.source/` prettier-ignored: generated by fumadocs-mdx at postinstall and
  already gitignored. In write mode the gate silently rewrote it on every push;
  in check mode it would have BLOCKED every push. A build artifact must not be
  able to do either.

Includes the one-time sweep check mode requires: the two pair-cli
version-check test files are formatted here. Sweeping unrelated files in the PR
that forbids sweeping them is deliberate — the drift has to be cleared once for
check mode to be viable, and after this the gate cannot produce such sweeps.

Guard logic in a tested module under packages/dev-tools/src/quality-gates/ with
a thin CLI entrypoint, per ADL 2026-07-13. The offender list is explicit rather
than a `/:fix/` pattern: `lint:fix` is an eslint autofix, a different concern,
and is asserted NOT to trip the guard.

`pnpm quality-gate` green, and it now prints
"✓ pre-push gate composition: check-mode only".

Closes #394

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
rucka added a commit that referenced this pull request Jul 31, 2026
…es re-anchored, wrappers deduped

Guard (pre-push-gate-composition.ts):
- expansion tolerates runner flags and npm/yarn: `pnpm -s format`, `pnpm -w format`,
  `npm run format` all reached the write-mode formatter with a green guard, because the
  captured "script name" was the flag and the body was never scanned.
- offender list made symmetric per tool: bin alias / .sh entrypoint / raw CLI write flag
  (`prettier-fix`, `markdownlint-fix`, `prettier --write`, `markdownlint --fix`) — the
  prettier `.sh` form used to walk straight past a list that named markdownlint's.
- guard-present check requires RUNNING it (`referencesScript`), so `echo gate:composition`
  no longer satisfies it.
- docstring: offenders come back in the offender list's order, not the gate's.

Wrappers:
- ignore assembly extracted per tool (`bin/_ignore-args.sh`, `bin/_ignore-file.sh`); check
  and fix now share one source of the invariant instead of four copies.
- prettier args assembled positionally, so a repo path containing a space no longer
  word-splits into a bogus pattern (prettier exited 2 on every push for that contributor).
- root .gitignore re-anchored to the cwd for markdownlint (`_reanchor-gitignore.awk`): it
  resolves patterns against the cwd, git against the ignore file's dir, so a path-anchored
  entry (`apps/website/gen/`) would have blocked every push from that package.
- cwd/git-root de-dup compares canonical paths (`pwd -P`), same structure in both tools.

Coverage + caching:
- new smoke test `format-ignore-delegation.sh` (both tools, check and fix, gitignored vs
  not, plus a path with a space) — verified RED against the pre-fix wrappers; wired into
  the CI list.
- turbo.json `globalDependencies`: the ignore sources are inputs of cacheable tasks, so a
  .gitignore edit no longer replays a stale PASS/FAIL.

ADL: Context now cites the incidents actually observed (PRs #388, #408, #411 — three in
two days, with story+branch each) and records the re-anchoring, the shared helpers, the
smoke coverage and the globalDependencies.

Refs: #394
rucka added a commit that referenced this pull request Jul 31, 2026
…rs the repo's write scripts

11 findings (2 Major, 9 Minor), all resolved.

Major:
- Rebased onto current origin/main (twice — #389/#391, then #405/#408 landed
  mid-round) and cleared main's format baseline in its own commit, so
  `format:check` is green on the tree this actually lands on (AC3). The
  sync-version-in-docs.ts conflict with #391 keeps BOTH docstrings.
- The advertised remedy was a trap: `pnpm format` fixes the dataset SKILL.md and
  cannot reach its generated .claude twin (not a workspace member), while
  skill-md-mirror asserts byte equality — so format:check-green became
  skills:conformance-red later in the SAME gate. Reproduced end-to-end. The
  two-step remedy is now stated in all three places that advertise it
  (DEVELOPMENT.md, the mdx twin, PRE_PUSH_REMEDY) and unit-tested; the
  structural fix is noted on #414.

Minor:
- Guard widened to the repo's real write scripts: `sync-version`
  (→ sync-version-in-docs.ts, writeFileSync across every .md/.mdx it walks;
  `--check` dry-run spared, bounded to the same command segment) and
  `test:perf` (→ benchmark-update-link.ts, no dry-run, banned outright).
  6 tests, verified RED. The ADL + way-of-working now state that what is
  enforced is the explicit list, not the invariant in general.
- `_reanchor-gitignore.awk`: `[!abc]` → `[^abc]` (ERE negates with ^, gitignore
  with !) — unfixed it matched a literal `!`, i.e. the inverse set, silently
  dropping the pattern. Pinned by a row in the table-driven smoke block
  (`apps/[!x]ebsite/build/`), verified RED. Known-approximation note extended
  to cover bracket expressions and the `[]abc]` leading-`]` case.
- `_ignore-file.sh` "Effect:" now warns the EXIT trap REPLACES the caller's.
- `format:check` aggregates instead of short-circuiting, so one run names both
  prettier AND markdownlint drift. Verified: the `&&` form hid the markdown
  violation entirely.
- turbo.json `//` comment records the globalDependencies blast radius as a
  deliberate over-approximation, and why the per-task `inputs` option was
  passed over.
- DEVELOPMENT.md and the mdx twin are now byte-identical modulo the link form
  (a `diff` of the two paragraphs is a one-line diff when in sync); command
  blocks mirrored both ways (`mdlint:check` added, `(prettier only)` added).

The two remaining PR-description findings (a false "were removed" parenthetical
and the stale #389/#391 merge-order section) are fixed in the PR body, not here.

NOTE: `pnpm turbo test` is red on this base for TWO reasons that pre-date and
have nothing to do with #394 — both reproduced on a pristine origin/main
worktree: skill-md-mirror on process/bootstrap/quick-mode-defaults.md (#408
merged an unregenerated .claude mirror — the very coupling this round
documents) and code-host-routing AC4 on assess-cost/SKILL.md:106 (#388 prose +
#389 audit merge-order collision). main's own CI is failing.
rucka added a commit that referenced this pull request Jul 31, 2026
… landing

Third and fourth instance today of the same class: two PRs each green on their
own branch, red once both are on main, because each PR's guard only ever saw its
own branch. Neither PR was wrong either time.

1. **#388 + #389.** #389's AC4 audit forbids a skill doc from reading a PR "from
   the PM tool". #388's `assess-cost` report mode reads the window's merged PRs
   "from the PM tool / code host" — correctly routed, with a pointer to the
   resolution convention, so it is a FALSE POSITIVE of the guard: the pattern
   tempers itself against `code host` only in the 60 characters BEFORE
   "the PM tool", and here it comes after. Reordered to "from the code host / PM
   tool", which is also the more accurate reading — a PR is a code-host object,
   so naming that side first is right independently of the guard.

   Recorded for whoever tunes that pattern next: the temper is order-dependent,
   so `PRs … from the PM tool … (code host)` would still pass. Not widened here —
   the guard belongs to #236 and this is a main-fix, not a scope change.

2. **#408 + #406.** The bootstrap sibling's mirror shipped `[SKILL.md](SKILL.md)`
   where the real pipeline emits `[SKILL.md](./SKILL.md)` — it prepends `./` to a
   same-dir link when the file moves. #408's own sibling-parity test tolerates
   exactly that shape (it calls `neutralizeSameDirDotSlash` on both sides), while
   #406's widened mirror guard does not. So the escape hatch in one test is what
   let it reach main, where the other guard caught it.

Both fixes are one line. What is not one line is the pattern: four times today a
merge of two green PRs produced a red main. The common cause is that every guard
runs against its own branch, so an interaction is only ever observable after the
second merge — and nothing runs the full gate on the post-merge state before it
is pushed.

`pnpm quality-gate` green — 22 + 12 tasks.
rucka added a commit that referenced this pull request Jul 31, 2026
Test-first: the guard was written and verified RED against the repo's own
package.json before the gate changed.

The gate ran `prettier:fix` and `mdlint:fix` REPO-WIDE in write mode, and the
gate is the pre-push hook. The decisive problem is not noise, it is
uselessness: at pre-push THE COMMITS ALREADY EXIST, so a write-mode formatter
rewrites the working tree and cannot fix what is being pushed. Its output goes
nowhere unless the author notices and amends — so the author either sweeps
unrelated reformats into the next commit or pushes with `--no-verify`, and once
bypassing is routine the hook asserts nothing.

Observed three times in two days: #388 was pushed with --no-verify after the
hook reformatted two unrelated pair-cli test files; the same two files were
swept into #411 by a `git add -A` and had to be reverted; and they were
excluded by hand from #408.

- `format` — the explicit fix command (was the gate's write-mode step)
- `format:check` — what the gate runs now
- `gate:composition` — a tested module that reads the root package.json and
  fails if a write-mode formatter is ever put back. The regression is a
  one-word edit away and its symptom looks like author error rather than
  tooling behaviour, which is why a comment would not have been enough.
- `**/.source/` prettier-ignored: generated by fumadocs-mdx at postinstall and
  already gitignored. In write mode the gate silently rewrote it on every push;
  in check mode it would have BLOCKED every push. A build artifact must not be
  able to do either.

Includes the one-time sweep check mode requires: the two pair-cli
version-check test files are formatted here. Sweeping unrelated files in the PR
that forbids sweeping them is deliberate — the drift has to be cleared once for
check mode to be viable, and after this the gate cannot produce such sweeps.

Guard logic in a tested module under packages/dev-tools/src/quality-gates/ with
a thin CLI entrypoint, per ADL 2026-07-13. The offender list is explicit rather
than a `/:fix/` pattern: `lint:fix` is an eslint autofix, a different concern,
and is asserted NOT to trip the guard.

`pnpm quality-gate` green, and it now prints
"✓ pre-push gate composition: check-mode only".

Closes #394

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
rucka added a commit that referenced this pull request Jul 31, 2026
…es re-anchored, wrappers deduped

Guard (pre-push-gate-composition.ts):
- expansion tolerates runner flags and npm/yarn: `pnpm -s format`, `pnpm -w format`,
  `npm run format` all reached the write-mode formatter with a green guard, because the
  captured "script name" was the flag and the body was never scanned.
- offender list made symmetric per tool: bin alias / .sh entrypoint / raw CLI write flag
  (`prettier-fix`, `markdownlint-fix`, `prettier --write`, `markdownlint --fix`) — the
  prettier `.sh` form used to walk straight past a list that named markdownlint's.
- guard-present check requires RUNNING it (`referencesScript`), so `echo gate:composition`
  no longer satisfies it.
- docstring: offenders come back in the offender list's order, not the gate's.

Wrappers:
- ignore assembly extracted per tool (`bin/_ignore-args.sh`, `bin/_ignore-file.sh`); check
  and fix now share one source of the invariant instead of four copies.
- prettier args assembled positionally, so a repo path containing a space no longer
  word-splits into a bogus pattern (prettier exited 2 on every push for that contributor).
- root .gitignore re-anchored to the cwd for markdownlint (`_reanchor-gitignore.awk`): it
  resolves patterns against the cwd, git against the ignore file's dir, so a path-anchored
  entry (`apps/website/gen/`) would have blocked every push from that package.
- cwd/git-root de-dup compares canonical paths (`pwd -P`), same structure in both tools.

Coverage + caching:
- new smoke test `format-ignore-delegation.sh` (both tools, check and fix, gitignored vs
  not, plus a path with a space) — verified RED against the pre-fix wrappers; wired into
  the CI list.
- turbo.json `globalDependencies`: the ignore sources are inputs of cacheable tasks, so a
  .gitignore edit no longer replays a stale PASS/FAIL.

ADL: Context now cites the incidents actually observed (PRs #388, #408, #411 — three in
two days, with story+branch each) and records the re-anchoring, the shared helpers, the
smoke coverage and the globalDependencies.

Refs: #394
rucka added a commit that referenced this pull request Jul 31, 2026
…rs the repo's write scripts

11 findings (2 Major, 9 Minor), all resolved.

Major:
- Rebased onto current origin/main (twice — #389/#391, then #405/#408 landed
  mid-round) and cleared main's format baseline in its own commit, so
  `format:check` is green on the tree this actually lands on (AC3). The
  sync-version-in-docs.ts conflict with #391 keeps BOTH docstrings.
- The advertised remedy was a trap: `pnpm format` fixes the dataset SKILL.md and
  cannot reach its generated .claude twin (not a workspace member), while
  skill-md-mirror asserts byte equality — so format:check-green became
  skills:conformance-red later in the SAME gate. Reproduced end-to-end. The
  two-step remedy is now stated in all three places that advertise it
  (DEVELOPMENT.md, the mdx twin, PRE_PUSH_REMEDY) and unit-tested; the
  structural fix is noted on #414.

Minor:
- Guard widened to the repo's real write scripts: `sync-version`
  (→ sync-version-in-docs.ts, writeFileSync across every .md/.mdx it walks;
  `--check` dry-run spared, bounded to the same command segment) and
  `test:perf` (→ benchmark-update-link.ts, no dry-run, banned outright).
  6 tests, verified RED. The ADL + way-of-working now state that what is
  enforced is the explicit list, not the invariant in general.
- `_reanchor-gitignore.awk`: `[!abc]` → `[^abc]` (ERE negates with ^, gitignore
  with !) — unfixed it matched a literal `!`, i.e. the inverse set, silently
  dropping the pattern. Pinned by a row in the table-driven smoke block
  (`apps/[!x]ebsite/build/`), verified RED. Known-approximation note extended
  to cover bracket expressions and the `[]abc]` leading-`]` case.
- `_ignore-file.sh` "Effect:" now warns the EXIT trap REPLACES the caller's.
- `format:check` aggregates instead of short-circuiting, so one run names both
  prettier AND markdownlint drift. Verified: the `&&` form hid the markdown
  violation entirely.
- turbo.json `//` comment records the globalDependencies blast radius as a
  deliberate over-approximation, and why the per-task `inputs` option was
  passed over.
- DEVELOPMENT.md and the mdx twin are now byte-identical modulo the link form
  (a `diff` of the two paragraphs is a one-line diff when in sync); command
  blocks mirrored both ways (`mdlint:check` added, `(prettier only)` added).

The two remaining PR-description findings (a false "were removed" parenthetical
and the stale #389/#391 merge-order section) are fixed in the PR body, not here.

NOTE: `pnpm turbo test` is red on this base for TWO reasons that pre-date and
have nothing to do with #394 — both reproduced on a pristine origin/main
worktree: skill-md-mirror on process/bootstrap/quick-mode-defaults.md (#408
merged an unregenerated .claude mirror — the very coupling this round
documents) and code-host-routing AC4 on assess-cost/SKILL.md:106 (#388 prose +
#389 audit merge-order collision). main's own CI is failing.
rucka added a commit that referenced this pull request Aug 1, 2026
Test-first: the guard was written and verified RED against the repo's own
package.json before the gate changed.

The gate ran `prettier:fix` and `mdlint:fix` REPO-WIDE in write mode, and the
gate is the pre-push hook. The decisive problem is not noise, it is
uselessness: at pre-push THE COMMITS ALREADY EXIST, so a write-mode formatter
rewrites the working tree and cannot fix what is being pushed. Its output goes
nowhere unless the author notices and amends — so the author either sweeps
unrelated reformats into the next commit or pushes with `--no-verify`, and once
bypassing is routine the hook asserts nothing.

Observed three times in two days: #388 was pushed with --no-verify after the
hook reformatted two unrelated pair-cli test files; the same two files were
swept into #411 by a `git add -A` and had to be reverted; and they were
excluded by hand from #408.

- `format` — the explicit fix command (was the gate's write-mode step)
- `format:check` — what the gate runs now
- `gate:composition` — a tested module that reads the root package.json and
  fails if a write-mode formatter is ever put back. The regression is a
  one-word edit away and its symptom looks like author error rather than
  tooling behaviour, which is why a comment would not have been enough.
- `**/.source/` prettier-ignored: generated by fumadocs-mdx at postinstall and
  already gitignored. In write mode the gate silently rewrote it on every push;
  in check mode it would have BLOCKED every push. A build artifact must not be
  able to do either.

Includes the one-time sweep check mode requires: the two pair-cli
version-check test files are formatted here. Sweeping unrelated files in the PR
that forbids sweeping them is deliberate — the drift has to be cleared once for
check mode to be viable, and after this the gate cannot produce such sweeps.

Guard logic in a tested module under packages/dev-tools/src/quality-gates/ with
a thin CLI entrypoint, per ADL 2026-07-13. The offender list is explicit rather
than a `/:fix/` pattern: `lint:fix` is an eslint autofix, a different concern,
and is asserted NOT to trip the guard.

`pnpm quality-gate` green, and it now prints
"✓ pre-push gate composition: check-mode only".

Closes #394

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
rucka added a commit that referenced this pull request Aug 1, 2026
…es re-anchored, wrappers deduped

Guard (pre-push-gate-composition.ts):
- expansion tolerates runner flags and npm/yarn: `pnpm -s format`, `pnpm -w format`,
  `npm run format` all reached the write-mode formatter with a green guard, because the
  captured "script name" was the flag and the body was never scanned.
- offender list made symmetric per tool: bin alias / .sh entrypoint / raw CLI write flag
  (`prettier-fix`, `markdownlint-fix`, `prettier --write`, `markdownlint --fix`) — the
  prettier `.sh` form used to walk straight past a list that named markdownlint's.
- guard-present check requires RUNNING it (`referencesScript`), so `echo gate:composition`
  no longer satisfies it.
- docstring: offenders come back in the offender list's order, not the gate's.

Wrappers:
- ignore assembly extracted per tool (`bin/_ignore-args.sh`, `bin/_ignore-file.sh`); check
  and fix now share one source of the invariant instead of four copies.
- prettier args assembled positionally, so a repo path containing a space no longer
  word-splits into a bogus pattern (prettier exited 2 on every push for that contributor).
- root .gitignore re-anchored to the cwd for markdownlint (`_reanchor-gitignore.awk`): it
  resolves patterns against the cwd, git against the ignore file's dir, so a path-anchored
  entry (`apps/website/gen/`) would have blocked every push from that package.
- cwd/git-root de-dup compares canonical paths (`pwd -P`), same structure in both tools.

Coverage + caching:
- new smoke test `format-ignore-delegation.sh` (both tools, check and fix, gitignored vs
  not, plus a path with a space) — verified RED against the pre-fix wrappers; wired into
  the CI list.
- turbo.json `globalDependencies`: the ignore sources are inputs of cacheable tasks, so a
  .gitignore edit no longer replays a stale PASS/FAIL.

ADL: Context now cites the incidents actually observed (PRs #388, #408, #411 — three in
two days, with story+branch each) and records the re-anchoring, the shared helpers, the
smoke coverage and the globalDependencies.

Refs: #394
rucka added a commit that referenced this pull request Aug 1, 2026
…rs the repo's write scripts

11 findings (2 Major, 9 Minor), all resolved.

Major:
- Rebased onto current origin/main (twice — #389/#391, then #405/#408 landed
  mid-round) and cleared main's format baseline in its own commit, so
  `format:check` is green on the tree this actually lands on (AC3). The
  sync-version-in-docs.ts conflict with #391 keeps BOTH docstrings.
- The advertised remedy was a trap: `pnpm format` fixes the dataset SKILL.md and
  cannot reach its generated .claude twin (not a workspace member), while
  skill-md-mirror asserts byte equality — so format:check-green became
  skills:conformance-red later in the SAME gate. Reproduced end-to-end. The
  two-step remedy is now stated in all three places that advertise it
  (DEVELOPMENT.md, the mdx twin, PRE_PUSH_REMEDY) and unit-tested; the
  structural fix is noted on #414.

Minor:
- Guard widened to the repo's real write scripts: `sync-version`
  (→ sync-version-in-docs.ts, writeFileSync across every .md/.mdx it walks;
  `--check` dry-run spared, bounded to the same command segment) and
  `test:perf` (→ benchmark-update-link.ts, no dry-run, banned outright).
  6 tests, verified RED. The ADL + way-of-working now state that what is
  enforced is the explicit list, not the invariant in general.
- `_reanchor-gitignore.awk`: `[!abc]` → `[^abc]` (ERE negates with ^, gitignore
  with !) — unfixed it matched a literal `!`, i.e. the inverse set, silently
  dropping the pattern. Pinned by a row in the table-driven smoke block
  (`apps/[!x]ebsite/build/`), verified RED. Known-approximation note extended
  to cover bracket expressions and the `[]abc]` leading-`]` case.
- `_ignore-file.sh` "Effect:" now warns the EXIT trap REPLACES the caller's.
- `format:check` aggregates instead of short-circuiting, so one run names both
  prettier AND markdownlint drift. Verified: the `&&` form hid the markdown
  violation entirely.
- turbo.json `//` comment records the globalDependencies blast radius as a
  deliberate over-approximation, and why the per-task `inputs` option was
  passed over.
- DEVELOPMENT.md and the mdx twin are now byte-identical modulo the link form
  (a `diff` of the two paragraphs is a one-line diff when in sync); command
  blocks mirrored both ways (`mdlint:check` added, `(prettier only)` added).

The two remaining PR-description findings (a false "were removed" parenthetical
and the stale #389/#391 merge-order section) are fixed in the PR body, not here.

NOTE: `pnpm turbo test` is red on this base for TWO reasons that pre-date and
have nothing to do with #394 — both reproduced on a pristine origin/main
worktree: skill-md-mirror on process/bootstrap/quick-mode-defaults.md (#408
merged an unregenerated .claude mirror — the very coupling this round
documents) and code-host-routing AC4 on assess-cost/SKILL.md:106 (#388 prose +
#389 audit merge-order collision). main's own CI is failing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:yellow Classification: medium risk tier

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Quickstart path in bootstrap — opinionated one-command setup

1 participant