Wire the repo guards that executed never, and the ratchet nothing ran - #1694
Conversation
…t nothing ran An audit of whether every check in this repo actually runs. Full method and per-guard verdicts in docs/reports/REPO_WIRING_AUDIT_2026-08-30.md. Two things were not running. **19 guard tests executed never.** vitest.config.ts already documented the trap and ships a self-check: 51 files in scripts/__tests__, 31 listed. The unlisted ones all import `node:test`, and nothing in this repo runs `node --test` — not a script, not a workflow. Promoting one is a port, not a config line. Run under node --test, all 19 fail. What matters is why, and it splits cleanly on whether the files each guard names still exist. Six fail because every path they reference was DELETED — traced to dated commits, mostly ffd0fd8 (the W1 Fairway consolidation) and a259fa2 (the dead player-CoachHelm cluster). Ten fail on real violations in files that exist. promoted admin-tables-mobile, no-arbitrary-text-px-fairway-pages — stale targets dropped, both now green. guards: 11 files/32 tests -> 13/37. deleted chart-tooltip-consolidated (all four subjects gone — a guard with an empty subject list is not a guard), genome-fluid (its subject was REWRITTEN onto recharts; it asserts a fixed viewBox and aspect-square on a hand-rolled SVG that no longer exists), and microcopy-banned-phrases (five of seven subjects rebuilt in #1058 and #984). Deleted rather than repaired: making a retired rule pass is implementing retired policy. repaired, badge-consolidation — six dead entries and one stale allowlist still red entry removed so its failure is now HONEST: two live CRM badges genuinely stopped delegating to <Badge>. Left unlisted. That tree is NOT dead — next.config.mjs:183 redirects /golf/admin on the exact path only, and 144 files live under it — so this is a colour-fidelity refactor, which is product work, not audit work. One path was a MOVE, not a deletion (GenomeRadar -> fairway/charts/). Worth separating: dropping a moved file silently loses coverage. **lint:duplicate-exports never ran.** It has a committed baseline (.duplicate-exports-baseline.json, 27 grandfathered) and exits 1 on anything new, and no job invoked it. A ratchet nothing compares against is a green that means nothing. Wired as a fifth step in the Lint ratchet job, following the existing continue-on-error + aggregate pattern so it reports its own outcome. Six other "unwired" scripts were false positives: CI invokes them as `node scripts/…` inside multi-line run: blocks, not `npm run <name>`. Recorded in the report as method, because the naive check is the obvious one to repeat. Bottleneck, measured rather than feared: the config warns these sweeps walk ~4,066 files each and carries a 120s timeout. The whole guards project runs in 1.48s and each promoted guard costs 0.1s. No argument for promoting in waves. Verified: typecheck 0, lint 0, npm test 1275 files / 12,209 passed, guards 37/37, duplicate-exports ratchet 0, docs:schema-drift 0, docs:path-drift 0, knowledge:check 0, inventory-check 0, markdown ratchet at baseline, ci.yml parses as valid YAML. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NbDxyygyXRUEERuGocpZZH
|
ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing |
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…#1694 #1693 was transitionally closed at its own merge; the grace ended when this branch added a commit past it. Cleared in the next ordinary PR, which registers itself at the same time. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NbDxyygyXRUEERuGocpZZH
…#1695 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NbDxyygyXRUEERuGocpZZH
* fix(lifecycle): stop inventing "no PR" for the canonical checkout's own branch
The PR lookup was skipped for the canonical checkout and substituted with a
literal:
const pr = w.branch && !isCanonical ? prFor(w.branch)
: { lookup: 'OK', state: 'NONE' };
`{ lookup: 'OK', state: 'NONE' }` does not mean "not checked". It means
"checked, and there is no PR" — and classifyBranch read it exactly as written,
returning UNKNOWN_PR ("no PR found — cannot prove the work landed") for
canonical's branch even with an OPEN PR against it. Reproduced against #1694
on 2026-08-30: `gh` answered `1694 OPEN` from the shell while the tool's own
report printed PR `NONE`.
Nothing was lost — UNKNOWN_PR fails safe to KEEP — but the tool was reaching a
right answer from an invented fact, in the evidence layer, which is the exact
failure this repo keeps removing everywhere else.
The shortcut also bought nothing. classifyWorktree returns ACTIVE for canonical
on its FIRST line, before any PR fact is read. Only the BRANCH verdict ever
consumed these — and that is the separation AGENTS.md insists on: may this
CHECKOUT go, versus may this BRANCH be deleted. The short-circuit conflated the
two inside the tool that defines the distinction.
The test took two attempts, and the first one is worth recording because it
looked fine. It passed with the bug reverted — because canonicalRoot() resolves
.claude/hooks/lib/workspace-identity.mjs against the repo under test, fixtures
do not have one, so isCanonical is ALWAYS false in the harness and the bug is
unreachable there. That null is deliberate and correct (a fixture must never be
able to claim it is the real canonical checkout), but it means every
canonical-only branch of this tool was untestable. The fixture now writes its
own identity stub, and the test asserts ACTIVE first — proving it really is
being treated as canonical — before asserting the branch verdict.
Verified by injection: reverting the one-line fix turns the new test red and
everything else green; restoring it returns the file byte-identical by sha256.
typecheck 0, lint 0, npm test 1275 files / 12,210 passed, guards 37/37.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NbDxyygyXRUEERuGocpZZH
* chore(control-plane): clear #1694's expired transitional row, register #1695
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NbDxyygyXRUEERuGocpZZH
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
An audit of one auditable question: does every check that exists actually run,
and does every ratchet actually ratchet? Full method and per-guard verdicts in
docs/reports/REPO_WIRING_AUDIT_2026-08-30.md.Two things were not running.
19 guard tests executed never
vitest.config.tsalready documented the trap and ships a self-check — 51 filesin
scripts/__tests__, 31 listed. The unlisted ones all importnode:test, andnothing in this repo runs
node --test. Promoting one is a port, not aconfig line.
Run under
node --test, all 19 fail. What matters is why, and it splitscleanly on whether the files each guard names still exist. Every missing path was
traced to a dated deletion commit — mostly
ffd0fd8ab(W1 Fairwayconsolidation) and
a259fa296(dead player-CoachHelm cluster).admin-tables-mobile,no-arbitrary-text-px-fairway-pages— stale targets dropped, both green.guards: 11 files/32 tests → 13/37chart-tooltip-consolidated,genome-fluid,microcopy-banned-phrases— subjects deleted or rewrittenbadge-consolidation— failure is now honest: two live CRM badges genuinely stopped delegating to<Badge>Deleted rather than repaired, deliberately: making a retired rule pass is
implementing retired policy.
genome-fluidis the clearest case — its subjectwas rewritten onto recharts, so it asserts a fixed
viewBoxandaspect-squareon a hand-rolled SVG that no longer exists.One path was a move, not a deletion (
GenomeRadar→fairway/charts/).Worth separating: dropping a moved file silently loses coverage.
Every one of the ten drift guards was checked against
.claude/rules/design-system.mdand encodes still-live policy, so none wasdeleted. Those are design debt a working guard would have caught — product work,
not audit work.
lint:duplicate-exportsnever ranIt has a committed baseline (27 grandfathered) and exits 1 on anything new, and
no job invoked it. A ratchet nothing compares against is a green that means
nothing. Now a fifth step in the
Lint ratchetjob, following the existingcontinue-on-error + aggregate pattern.
Six other "unwired" scripts were false positives — CI invokes them as
node scripts/…inside multi-linerun:blocks. Recorded as method, becausethe naive check is the obvious one to repeat.
Bottleneck — measured, not where it was feared
The config warns these sweeps walk ~4,066 files each and carries a 120s timeout.
The whole
guardsproject runs in 1.48s; each promoted guard costs 0.1s.No argument for promoting in waves.
One finding that is not about wiring
Two
ChartTooltipcomponents, one exported name.fairway/charts/ChartTooltip.tsx(220 lines) has five real importers.ui/chart-tooltip.tsx(108 lines) has zero — but is re-exported asChartTooltipfrom@/components/ui, so importing from that barrel silentlygets the dead one. This is exactly what the deleted
chart-tooltip-consolidatedguard existed to prevent, and it happened whilethat guard was not running. Not touched here: product code, and Knip's weekly
job is the right owner.
Verified
typecheck 0 · lint 0 ·
npm test1275 files / 12,209 passed · guards 37/37 ·duplicate-exports ratchet 0 · docs:schema-drift 0 · docs:path-drift 0 ·
knowledge:check 0 · inventory-check 0 · markdown ratchet at baseline ·
ci.ymlparses as valid YAML🤖 Generated with Claude Code
https://claude.ai/code/session_01NbDxyygyXRUEERuGocpZZH