diff --git a/.claude/skills/gates/SKILL.md b/.claude/skills/gates/SKILL.md new file mode 100644 index 0000000000..615e079bd7 --- /dev/null +++ b/.claude/skills/gates/SKILL.md @@ -0,0 +1,95 @@ +--- +name: gates +description: Pick the smallest correct verification gate for a change in this repo, and prove it actually ran before calling it green. Use before running any `npm run verify:*` or `check:*` command, before reporting a gate as passing, when a gate finishes suspiciously fast or clean, and before trusting any agent or bot claim that a fix landed. +--- + +# gates — prove it ran, then report it + +A green exit code is not proof. Contended gates can wait a long time before failing, early stops +leave later checks unrun, and a stale worktree makes healthy-looking runs meaningless. This skill +exists because those failures have cost real time more than once. + +**Rule: never report a gate as passing without quoting the line that proves it ran.** + +## The false-green traps + +Check these before believing any result. + +- **`verify:ui` under heavy-lock contention waits, then fails — it does not soft-skip green.** When + another worktree holds the exclusive lease, `acquireHeavyRunLock` queues Playwright admission for + up to 15 minutes and throws on timeout; `run-playwright.mjs` catches that error and exits `1`. Do + not treat a long wait or a red contention timeout as a false-green soft-skip. When the gate does + run, grep the output for the `N passed` line — exit `0` alone is never proof. +- **A stale worktree makes every downstream gate a lie.** `check:installed-lock-parity` fails closed + for exactly this reason — if installed packages do not match `package-lock.json`, treat any test, + lint, or typecheck result as void until `npm ci` has run. Its own failure message says as much. +- **`verify:cheap` stops at the first failing check.** Everything after that point never ran. Do not + describe the change as broadly verified when the gate died at check 2 of 26. +- **`format:check` is required in CI but is not part of `verify:cheap`.** A locally green + `verify:cheap` can still fail CI on formatting. Run `npx prettier --write ` before + pushing — scoped to your files, never `prettier --write .`, which sweeps the whole tree. +- **Piping a gate into `tail` or `head` masks its exit code.** In Bash, capture `${PIPESTATUS[0]}`, + or check the exit status before piping. + +## Pick the smallest gate that can fail + +Match the gate to what actually changed. Running a broader gate is not more rigorous if it cannot +observe the change; running a narrower one is not sloppy if it can. + +| Change | Gate that can actually fail | +| ----------------------------- | --------------------------------------------------------------- | +| Markdown / docs only | `prettier --check`, `docs:check-links`, `docs:check-index` | +| Source, config, tests | `verify:cheap` | +| Before PR handoff | `verify:pr-local` | +| UI, styling, routing, a11y | `npm run ensure` then `verify:ui` | +| Phone chrome | `verify:phone-chrome` (narrower than `verify:ui`; run it first) | +| Release or handoff confidence | `verify:release` | + +`lint`, `typecheck`, and `test` cannot observe a markdown-only change. Say so rather than running +them for appearance. + +## Before any heavy run or install + +The repository run coordinator serialises heavy work across worktrees. Leases live at +`/clinical-kb-heavy-locks/.lock/leases/`; each holds an `owner.json` with pid, +mode, and command. + +- An **exclusive** lease means full Vitest, coverage, lint, build, Playwright, or live-provider work + is running. Do not install and do not start another heavy gate. +- Never `npm ci` or `npm install` while any repository test, build, lint, typecheck, or server + command is active — including in another worktree. +- Never kill a lease-holding process that belongs to another worktree or another agent's session. +- Check the lease directory rather than scanning the repo tree; ~40 worktrees make recursive scans + slow and noisy. Do not print raw process command lines. + +## Provider boundary + +Never run provider-backed gates without explicit user confirmation: `eval:rag`, `eval:quality`, +`eval:retrieval:quality`, `verify:release`, `check:supabase-project`, `test:live`, and any GitHub, +Supabase, OpenAI, or hosted-CI call. Report the command and ask instead of running it. + +The only standing exception is the user typing `Run PR`, and that authorises only the GitHub actions +enumerated in the `run-pr` skill, for that sweep alone. + +## Third-party claims are not evidence + +A bot or agent saying it fixed something is a claim, not a result. + +- Verify against the actual ref content before repeating it as fact. Prefer refs already available + locally (`git log`, `git show`); fetching from the remote is a network action subject to the + provider boundary above. +- A squash merge breaks ancestry. `git merge-base --is-ancestor` returning false does **not** mean + the work is missing — compare file content on `origin/main` instead. +- Absence of evidence in one place is not proof. Grepping `.github/workflows` for `auto-merge` + returns nothing even though GitHub's per-PR auto-merge is in active use here, because that setting + is not a workflow file. + +## Reporting + +State what ran, what passed, and what never ran. + +- Paste the decisive line: `42 passed`, `docs link check passed: 1287 …`, not "gate green". +- Name the gates that were skipped and why. +- Separate verified from assumed. If a claim came from memory or a prior session rather than this + run, say so. +- Never let output-style compression drop this section. Brevity applies to prose, never to proof. diff --git a/AGENTS.md b/AGENTS.md index ce51ec9675..10cac063b7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -252,9 +252,10 @@ system, developer, user, security, or compliance requirements, which remain high Output-style plugins such as caveman mode may compress prose. They must never compress proof. -- **Always paste the decisive line.** Report gates with real output, not a summary. `npm run -verify:ui` exits 0 without running a single Playwright test when another worktree holds the heavy - lock, so grep for the "N passed" line; exit 0 alone is not proof. +- **Always paste the decisive line.** Report gates with real output, not a summary. Under heavy-lock + contention, `npm run verify:ui` queues Playwright admission for up to 15 minutes and exits `1` on + timeout (`run-playwright.mjs`) — it does not soft-skip green. When the gate does run, grep for the + "N passed" line; exit 0 alone is not proof. - **State verified versus assumed.** Calibration is not filler. Say what was actually run, what was read, and what is inferred. Do not drop uncertainty to save tokens. - **Third-party fix claims stay unverified until checked.** Bot or agent claims that a fix landed diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md index dc50c7c68b..222884fb56 100644 --- a/docs/branch-review-ledger.md +++ b/docs/branch-review-ledger.md @@ -1213,5 +1213,7 @@ This file is append-only. Never rewrite or delete an existing review record; app | 2026-07-28 | PR #1291 / `claude/issues-upload-limit-sync-123366` | `1607558188283d3497683f1067835d96f1031d3c` | CI babysit + merge conflict + Bugbot | FIXED. GitHub CONFLICTING/DIRTY was a real content conflict in `docs/outstanding-issues.md`: main had claimed `#084` for completed per-result grading evidence, colliding with this PR's upload-limit capture. Resolved by keeping main's ledger, renumbering the upload-limit recommendation to `#085`, and bumping `issues:next-id` to `086`. Synced again when main advanced with #1300. CodeRabbit date thread already resolved. Bugbot: zero `cursor[bot]` findings. Required CI green (PR required SUCCESS). | merge-tree CLEAN; prettier + docs:check-links PASS; hosted Change scope/Static/PR required SUCCESS; no provider-backed checks. | | 2026-07-28 | PR #1291 / `claude/issues-upload-limit-sync-123366` | `af140d11d5ca23dee0d8705d9933db967fc8c404` | Babysit closeout tip | Supersedes prior #1291 row at `16075581` after appending the conflict/Bugbot ledger record. Product delta vs main unchanged: `#085` upload-limit capture only. merge-tree CLEAN; awaiting exact-head required checks. | ledger append + check:branch-review-ledger PASS; prior tip hosted PR required SUCCESS. | | 2026-07-28 | PR #1302 / `claude/maturity-ledger-entry` | `64da2c1b34ae101590b8676af12ec6b49c14f0ad` | CI/conflict babysit + Codex threads + Bugbot | FIXED. Real content conflict with main: `#085` already claimed by upload-limit rec (#1291). Merged origin/main; renumbered maturity backlog to `#086`, bumped `issues:next-id` to `087`, added recommended-queue order 29 with go-ahead/RAG/provider stop rules. X7/M1 work orders arrived via main #1299. Codex P2 threads replied + resolved. Bugbot: zero cursor[bot] findings. CircleCI stub from main clears prior "no configuration" status error. | merge-tree CLEAN; prettier + docs:check-links + docs:check-scripts PASS; awaiting exact-head hosted CI; no provider-backed checks. | +| 2026-07-28 | PR #1306 / `claude/frontend-checklist-skills-ece5e6` | `3e6584413f15cdc2c201b8ab123191b38f5d8042` | External skill precedence + evidence rules; CodeRabbit closeout | MERGED (squash); remote branch auto-deleted. Added `External skill precedence` and `Evidence and calibration are never compressed` to AGENTS.md after installing 390 user-global Front-End Checklist skills plus the caveman output-style plugin. CodeRabbit raised 3 findings; its autofix landed 2 pre-merge (WCAG target-size citation corrected to 2.5.5 AAA 44x44 vs 2.5.8 AA 24x24; third-party ref verification deferred to the provider boundary). The summary-level precedence-scoping nitpick had no inline thread, was skipped by autofix, and landed separately in PR #1308. | prettier PASS; docs:check-links 1274 refs PASS; docs:check-index PASS; verify:cheap BLOCKED at check:installed-lock-parity (worktree next 16.2.10 vs locked 16.2.11) so lint/typecheck/test never ran; no provider-backed checks. | | 2026-07-28 | PR #1307 / `claude/rag-019-fallback-guard` | `0827d65d12f5c25faffdf4ebca036f00fc2512cd` | CI babysit + Bugbot | FIXED. Build failed because `guard-next-build.mjs` hard-failed when GitHub runners reported 7.8 GiB RAM (<10 GiB); prior tip Build succeeded on a larger runner (flake). Softened to warn-and-continue under CI/GITHUB_ACTIONS; local/Docker still hard-fail. PR policy FAIL: missing `## Clinical Governance Preflight` — body updated. Bugbot: zero cursor[bot] findings; reviewThreads=0 (nothing to resolve). merge-tree clean vs origin/main. | Unit: guard-next-build + #019 fallback + extractive-answer-formatting 137/137; prettier/eslint clean on touched files; pr-policy evaluate ok; no provider checks. | | 2026-07-28 | PR #1307 / `claude/rag-019-fallback-guard` | `2e5edfc6c9fcc0bb75674b179607888bbf872b91` | PR policy body synced + template removed | Sync PR policy body SUCCESS applied Clinical Governance Preflight (7/7). Deleted temporary `PR_POLICY_BODY.md`. Awaiting Build/PR policy/PR required on this tip. | Hosted Sync SUCCESS; no provider checks. | +| 2026-07-28 | PR #1309 / `claude/gates-skill` | `7dfe103bfa408052c9e899211b8373c7ccb708d3` | Conflict sync + Codex/CodeRabbit + Bugbot | FIXED. GitHub CONFLICTING/DIRTY was main-staleness only (`merge-tree` clean); merged `origin/main`. Codex P2: skill wrongly claimed `verify:ui` exits 0 under heavy-lock contention — corrected to 15m queue then exit 1 via `run-playwright.mjs`; mirrored in AGENTS.md. CodeRabbit: marked `${PIPESTATUS[0]}` as Bash-specific. Bugbot: zero `cursor[bot]` findings; confirmed same P2. No CI failures on prior tip. | `prettier --check` PASS; `docs:check-links` 1287 PASS; no provider-backed checks. |