From 2f26a53b5aeb3df451cf7b1d04f80b07edf0d6fe Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Thu, 30 Jul 2026 18:40:38 +0800 Subject: [PATCH 01/15] docs: file loose dated records and close the docs index gaps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Organisation pass over the documentation surface and the orientation maps. No product code, schema, or retrieval/ranking surface is touched. Five dated point-in-time docs were sitting loose at the docs/ top level even though docs/README.md documents where they belong: - audit-handover-2026-07-14.md, audit-remediation-plan-2026-07-14.md and design-audit-2026-07-17.md move to docs/audit/ - rag-scalability-wip-remediation-2026-07-17.md (self-labelled "Superseded historical record") and rag-scalability-wip-review-handover-2026-07-15.md move to docs/archive/ Relative links inside the moved files are re-anchored to ../, and the two inbound references are updated in docs/operator-backlog.md and docs/archive/design-qa-2026-07-15.md. Contents are otherwise unchanged apart from Prettier's table reflow. The root codex-cloud-review/ directory moves to docs/prompts/codex-cloud-review/, where review prompts already live; .prettierignore and .cursorindexingignore are repointed so those verbatim inputs stay unformatted and unindexed. docs/README.md gains the seventeen docs it never listed — including search-chrome-behaviour.md, which AGENTS.md requires reading before search-chrome work — plus a subdirectory map for rag-behaviour/, prompts/, codex/, evidence/, audit/, redesign/, superpowers/ and archive/. CLAUDE.md and docs/codebase-index.md now document the top-level directories they omitted. Root data/ is the notable one: seven src/lib modules load it at runtime and it is easily confused with src/data/. scripts/check-docs-links.mjs gains a VERBATIM_DIRS skip for codex-cloud-review/. Relocating that directory under docs/ brought it into the default scan, where two of its internal references point at a path that never existed; the files are kept byte-for-byte as provided, so the reference cannot be corrected. This mirrors the existing archive/ and audit/ skip, and --all still sweeps them. Co-Authored-By: Claude Opus 5 --- .cursorindexingignore | 2 +- .prettierignore | 2 +- CLAUDE.md | 4 ++ docs/README.md | 27 +++++++ docs/archive/design-qa-2026-07-15.md | 2 +- ...-scalability-wip-remediation-2026-07-17.md | 6 +- ...lability-wip-review-handover-2026-07-15.md | 0 docs/{ => audit}/audit-handover-2026-07-14.md | 18 ++--- .../audit-remediation-plan-2026-07-14.md | 70 +++++++++---------- docs/{ => audit}/design-audit-2026-07-17.md | 0 docs/codebase-index.md | 12 ++++ docs/operator-backlog.md | 4 +- ...1-codex-full-stack-master-review-prompt.md | 0 ...ck-master-prompt-review-and-stress-test.md | 0 .../3-codex-agents-md-companion.md | 0 scripts/check-docs-links.mjs | 14 ++-- 16 files changed, 104 insertions(+), 57 deletions(-) rename docs/{ => archive}/rag-scalability-wip-remediation-2026-07-17.md (98%) rename docs/{ => archive}/rag-scalability-wip-review-handover-2026-07-15.md (100%) rename docs/{ => audit}/audit-handover-2026-07-14.md (96%) rename docs/{ => audit}/audit-remediation-plan-2026-07-14.md (96%) rename docs/{ => audit}/design-audit-2026-07-17.md (100%) rename {codex-cloud-review => docs/prompts/codex-cloud-review}/1-codex-full-stack-master-review-prompt.md (100%) rename {codex-cloud-review => docs/prompts/codex-cloud-review}/2-codex-full-stack-master-prompt-review-and-stress-test.md (100%) rename {codex-cloud-review => docs/prompts/codex-cloud-review}/3-codex-agents-md-companion.md (100%) diff --git a/.cursorindexingignore b/.cursorindexingignore index 6ba7ac17bb..4f9071e867 100644 --- a/.cursorindexingignore +++ b/.cursorindexingignore @@ -45,7 +45,7 @@ src/components/*mockups.tsx src/components/clinical-dashboard/global-mockup-search-shell.tsx # One-off Codex review prompt dumps (not product code) -codex-cloud-review/ +docs/prompts/codex-cloud-review/ # Generated schema-drift inventory (large JSON) supabase/drift-manifest.json diff --git a/.prettierignore b/.prettierignore index d897f291c5..954ee472d6 100644 --- a/.prettierignore +++ b/.prettierignore @@ -22,4 +22,4 @@ supabase/drift-manifest.json public/therapy-compass-data/ docs/branch-review-ledger.md # Verbatim user-provided prompt inputs retained for cloud review. -codex-cloud-review/ +docs/prompts/codex-cloud-review/ diff --git a/CLAUDE.md b/CLAUDE.md index aa3ad0e38b..eb48f32dc9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -87,14 +87,18 @@ src/components/ UI; clinical-dashboard/ is the shell, *-mockups.tsx are design src/lib/ ~200 modules — rag/, supabase/, validation/, observability/, extractors/, webhooks/ are the extracted subdirectories src/data/ Static clinical content (DSM, formulation, therapies indexes) +data/ Generated clinical snapshot exports loaded at runtime — regenerate, never hand-edit supabase/ migrations/ (source of truth), schema.sql (mirror), functions/ worker/ Ingestion worker; worker/python/ is the OCR stack scripts/ ~160 files backing 194 npm scripts: gates, eval, reindex, governance, dev tests/ Vitest unit + Playwright E2E, side by side docs/ Runbooks, governance, plans; docs/README.md categorises them eslint-rules/ Repo-specific lint rules (see Conventions below) +mockups/ Notes for the design-scratch routes under src/app/mockups/ +plugins/ plugins/clinical-kb/ Codex plugin manifest and workflow skill .claude/ Claude Code agents, skills, hooks, settings .agents/ Single-word skill catalogue (`npm run skills`) +.githooks/ Installed by `npm install`; pre-push runs scripts/guard-push.mjs ``` Never commit: `.next/`, `node_modules/`, `coverage/`, `.env*`, `sample-documents/`, logs. diff --git a/docs/README.md b/docs/README.md index ff0cdb1aa6..2dde2efb17 100644 --- a/docs/README.md +++ b/docs/README.md @@ -24,6 +24,7 @@ npm run docs:check-links - [frontend-architecture.md](frontend-architecture.md) — shell, routing, dashboard module structure - [wiring-conventions.md](wiring-conventions.md) — page/button wiring conventions and the dead-button / orphan-route gates +- [search-chrome-behaviour.md](search-chrome-behaviour.md) — shared search-chrome contract: composer ownership, phone edge-to-edge dock, hide/reveal reserves - [deployment-architecture.md](deployment-architecture.md) — app/worker/Supabase deployment topology - [ingestion-state-machine.md](ingestion-state-machine.md) — ingestion job lifecycle and states - [design-system.md](design-system.md) — tokens, primitives, styling conventions @@ -31,6 +32,8 @@ npm run docs:check-links - [clinical-badge-system-guide.md](clinical-badge-system-guide.md) — clinical badge semantics - [multi-user-auth-setup.md](multi-user-auth-setup.md) — auth, sessions, owner scoping - [pwa.md](pwa.md) — PWA install assets, privacy-first service worker, offline shell +- [webhooks.md](webhooks.md) — the two inbound webhook receivers and the outbound Actions notifier +- [api-jobs-ops-surface.md](api-jobs-ops-surface.md) — standing decision to keep `GET /api/jobs` as an ops/admin surface ## Operations runbooks @@ -43,11 +46,15 @@ npm run docs:check-links - [staging-setup.md](staging-setup.md) — staging environment bootstrap - [database-drift-detection.md](database-drift-detection.md) — schema drift detection (`npm run check:drift`) - [supabase-migration-reconciliation.md](supabase-migration-reconciliation.md) — migration drift and repair policy +- [db-maintenance.md](db-maintenance.md) — Supabase advisor snapshots and the standing disposition per finding class - [observability-slos.md](observability-slos.md) — health probes, SLO counters, degraded modes - [openai-rag-operations.md](openai-rag-operations.md) — OpenAI/RAG provider operations and modes - [outstanding-issues.md](outstanding-issues.md) — single universal task ledger and repository memory - [operator-backlog.md](operator-backlog.md) — provider/operator runbook detail (status is canonical in the universal ledger) - [deploy-corrector-public-titles.md](deploy-corrector-public-titles.md) — public-title corrector deploy notes +- [operator-apply-performance-latency-remediation.md](operator-apply-performance-latency-remediation.md) — operator apply steps for the performance/latency migration batch +- [reconciliation-playbook.md](reconciliation-playbook.md) — broad chat/worktree reconciliation and archive-safe cleanup (not for ordinary feature work) +- [staging-tenancy-release-evidence.md](staging-tenancy-release-evidence.md) — cross-tenant staging harness as executable owner-boundary proof ## Governance, safety, privacy @@ -82,6 +89,19 @@ npm run docs:check-links - [redesign/](redesign/) — premium redesign plans, decision log, token adoption - [superpowers/](superpowers/) — agent-authored plans and specs +## Subdirectory map + +| Directory | What lives there | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------- | +| [rag-behaviour/](rag-behaviour/) | Protected retrieval/ranking surface: behaviour map, refuted approaches, safeguards. **Read before touching ranking.** | +| [prompts/](prompts/) | Copy/paste review prompts, including the verbatim `codex-cloud-review/` inputs | +| [codex/](codex/) | Per-lens Codex ultra-review output folders, one per review dimension | +| [evidence/](evidence/) | Captured evidence artifacts backing ledger items (reliability reports, review manifests) | +| [audit/](audit/) | Dated repo, design, accessibility, and latency audits (point-in-time) | +| [redesign/](redesign/) | Premium redesign plans, decision log, token adoption | +| [superpowers/](superpowers/) | Agent-authored plans and specs | +| [archive/](archive/) | Completed phase plans, superseded designs, old progress logs — never current guidance | + ## Point-in-time records (historical — do not update) Dated status reports, reviews, and operator decisions. They describe the repo @@ -90,6 +110,13 @@ as it was on that date; supersede with a new dated document rather than editing. - [audit/](audit/) — repo and UX/accessibility audits - [audit/2026-07-20-repository-maturity.md](audit/2026-07-20-repository-maturity.md) — full repository maturity, mapping, and organisation audit - [audit/latency-audit-2026-07-28.md](audit/latency-audit-2026-07-28.md) — latency audit: server, client, and database findings by tier, with the already-cleared list +- [audit/audit-handover-2026-07-14.md](audit/audit-handover-2026-07-14.md) — multi-skill repository audit findings inventory +- [audit/audit-remediation-plan-2026-07-14.md](audit/audit-remediation-plan-2026-07-14.md) — sequenced remediation plan for the 2026-07-14 audit, with the 2026-07-17 reconciliation +- [audit/design-audit-2026-07-17.md](audit/design-audit-2026-07-17.md) — repository-wide design, accessibility, and interaction audit +- [current-clinical-work-brief.md](current-clinical-work-brief.md) — ledger #063 product/privacy/persistence brief (decision only, no implementation) +- [factsheets-reading-model-brief.md](factsheets-reading-model-brief.md) — ledger #041 reading-model decision (no second Factsheets mode) +- [source-governance-refresh-worklist-2026-07-22.md](source-governance-refresh-worklist-2026-07-22.md) — ledger #022 worklist and BMJ attestation policy status +- `release-source-metadata-debt-2026-06-30.json` — captured source-metadata debt policy, consumed by `npm run audit:source-governance:release` and `npm run eval:quality:release` - [forward-codify-retrieval-rpcs-workorder.md](forward-codify-retrieval-rpcs-workorder.md) — completed retrieval RPC codification workorder - [project-alignment-cleanup.md](archive/project-alignment-cleanup.md) — completed June 2026 repo-alignment record - [capacity-review.md](capacity-review.md), [scale-readiness-review.md](scale-readiness-review.md), [tenancy-defense-in-depth-review.md](tenancy-defense-in-depth-review.md) diff --git a/docs/archive/design-qa-2026-07-15.md b/docs/archive/design-qa-2026-07-15.md index 92684d102e..52197cb031 100644 --- a/docs/archive/design-qa-2026-07-15.md +++ b/docs/archive/design-qa-2026-07-15.md @@ -64,4 +64,4 @@ Blocker: an independent source visual target is required to certify concept fide ## Follow-up audit — 2026-07-17 -The exhaustive line-level design, accessibility, UX, interaction, and route-coverage follow-up is documented in [`docs/design-audit-2026-07-17.md`](../design-audit-2026-07-17.md). It preserves the fixes above, avoids duplicating this pass, and records the new P1/P2/P3 fixes plus the exact local verification limitations. +The exhaustive line-level design, accessibility, UX, interaction, and route-coverage follow-up is documented in [`docs/audit/design-audit-2026-07-17.md`](../audit/design-audit-2026-07-17.md). It preserves the fixes above, avoids duplicating this pass, and records the new P1/P2/P3 fixes plus the exact local verification limitations. diff --git a/docs/rag-scalability-wip-remediation-2026-07-17.md b/docs/archive/rag-scalability-wip-remediation-2026-07-17.md similarity index 98% rename from docs/rag-scalability-wip-remediation-2026-07-17.md rename to docs/archive/rag-scalability-wip-remediation-2026-07-17.md index 04ef319386..dcb911a8a5 100644 --- a/docs/rag-scalability-wip-remediation-2026-07-17.md +++ b/docs/archive/rag-scalability-wip-remediation-2026-07-17.md @@ -6,9 +6,9 @@ > `20260717170000_registry_projection_cleanup.sql` and > `20260717171000_public_title_corrector.sql`. Do not use this report's status or next > steps as current operator guidance. Use -> [operator-apply-performance-latency-remediation.md](operator-apply-performance-latency-remediation.md), -> [deploy-corrector-public-titles.md](deploy-corrector-public-titles.md), and -> [operator-backlog.md](operator-backlog.md) instead. +> [operator-apply-performance-latency-remediation.md](../operator-apply-performance-latency-remediation.md), +> [deploy-corrector-public-titles.md](../deploy-corrector-public-titles.md), and +> [operator-backlog.md](../operator-backlog.md) instead. **Status:** F11 shipped and merged; all correctness findings verified moot on this branch; scalability build recorded and deferred pending go-ahead. diff --git a/docs/rag-scalability-wip-review-handover-2026-07-15.md b/docs/archive/rag-scalability-wip-review-handover-2026-07-15.md similarity index 100% rename from docs/rag-scalability-wip-review-handover-2026-07-15.md rename to docs/archive/rag-scalability-wip-review-handover-2026-07-15.md diff --git a/docs/audit-handover-2026-07-14.md b/docs/audit/audit-handover-2026-07-14.md similarity index 96% rename from docs/audit-handover-2026-07-14.md rename to docs/audit/audit-handover-2026-07-14.md index f63d842553..a969d672ca 100644 --- a/docs/audit-handover-2026-07-14.md +++ b/docs/audit/audit-handover-2026-07-14.md @@ -9,7 +9,7 @@ remediation without re-running discovery. | Audit date | 2026-07-14 | | Mode | Pure review (no app-code fixes applied as part of the audit) | | Remediation plan | [`audit-remediation-plan-2026-07-14.md`](audit-remediation-plan-2026-07-14.md) | -| Ledger rows | [`branch-review-ledger.md`](branch-review-ledger.md) (multi-skill + consolidated rows) | +| Ledger rows | [`branch-review-ledger.md`](../branch-review-ledger.md) (multi-skill + consolidated rows) | | Plan PR | [#673](https://github.com/BigSimmo/Database/pull/673) (`cursor/audit-remediation-plan-0411`) | | Ledger-only PR | [#652](https://github.com/BigSimmo/Database/pull/652) (`cursor/repo-wide-audit-ledger-0411`) | @@ -238,14 +238,14 @@ Full address sketches: Remediation Wave I in the remediation plan. | Doc | Role | | ------------------------------------------------------------------------------ | -------------------------------- | | [`audit-remediation-plan-2026-07-14.md`](audit-remediation-plan-2026-07-14.md) | How to fix, sequenced | -| [`operator-backlog.md`](operator-backlog.md) | Human/provider actions index | -| [`launch-operator-runbook.md`](launch-operator-runbook.md) | Sequenced launch commands | -| [`privacy-impact-assessment.md`](privacy-impact-assessment.md) | PIA register | -| [`openai-cross-border-basis.md`](openai-cross-border-basis.md) | APP 8 checklist | -| [`tenancy-defense-in-depth-review.md`](tenancy-defense-in-depth-review.md) | Tenancy defense notes | -| [`process-hardening.md`](process-hardening.md) | Process & known debts | -| [`codex-review-protocol.md`](codex-review-protocol.md) | Review severity / mutation rules | -| [`branch-review-ledger.md`](branch-review-ledger.md) | Prevent repeat audits | +| [`operator-backlog.md`](../operator-backlog.md) | Human/provider actions index | +| [`launch-operator-runbook.md`](../launch-operator-runbook.md) | Sequenced launch commands | +| [`privacy-impact-assessment.md`](../privacy-impact-assessment.md) | PIA register | +| [`openai-cross-border-basis.md`](../openai-cross-border-basis.md) | APP 8 checklist | +| [`tenancy-defense-in-depth-review.md`](../tenancy-defense-in-depth-review.md) | Tenancy defense notes | +| [`process-hardening.md`](../process-hardening.md) | Process & known debts | +| [`codex-review-protocol.md`](../codex-review-protocol.md) | Review severity / mutation rules | +| [`branch-review-ledger.md`](../branch-review-ledger.md) | Prevent repeat audits | --- diff --git a/docs/audit-remediation-plan-2026-07-14.md b/docs/audit/audit-remediation-plan-2026-07-14.md similarity index 96% rename from docs/audit-remediation-plan-2026-07-14.md rename to docs/audit/audit-remediation-plan-2026-07-14.md index 4209f5f04a..a89dd32d1e 100644 --- a/docs/audit-remediation-plan-2026-07-14.md +++ b/docs/audit/audit-remediation-plan-2026-07-14.md @@ -1,7 +1,7 @@ # Audit remediation plan — 2026-07-14 Plan derived from the multi-skill repository audit of `main` @ `570e6ba` (ledger rows in -[`branch-review-ledger.md`](branch-review-ledger.md)). This document is the sequenced address plan for +[`branch-review-ledger.md`](../branch-review-ledger.md)). This document is the sequenced address plan for every finding: major blockers first, then P2 sub-issues, then P3 cleanup. **Findings handover (inventory + status):** [`audit-handover-2026-07-14.md`](audit-handover-2026-07-14.md). @@ -31,8 +31,8 @@ every finding against current `main` found the code side largely landed since th - Code fixes use `npm run verify:cheap` first, then the smallest domain check, then `npm run verify:pr-local` before handoff. - Provider/live actions are **operator-gated** (`⏸`). Do not run them without explicit confirmation. -- Reconcile [`operator-backlog.md`](operator-backlog.md) against - [`launch-operator-runbook.md`](launch-operator-runbook.md) before repeating any historical apply. +- Reconcile [`operator-backlog.md`](../operator-backlog.md) against + [`launch-operator-runbook.md`](../launch-operator-runbook.md) before repeating any historical apply. **Legend** @@ -102,48 +102,48 @@ Suggested PR granularity (one theme per PR): ### B1. Close PIA-1 APP 8 / overseas processing basis -| | | -| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **Finding** | M1 — Railway Singapore + OpenAI US process incidental PHI queries | -| **Owner** | OWNER:LEGAL + OWNER:OPS | -| **Address** | Execute checklist in [`openai-cross-border-basis.md`](openai-cross-border-basis.md): OpenAI DPA, ZDR eligibility enablement where chosen, Railway DPA/processor record, update PIA status tables and `/privacy` copy only after counsel approval. | -| **Prove** | Status record rows move from `_no_` to dated `_yes_` / approved alternative; PIA-1 no longer High-open | +| | | +| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Finding** | M1 — Railway Singapore + OpenAI US process incidental PHI queries | +| **Owner** | OWNER:LEGAL + OWNER:OPS | +| **Address** | Execute checklist in [`openai-cross-border-basis.md`](../openai-cross-border-basis.md): OpenAI DPA, ZDR eligibility enablement where chosen, Railway DPA/processor record, update PIA status tables and `/privacy` copy only after counsel approval. | +| **Prove** | Status record rows move from `_no_` to dated `_yes_` / approved alternative; PIA-1 no longer High-open | ### B2. Verify Railway `RAG_QUERY_HASH_SECRET` (PIA-2) -| | | -| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **Finding** | M2 — secret verified in GitHub CI, Railway runtime still `🔎 verify` | -| **Owner** | OWNER:OPS | -| **Address** | Set/confirm a ≥16-char value in Railway **production** that matches the GitHub Actions secret used for CI smoke. For staging, set a **separate** staging-only `RAG_QUERY_HASH_SECRET` per [`staging-setup.md`](staging-setup.md) — do not reuse the production HMAC key. Confirm boot smoke and deep readiness. | -| **Prove** | `⏸ npm run check:deployment-readiness` / production health boot; backlog → `✅` | +| | | +| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **Finding** | M2 — secret verified in GitHub CI, Railway runtime still `🔎 verify` | +| **Owner** | OWNER:OPS | +| **Address** | Set/confirm a ≥16-char value in Railway **production** that matches the GitHub Actions secret used for CI smoke. For staging, set a **separate** staging-only `RAG_QUERY_HASH_SECRET` per [`staging-setup.md`](../staging-setup.md) — do not reuse the production HMAC key. Confirm boot smoke and deep readiness. | +| **Prove** | `⏸ npm run check:deployment-readiness` / production health boot; backlog → `✅` | ### B3. Restore OpenAI quota and run release gates -| | | -| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **Finding** | M3 — release gate + golden evals incomplete; prior quota exhaustion | -| **Owner** | OWNER:OPS | -| **Address** | Complete the runbook §0 identity preflight with `npm run check:supabase-project`, then restore embedding/completions quota → run `npm run eval:retrieval:quality` (36/36) → `npm run eval:quality -- --rag-only` → `npm run verify:release` per [`launch-operator-runbook.md`](launch-operator-runbook.md) §2. | -| **Prove** | Paste summaries into release notes / backlog; canary path in B4 | +| | | +| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Finding** | M3 — release gate + golden evals incomplete; prior quota exhaustion | +| **Owner** | OWNER:OPS | +| **Address** | Complete the runbook §0 identity preflight with `npm run check:supabase-project`, then restore embedding/completions quota → run `npm run eval:retrieval:quality` (36/36) → `npm run eval:quality -- --rag-only` → `npm run verify:release` per [`launch-operator-runbook.md`](../launch-operator-runbook.md) §2. | +| **Prove** | Paste summaries into release notes / backlog; canary path in B4 | ### B4. Eval Canary trust + staging soak -| | | -| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **Finding** | M3 leftovers — canary not yet “two greens”; staging soak pending | -| **Owner** | OWNER:OPS | -| **Address** | Provision staging if absent ([`staging-setup.md`](staging-setup.md)); soak (`scripts/soak-test.ts --confirm-staging`, answer p95 ≤ 25 s); run two consecutive Eval Canary greens from `main`. | -| **Prove** | Soak log + two green workflow runs recorded in backlog | +| | | +| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **Finding** | M3 leftovers — canary not yet “two greens”; staging soak pending | +| **Owner** | OWNER:OPS | +| **Address** | Provision staging if absent ([`staging-setup.md`](../staging-setup.md)); soak (`scripts/soak-test.ts --confirm-staging`, answer p95 ≤ 25 s); run two consecutive Eval Canary greens from `main`. | +| **Prove** | Soak log + two green workflow runs recorded in backlog | ### B5. Worker image / secret / seed post-deploy confirm -| | | -| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **Finding** | Worker redeploy, registry seed, `HEALTH_DEEP_PROBE_SECRET`, auth connection cap | -| **Owner** | OWNER:OPS | -| **Address** | Follow runbook §6 after B3: `reindex:health`, seed registry/differentials, wire ops-digest secrets if desired, flip auth connection allocation **before** vertical scale ([`auth-connection-cap-runbook.md`](auth-connection-cap-runbook.md)). | -| **Prove** | Non-empty Services/Forms; reindex health clear; optional ops-digest cron enabled | +| | | +| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Finding** | Worker redeploy, registry seed, `HEALTH_DEEP_PROBE_SECRET`, auth connection cap | +| **Owner** | OWNER:OPS | +| **Address** | Follow runbook §6 after B3: `reindex:health`, seed registry/differentials, wire ops-digest secrets if desired, flip auth connection allocation **before** vertical scale ([`auth-connection-cap-runbook.md`](../auth-connection-cap-runbook.md)). | +| **Prove** | Non-empty Services/Forms; reindex health clear; optional ops-digest cron enabled | --- @@ -447,7 +447,7 @@ After Waves B–H land (or are deferred with dated waiver): 4. `⏸ npm run eval:retrieval:quality` + `npm run eval:quality -- --rag-only` 5. `⏸ npm run verify:release` 6. Update PIA / backlog / this plan’s status column (add a “Status” column locally as work completes) -7. Record outcomes in [`branch-review-ledger.md`](branch-review-ledger.md) +7. Record outcomes in [`branch-review-ledger.md`](../branch-review-ledger.md) --- @@ -477,5 +477,5 @@ After Waves B–H land (or are deferred with dated waiver): ## Tracking Append progress to the review ledger when a wave completes, and flip matching rows in -[`operator-backlog.md`](operator-backlog.md). Prefer linking PRs back to issue IDs in this document +[`operator-backlog.md`](../operator-backlog.md). Prefer linking PRs back to issue IDs in this document (`Wave C1`, `Wave E2`, …) in the PR body. diff --git a/docs/design-audit-2026-07-17.md b/docs/audit/design-audit-2026-07-17.md similarity index 100% rename from docs/design-audit-2026-07-17.md rename to docs/audit/design-audit-2026-07-17.md diff --git a/docs/codebase-index.md b/docs/codebase-index.md index 0af4904fe6..d0afc40070 100644 --- a/docs/codebase-index.md +++ b/docs/codebase-index.md @@ -32,6 +32,18 @@ Structured map for AI agents and onboarding. For live routes, see `docs/site-map | `public/` | Static assets (`public/llms.txt`) | | `.github/` | CI workflows, PR template (clinical governance preflight) | +Smaller top-level directories that are easy to miss: + +| Path | Purpose | +| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `data/` | Committed clinical **snapshot exports** loaded at runtime by `src/lib/` (differentials, forms, medications, services, specifiers). Regenerate via the matching `scripts/import-*-export.ts` / `build-*-index.mjs`; do not hand-edit. Distinct from `src/data/`, which holds hand-authored static content. | +| `eslint-rules/` | Repo-specific lint rules enforced by `npm run lint` (button wiring, hardcoded hex, type/icon scale, z-index ladder) | +| `mockups/` | Notes for the design-scratch routes under `src/app/mockups/` (the routes themselves 404 in production) | +| `plugins/` | `plugins/clinical-kb/` Codex plugin manifest and workflow skill | +| `.agents/` | Single-word skill catalogue (`npm run skills`, validated by `npm run check:skills`) | +| `.claude/` | Claude Code agents, skills, hooks, settings — plus the `.claude/worktrees/` working copies | +| `.githooks/` | Installed by `npm install`; `pre-push` runs `scripts/guard-push.mjs` (format, auto-merge race, drift staleness) | + **Do not commit:** `.next/`, `node_modules/`, `coverage/`, `.env*`, `sample-documents/`, logs. --- diff --git a/docs/operator-backlog.md b/docs/operator-backlog.md index 383760ce92..84f1a16998 100644 --- a/docs/operator-backlog.md +++ b/docs/operator-backlog.md @@ -10,8 +10,8 @@ presence claims that must be verified before acting. Update the row (and its runbook) when an action lands. The sequenced flow with exact commands and approval gates is [launch-operator-runbook.md](launch-operator-runbook.md); this table is the index. Code + ops remediation waves from the 2026-07-14 multi-skill audit live in -[audit-remediation-plan-2026-07-14.md](audit-remediation-plan-2026-07-14.md). -Findings inventory for handover: [audit-handover-2026-07-14.md](audit-handover-2026-07-14.md). +[audit/audit-remediation-plan-2026-07-14.md](audit/audit-remediation-plan-2026-07-14.md). +Findings inventory for handover: [audit/audit-handover-2026-07-14.md](audit/audit-handover-2026-07-14.md). > Status column is seeded from repo runbooks + session memory and **must be confirmed against live > state** before acting — do not treat a `🔎 verify` row as authoritative. diff --git a/codex-cloud-review/1-codex-full-stack-master-review-prompt.md b/docs/prompts/codex-cloud-review/1-codex-full-stack-master-review-prompt.md similarity index 100% rename from codex-cloud-review/1-codex-full-stack-master-review-prompt.md rename to docs/prompts/codex-cloud-review/1-codex-full-stack-master-review-prompt.md diff --git a/codex-cloud-review/2-codex-full-stack-master-prompt-review-and-stress-test.md b/docs/prompts/codex-cloud-review/2-codex-full-stack-master-prompt-review-and-stress-test.md similarity index 100% rename from codex-cloud-review/2-codex-full-stack-master-prompt-review-and-stress-test.md rename to docs/prompts/codex-cloud-review/2-codex-full-stack-master-prompt-review-and-stress-test.md diff --git a/codex-cloud-review/3-codex-agents-md-companion.md b/docs/prompts/codex-cloud-review/3-codex-agents-md-companion.md similarity index 100% rename from codex-cloud-review/3-codex-agents-md-companion.md rename to docs/prompts/codex-cloud-review/3-codex-agents-md-companion.md diff --git a/scripts/check-docs-links.mjs b/scripts/check-docs-links.mjs index 4883994037..65b782bb74 100644 --- a/scripts/check-docs-links.mjs +++ b/scripts/check-docs-links.mjs @@ -11,10 +11,11 @@ * inside the repository. * * Scanned by default: README.md, AGENTS.md, and docs/**\/*.md excluding - * docs/archive/, docs/audit/, and dated point-in-time filenames + * docs/archive/, docs/audit/, dated point-in-time filenames * (docs/README.md classifies those as historical records that intentionally - * reference the repo as it was). Pass --all to scan those too - * (informational deeper sweep; still fails on missing paths). + * reference the repo as it was), and docs/prompts/codex-cloud-review/ (verbatim + * as-provided prompt inputs whose paths must not be edited). Pass --all to scan + * those too (informational deeper sweep; still fails on missing paths). * * Advisory tool: run `npm run docs:check-links` before doc handoffs. It is * deliberately NOT part of verify:cheap or CI so historical docs cannot @@ -57,6 +58,9 @@ const ALLOWLIST = new Set([ const DATED_DOC = /\b20\d{2}-\d{2}(-\d{2})?\b/; // Historical directories: only scanned with --all. const HISTORICAL_DIRS = new Set(["archive", "audit"]); +// Verbatim as-provided inputs: retained byte-for-byte, so their internal path +// references cannot be corrected. Only scanned with --all. +const VERBATIM_DIRS = new Set(["codex-cloud-review"]); const APP_ROUTE_GROUPS = ["(search-app)"]; function repoPathExists(repoRelative) { @@ -73,8 +77,8 @@ function collectDocs(dirRelative, targets) { for (const entry of readdirSync(absolute, { withFileTypes: true })) { const entryRelative = path.posix.join(dirRelative, entry.name); if (entry.isDirectory()) { - const isHistorical = HISTORICAL_DIRS.has(entry.name); - if (isHistorical && !scanAll) continue; + const isSkippable = HISTORICAL_DIRS.has(entry.name) || VERBATIM_DIRS.has(entry.name); + if (isSkippable && !scanAll) continue; collectDocs(entryRelative, targets); continue; } From 12b20c3e5130a71c5c2483320f494cac96b6c8a5 Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Thu, 30 Jul 2026 18:57:10 +0800 Subject: [PATCH 02/15] docs(ledger): record the docs organisation review for PR #1436 Co-Authored-By: Claude Opus 5 --- docs/branch-review-ledger.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md index 036c7dc9b0..5712ecf451 100644 --- a/docs/branch-review-ledger.md +++ b/docs/branch-review-ledger.md @@ -148,3 +148,4 @@ Records before 2026-07-28 were written by hand and had drifted: 146 lines carrie | 2026-07-30 | cursor/ci-hygiene-gates-1bf5 | b660dbc5a10d7ca3da03541028017f0abc6b5bd3 | ci-hygiene-gates merge-readiness | findings | check:ci-scope;check:gitleaks-pinned;scope-classify PR files ui_changed=false;sim cancelled-as-neutral | | 2026-07-30 | cursor/ci-hygiene-gates-1bf5 | 8f3283d00da274dee507a1b8e9b611321d1f35be | pr-1413-merge-readiness | READY after main sync + cancel-to-green fix; draft until tip CI green; deferred #093 + CI_TRIAGE_ENABLED confirm | verify:cheap:4481-pass;format:outstanding-issues;merge-tree:clean;cancelled:!cancelled();hosted:awaiting-tip | | 2026-07-30 | cursor/ci-hygiene-gates-1bf5 | 0d70de480f370fec3e7f3774f13d906318a09b3c | pr-1413-merge-readiness | READY: synced with main/#1409; tip CI success incl PR required; draft; deferred #093 + CI_TRIAGE_ENABLED | merge-tree:clean;ci-cache-safety:13/13;hosted:30520195863:success;PR-required:pass | +| 2026-07-30 | claude/organize-local-worktree-d22bc3 | 2f26a53b5aeb3df451cf7b1d04f80b07edf0d6fe | docs organisation: dated-record filing, docs index gaps, orientation maps | PR #1436 opened — 5 dated docs filed into docs/audit and docs/archive, root codex-cloud-review moved under docs/prompts, 17 docs README index gaps closed, root data/ documented in CLAUDE.md + codebase-index; no product code, schema or RAG surface touched | docs:check-links 1368 refs pass; docs:check-scripts 378 pass; docs:check-index OK; format:check whole-tree clean; verify:cheap 26 static gates + lint + typecheck pass, unit 4562 pass / 1 pre-existing Windows path-separator failure in tests/repo-hygiene.test.ts | From 270435e824b314c3f85bcb2b55678bbdd68b6285 Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Thu, 30 Jul 2026 19:24:11 +0800 Subject: [PATCH 03/15] issues: capture the root-dir coverage gap, the four unfileable dated docs, and the cross-worktree pre-commit hook Co-Authored-By: Claude Opus 5 --- docs/outstanding-issues.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/outstanding-issues.md b/docs/outstanding-issues.md index 5ddaa6d1a7..105a667b2d 100644 --- a/docs/outstanding-issues.md +++ b/docs/outstanding-issues.md @@ -82,7 +82,7 @@ removed after current-main verification; it is not missing recommended work. | 34 | `#105` | Optional | High — browser/UI verification | When the heavy-run lock is free | 20–40 minutes | Run `verify:ui` over the ten `LoadingPanel` fallbacks and confirm the Supabase `preconnect` reaches `` on a live page. Implementation already shipped; this row is the outstanding verification only. | | 35 | `#126` | Optional | Standard — repository hygiene | Once per UTC calendar quarter, or when the live ledger grows large | 5–15 minutes | Run `npm run ledger:rotate -- --dry-run`, then `npm run ledger:rotate` if the preview looks right; commit the live+archive diff. Stop if dry-run shows unexpected mass moves or archive path collisions. | - + ## Open items @@ -159,6 +159,9 @@ removed after current-main verification; it is not missing recommended work. | #132 | P3 | issue | Both client-side push guards are inert for agent pushes | **Outcome:** the format and auto-merge guards protect every push, or their blind spot is explicit. **Detail:** `scripts/guard-push.mjs` printed `auto-merge: gh not available — auto-merge check skipped (fail-open)` for pushes from a remote agent environment, so the auto-merge race sentinel never evaluated; and `core.hooksPath` is set only by a local `npm install`, so an agent pushing from its own checkout bypasses `.githooks/pre-push` entirely. Both guards therefore protect exactly the environment least likely to break the rule, which is why the AGENTS.md format-before-push instruction is still load-bearing even though the tooling now exists. Observed directly on PR #1400: a push landed while auto-merge was armed with nothing to stop it. **Next:** provide `gh` (or a token-based equivalent) in agent environments so the sentinel can evaluate. **Do not move the format check into `pull_request_target`** — that context carries secrets and a write token, and a format check must execute PR-head code including this repo's now-loadable dynamic `prettier.config.*`, which is the classic privileged-context vector; `.github/workflows/pr-policy.yml` deliberately checks out only `github.workflow_sha` for exactly this reason. Formatting is already enforced server-side by `Static PR checks` running `format:check` on ordinary `pull_request` CI, so the guard's only unique value is failing fast before the push — nothing to duplicate. The auto-merge sentinel reads PR metadata only and could safely live in `pull_request_target` if it is ever worth moving. | PR #1400; session 2026-07-30 | 2026-07-30 | | #133 | P3 | rec | `docs/outstanding-issues.md` conflicts on nearly every `main` advance | **Outcome:** two agents editing different rows of this ledger do not conflict. **Detail:** the table is padded to fixed column widths, so a single row's edit re-pads all 59 open rows and git sees the whole table as one changed hunk. On 2026-07-30 this file conflicted twice within an hour on PR #1400, and each conflict silently stopped **all** CI on that PR (`#116`) — so the cost is not the merge itself but the invisible loss of every check while it lasts. Both conflicts were mechanical: only two rows differed semantically out of 58. **Next:** stop padding this table (Prettier will still render it readably, and one-row edits become one-line diffs), or split the open items into per-row files. **Do not** apply a `merge=union` driver — tested 2026-07-30 and it is worse: union concatenates conflicting hunks, so two sides each bumping the marker produce two `next-id` lines, corrupting the file silently where a conflict would fail loudly. `#112`'s new `check:outstanding-issues` gate catches the corrupted result but does not prevent the conflict. | PR #1400; session 2026-07-30 | 2026-07-30 | | #134 | P2 | issue | Ledger union-merge driver is absent wherever `npm install` was skipped | **Outcome:** the ledger's union-merge protection is present wherever a merge happens, or its absence is loud. **Detail:** `.gitattributes` declares `docs/branch-review-ledger.md merge=ledger`, but the driver itself lives in git _config_, installed by `postinstall` -> `scripts/install-git-hooks.mjs`. A container that skips `npm install` (this repo's remote agent sessions do — the session hook reports "node_modules matches the lockfile, skipping install") therefore has the attribute without the driver, and git silently falls back to an ordinary merge. On 2026-07-30 a `git merge origin/main` on PR #1424 produced **conflict markers inside the append-only ledger** at three lines; `git merge` itself did not name the file, so only `npm run check:branch-review-ledger` caught it. Committing that would have corrupted the file the guard exists to protect. **Next:** make the absence loud — have `check:branch-review-ledger` (already in `verify:cheap` and `static-pr`) fail when `.gitattributes` declares `merge=ledger` but `git config merge.ledger.driver` is unset, so the environment is caught before a merge rather than after. `npm run hooks:install` is the one-line fix once detected. **Stop:** never trust a `merge=union`-style attribute to be active just because `.gitattributes` declares it; the driver is per-checkout config. | PR #1424; session 2026-07-30 | 2026-07-30 | +| #135 | P2 | issue | `check:docs-index` has no repo-root directory coverage | **Outcome:** a new top-level directory cannot stay absent from the orientation maps. **Detail:** `scripts/check-codebase-index-coverage.mjs` exists precisely to catch "a module that never gets added to the map, silently staling it", but its granularity is route groups, `src/lib` module dirs and schema tables — it never looks at repo-root directories. That blind spot is how root `data/` stayed undocumented in both `CLAUDE.md` and `docs/codebase-index.md` while seven `src/lib` modules loaded it at runtime (differentials, forms, medications, services, specifiers), and how it stayed easy to confuse with the unrelated `src/data/`. PR #1436 documented `data/`, `mockups/`, `plugins/`, `eslint-rules/`, `.agents/`, `.claude/` and `.githooks/` by hand, so the maps are correct today with nothing stopping the next one from drifting. **Next:** extend the checker with a repo-root pass plus an allowlist for directories that are deliberately unmapped (build output, `.git`, vendored dirs). Kept out of #1436 deliberately — widening a blocking gate that runs in `verify:cheap` and `static-pr` deserves its own PR and its own red-then-green proof. | PR #1436; `scripts/check-codebase-index-coverage.mjs:1-17`; session 2026-07-30 | 2026-07-30 | +| #136 | P3 | task | Four loose dated docs need source and migration edits before they can be filed | **Outcome:** every dated point-in-time doc lives in `docs/audit/` or `docs/archive/` as `docs/README.md` requires, not loose at the `docs/` top level. **Detail:** PR #1436 filed the five that were docs-only moves. These four are referenced from outside `docs/`, so relocating them means editing source, tests and migration SQL comments — a different risk class than a docs tidy, and not worth bundling into one: `capacity-review.md` (`scripts/soak-test.ts`), `tenancy-defense-in-depth-review.md` (`src/lib/owner-scope.ts`, `tests/owner-scope-guard.test.ts`, two migrations, `SECURITY.md`, `.claude/agents/clinical-governance-reviewer.md`), `operator-apply-july8-batch.md` (three migrations plus `supabase/schema.sql`), `scale-readiness-review.md` (one migration). Also note `forward-codify-retrieval-rpcs-workorder.md` is indexed as a completed workorder but live is still ahead of the repo on those RPCs, so archiving it would misrepresent open operator work. **Next:** treat as low priority — the docs are correctly indexed and reachable where they are; only file them if a pass is already editing those migrations. Editing applied migration SQL is subject to `npm run check:migration-role`'s immutability pin. | PR #1436; session 2026-07-30 | 2026-07-30 | +| #137 | P2 | issue | An uncommitted hook in the main checkout aborts commits in every worktree | **Outcome:** a worktree commit is not blocked by unfinished work sitting in a different checkout. **Detail:** `core.hooksPath` is an absolute path to the primary checkout's `.githooks` (`C:\Dev\Apps\Database\.githooks`), and it is shared by every linked worktree because `git config` writes to the common config file. That primary checkout currently has an **uncommitted** `.githooks/pre-commit` plus `scripts/update-docs-inventory.mjs`; neither is on `origin/main`. The hook therefore fires in worktrees whose branch does not contain the script and dies: `Error: Cannot find module '/scripts/update-docs-inventory.mjs'` — `[pre-commit] Synchronizing generated documentation...` then `MODULE_NOT_FOUND`, commit aborted. Hit directly on PR #1436, worked around per-command with `git -c core.hooksPath=/.githooks commit` (not `--no-verify`, and without touching the shared checkout). **Next:** whoever owns that WIP either commits the hook together with its script or removes the hook; independently, the hook should fail open when its script is missing, the way `.githooks/pre-push` already fails open when `node` is absent. Inverse blind spot to #132: there the hook never runs, here it runs from the wrong tree. | PR #1436 commit attempt; session 2026-07-30 | 2026-07-30 | ## Resolved / archive From cede8ebc77b63b08d3c26b32139efb96b1fd3017 Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Thu, 30 Jul 2026 19:29:11 +0800 Subject: [PATCH 04/15] issues: keep the hook path out of the docs link checker Co-Authored-By: Claude Opus 5 --- docs/outstanding-issues.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/outstanding-issues.md b/docs/outstanding-issues.md index 105a667b2d..c3c3fce470 100644 --- a/docs/outstanding-issues.md +++ b/docs/outstanding-issues.md @@ -159,9 +159,9 @@ removed after current-main verification; it is not missing recommended work. | #132 | P3 | issue | Both client-side push guards are inert for agent pushes | **Outcome:** the format and auto-merge guards protect every push, or their blind spot is explicit. **Detail:** `scripts/guard-push.mjs` printed `auto-merge: gh not available — auto-merge check skipped (fail-open)` for pushes from a remote agent environment, so the auto-merge race sentinel never evaluated; and `core.hooksPath` is set only by a local `npm install`, so an agent pushing from its own checkout bypasses `.githooks/pre-push` entirely. Both guards therefore protect exactly the environment least likely to break the rule, which is why the AGENTS.md format-before-push instruction is still load-bearing even though the tooling now exists. Observed directly on PR #1400: a push landed while auto-merge was armed with nothing to stop it. **Next:** provide `gh` (or a token-based equivalent) in agent environments so the sentinel can evaluate. **Do not move the format check into `pull_request_target`** — that context carries secrets and a write token, and a format check must execute PR-head code including this repo's now-loadable dynamic `prettier.config.*`, which is the classic privileged-context vector; `.github/workflows/pr-policy.yml` deliberately checks out only `github.workflow_sha` for exactly this reason. Formatting is already enforced server-side by `Static PR checks` running `format:check` on ordinary `pull_request` CI, so the guard's only unique value is failing fast before the push — nothing to duplicate. The auto-merge sentinel reads PR metadata only and could safely live in `pull_request_target` if it is ever worth moving. | PR #1400; session 2026-07-30 | 2026-07-30 | | #133 | P3 | rec | `docs/outstanding-issues.md` conflicts on nearly every `main` advance | **Outcome:** two agents editing different rows of this ledger do not conflict. **Detail:** the table is padded to fixed column widths, so a single row's edit re-pads all 59 open rows and git sees the whole table as one changed hunk. On 2026-07-30 this file conflicted twice within an hour on PR #1400, and each conflict silently stopped **all** CI on that PR (`#116`) — so the cost is not the merge itself but the invisible loss of every check while it lasts. Both conflicts were mechanical: only two rows differed semantically out of 58. **Next:** stop padding this table (Prettier will still render it readably, and one-row edits become one-line diffs), or split the open items into per-row files. **Do not** apply a `merge=union` driver — tested 2026-07-30 and it is worse: union concatenates conflicting hunks, so two sides each bumping the marker produce two `next-id` lines, corrupting the file silently where a conflict would fail loudly. `#112`'s new `check:outstanding-issues` gate catches the corrupted result but does not prevent the conflict. | PR #1400; session 2026-07-30 | 2026-07-30 | | #134 | P2 | issue | Ledger union-merge driver is absent wherever `npm install` was skipped | **Outcome:** the ledger's union-merge protection is present wherever a merge happens, or its absence is loud. **Detail:** `.gitattributes` declares `docs/branch-review-ledger.md merge=ledger`, but the driver itself lives in git _config_, installed by `postinstall` -> `scripts/install-git-hooks.mjs`. A container that skips `npm install` (this repo's remote agent sessions do — the session hook reports "node_modules matches the lockfile, skipping install") therefore has the attribute without the driver, and git silently falls back to an ordinary merge. On 2026-07-30 a `git merge origin/main` on PR #1424 produced **conflict markers inside the append-only ledger** at three lines; `git merge` itself did not name the file, so only `npm run check:branch-review-ledger` caught it. Committing that would have corrupted the file the guard exists to protect. **Next:** make the absence loud — have `check:branch-review-ledger` (already in `verify:cheap` and `static-pr`) fail when `.gitattributes` declares `merge=ledger` but `git config merge.ledger.driver` is unset, so the environment is caught before a merge rather than after. `npm run hooks:install` is the one-line fix once detected. **Stop:** never trust a `merge=union`-style attribute to be active just because `.gitattributes` declares it; the driver is per-checkout config. | PR #1424; session 2026-07-30 | 2026-07-30 | -| #135 | P2 | issue | `check:docs-index` has no repo-root directory coverage | **Outcome:** a new top-level directory cannot stay absent from the orientation maps. **Detail:** `scripts/check-codebase-index-coverage.mjs` exists precisely to catch "a module that never gets added to the map, silently staling it", but its granularity is route groups, `src/lib` module dirs and schema tables — it never looks at repo-root directories. That blind spot is how root `data/` stayed undocumented in both `CLAUDE.md` and `docs/codebase-index.md` while seven `src/lib` modules loaded it at runtime (differentials, forms, medications, services, specifiers), and how it stayed easy to confuse with the unrelated `src/data/`. PR #1436 documented `data/`, `mockups/`, `plugins/`, `eslint-rules/`, `.agents/`, `.claude/` and `.githooks/` by hand, so the maps are correct today with nothing stopping the next one from drifting. **Next:** extend the checker with a repo-root pass plus an allowlist for directories that are deliberately unmapped (build output, `.git`, vendored dirs). Kept out of #1436 deliberately — widening a blocking gate that runs in `verify:cheap` and `static-pr` deserves its own PR and its own red-then-green proof. | PR #1436; `scripts/check-codebase-index-coverage.mjs:1-17`; session 2026-07-30 | 2026-07-30 | -| #136 | P3 | task | Four loose dated docs need source and migration edits before they can be filed | **Outcome:** every dated point-in-time doc lives in `docs/audit/` or `docs/archive/` as `docs/README.md` requires, not loose at the `docs/` top level. **Detail:** PR #1436 filed the five that were docs-only moves. These four are referenced from outside `docs/`, so relocating them means editing source, tests and migration SQL comments — a different risk class than a docs tidy, and not worth bundling into one: `capacity-review.md` (`scripts/soak-test.ts`), `tenancy-defense-in-depth-review.md` (`src/lib/owner-scope.ts`, `tests/owner-scope-guard.test.ts`, two migrations, `SECURITY.md`, `.claude/agents/clinical-governance-reviewer.md`), `operator-apply-july8-batch.md` (three migrations plus `supabase/schema.sql`), `scale-readiness-review.md` (one migration). Also note `forward-codify-retrieval-rpcs-workorder.md` is indexed as a completed workorder but live is still ahead of the repo on those RPCs, so archiving it would misrepresent open operator work. **Next:** treat as low priority — the docs are correctly indexed and reachable where they are; only file them if a pass is already editing those migrations. Editing applied migration SQL is subject to `npm run check:migration-role`'s immutability pin. | PR #1436; session 2026-07-30 | 2026-07-30 | -| #137 | P2 | issue | An uncommitted hook in the main checkout aborts commits in every worktree | **Outcome:** a worktree commit is not blocked by unfinished work sitting in a different checkout. **Detail:** `core.hooksPath` is an absolute path to the primary checkout's `.githooks` (`C:\Dev\Apps\Database\.githooks`), and it is shared by every linked worktree because `git config` writes to the common config file. That primary checkout currently has an **uncommitted** `.githooks/pre-commit` plus `scripts/update-docs-inventory.mjs`; neither is on `origin/main`. The hook therefore fires in worktrees whose branch does not contain the script and dies: `Error: Cannot find module '/scripts/update-docs-inventory.mjs'` — `[pre-commit] Synchronizing generated documentation...` then `MODULE_NOT_FOUND`, commit aborted. Hit directly on PR #1436, worked around per-command with `git -c core.hooksPath=/.githooks commit` (not `--no-verify`, and without touching the shared checkout). **Next:** whoever owns that WIP either commits the hook together with its script or removes the hook; independently, the hook should fail open when its script is missing, the way `.githooks/pre-push` already fails open when `node` is absent. Inverse blind spot to #132: there the hook never runs, here it runs from the wrong tree. | PR #1436 commit attempt; session 2026-07-30 | 2026-07-30 | +| #135 | P2 | issue | `check:docs-index` has no repo-root directory coverage | **Outcome:** a new top-level directory cannot stay absent from the orientation maps. **Detail:** `scripts/check-codebase-index-coverage.mjs` exists precisely to catch "a module that never gets added to the map, silently staling it", but its granularity is route groups, `src/lib` module dirs and schema tables — it never looks at repo-root directories. That blind spot is how root `data/` stayed undocumented in both `CLAUDE.md` and `docs/codebase-index.md` while seven `src/lib` modules loaded it at runtime (differentials, forms, medications, services, specifiers), and how it stayed easy to confuse with the unrelated `src/data/`. PR #1436 documented `data/`, `mockups/`, `plugins/`, `eslint-rules/`, `.agents/`, `.claude/` and `.githooks/` by hand, so the maps are correct today with nothing stopping the next one from drifting. **Next:** extend the checker with a repo-root pass plus an allowlist for directories that are deliberately unmapped (build output, `.git`, vendored dirs). Kept out of #1436 deliberately — widening a blocking gate that runs in `verify:cheap` and `static-pr` deserves its own PR and its own red-then-green proof. | PR #1436; `scripts/check-codebase-index-coverage.mjs:1-17`; session 2026-07-30 | 2026-07-30 | +| #136 | P3 | task | Four loose dated docs need source and migration edits before they can be filed | **Outcome:** every dated point-in-time doc lives in `docs/audit/` or `docs/archive/` as `docs/README.md` requires, not loose at the `docs/` top level. **Detail:** PR #1436 filed the five that were docs-only moves. These four are referenced from outside `docs/`, so relocating them means editing source, tests and migration SQL comments — a different risk class than a docs tidy, and not worth bundling into one: `capacity-review.md` (`scripts/soak-test.ts`), `tenancy-defense-in-depth-review.md` (`src/lib/owner-scope.ts`, `tests/owner-scope-guard.test.ts`, two migrations, `SECURITY.md`, `.claude/agents/clinical-governance-reviewer.md`), `operator-apply-july8-batch.md` (three migrations plus `supabase/schema.sql`), `scale-readiness-review.md` (one migration). Also note `forward-codify-retrieval-rpcs-workorder.md` is indexed as a completed workorder but live is still ahead of the repo on those RPCs, so archiving it would misrepresent open operator work. **Next:** treat as low priority — the docs are correctly indexed and reachable where they are; only file them if a pass is already editing those migrations. Editing applied migration SQL is subject to `npm run check:migration-role`'s immutability pin. | PR #1436; session 2026-07-30 | 2026-07-30 | +| #137 | P2 | issue | An uncommitted hook in the main checkout aborts commits in every worktree | **Outcome:** a worktree commit is not blocked by unfinished work sitting in a different checkout. **Detail:** `core.hooksPath` is an absolute path to the primary checkout's `.githooks` (`C:\Dev\Apps\Database\.githooks`), and it is shared by every linked worktree because `git config` writes to the common config file. That primary checkout currently has an **uncommitted** `.githooks/pre-commit` plus an `update-docs-inventory.mjs` under `scripts/`; neither is on `origin/main` (so that path deliberately appears un-linked here — it does not resolve in this repo). The hook therefore fires in worktrees whose branch does not contain the script and dies: `Error: Cannot find module '/scripts/update-docs-inventory.mjs'` — `[pre-commit] Synchronizing generated documentation...` then `MODULE_NOT_FOUND`, commit aborted. Hit directly on PR #1436, worked around per-command with `git -c core.hooksPath=/.githooks commit` (not `--no-verify`, and without touching the shared checkout). **Next:** whoever owns that WIP either commits the hook together with its script or removes the hook; independently, the hook should fail open when its script is missing, the way `.githooks/pre-push` already fails open when `node` is absent. Inverse blind spot to #132: there the hook never runs, here it runs from the wrong tree. | PR #1436 commit attempt; session 2026-07-30 | 2026-07-30 | ## Resolved / archive From 56ca2c6e48adf25ea42f4d23d94cd46ad3e16142 Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Thu, 30 Jul 2026 19:29:11 +0800 Subject: [PATCH 05/15] docs(scripts-index): name every top-level script and correct the stale counts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The index claimed ~135 files and ~166 npm entries against an actual 188 and 203, and 53 top-level scripts were unnamed — including ones AGENTS.md tells agents to run by name: branch-review-ledger.mjs (the only sanctioned way to read or write the review ledger), reconciliation-preflight.mjs, test-focused.mjs, check-hosted-migration-role.mjs and sync-open-pr-branches.mjs. Every one of the 168 top-level .mjs/.ts/.cjs scripts is now named, grouped by purpose in the doc's existing style rather than itemised per file, with new subsections for the review ledger/branch/skill tooling, live and staging verification, and browser and performance capture. The headline counts keep the exact '(N files)' / '(N entries)' shape and use the recursive scripts/ file count, because in-flight tooling in the primary checkout rewrites that sentence by regex; a note above the sentence records that contract so it is not reworded back into prose. Co-Authored-By: Claude Opus 5 --- docs/scripts-index.md | 80 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 16 deletions(-) diff --git a/docs/scripts-index.md b/docs/scripts-index.md index fcd0b25993..ca5319059d 100644 --- a/docs/scripts-index.md +++ b/docs/scripts-index.md @@ -1,9 +1,14 @@ # Scripts index -Curated map of `scripts/` (~135 files) and the `package.json` script surface (~166 entries), +Curated map of `scripts/` (188 files) and the `package.json` script surface (203 entries), grouped by purpose. This is orientation, not an exhaustive per-file listing — the authoritative command list is `package.json`, and `npm run docs:check-scripts` verifies every `npm run ` -referenced in docs resolves to a real script. +referenced in docs resolves to a real script. Every one of the 168 top-level `.mjs`/`.ts`/`.cjs` +scripts is named below; the rest of the 188 are fixtures, SQL and subfolder helpers, and small +shared helpers are grouped rather than itemised. + +> The two counts in the sentence above are generated facts, not prose. Keep them in the exact +> `(N files)` / `(N entries)` shape — tooling rewrites that sentence by regex. Legend: **[live]** routine tooling · **[infra]** runner/guard plumbing · **[one-shot]** completed migration/batch helper that is a candidate for an `archive/` subfolder under `scripts/` once its @@ -11,17 +16,22 @@ migration has shipped (see `docs/maturity-backlog-workorders.md` L1). ## Runner & guard infrastructure [infra] -| Script | Role | -| ------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -| `run-heavy.mjs` | Acquires shared/exclusive cross-worktree leases (`test-run-lock.mjs`) so focused checks can overlap safely | -| `run-tsx.mjs`, `run-vitest.mjs`, `run-playwright.mjs`, `run-eval-safe.mjs` | Typed/test/e2e/eval entrypoint wrappers | -| `dev-free-port.mjs`, `ensure-local-server.mjs` | Project-stable localhost port selection + background server ensure | -| `check-node-engine.cjs`, `install-git-hooks.mjs`, `guard-push.mjs`, `guard-next-build.mjs` | Install/preflight guards | -| `ci-change-scope.mjs`, `ci-triage.mjs`, `pr-policy.mjs`, `pr-mergeability.mjs` | CI change classification + PR policy + conflict signal (self-tested via `check:ci-scope`/`check:ci-triage`/`check:pr-policy`/`check:pr-mergeability`) | -| `check-outstanding-issues.mjs`, `check-pr-mergeability-workflow.mjs` | Outstanding-issues ID/marker/union guard + PR mergeability workflow contract | -| `check-installed-lock-parity.mjs`, `phone-chrome-plan.mjs`, `verify-phone-chrome.mjs` | Lock-trust preflight plus change-scoped phone contracts, ownership journeys, and smart full-UI escalation | -| `final-merge-audit.mjs` | Fail-closed local merge-tree audit; explicit provider mode adds PR/check/thread/tree/deployment proof | -| `child-process-result.mjs`, `cli-utils.ts`, `productivity-core.mjs` | Shared helpers | +| Script | Role | +| ------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | +| `run-heavy.mjs` | Acquires shared/exclusive cross-worktree leases (`test-run-lock.mjs`) so focused checks can overlap safely | +| `run-tsx.mjs`, `run-vitest.mjs`, `run-playwright.mjs`, `run-eval-safe.mjs` | Typed/test/e2e/eval entrypoint wrappers | +| `dev-free-port.mjs`, `ensure-local-server.mjs` | Project-stable localhost port selection + background server ensure | +| `check-node-engine.cjs`, `install-git-hooks.mjs`, `guard-push.mjs`, `guard-next-build.mjs` | Install/preflight guards | +| `ci-change-scope.mjs`, `ci-triage.mjs`, `pr-policy.mjs`, `pr-mergeability.mjs` | CI change classification + PR policy + conflict signal (self-tested via `check:ci-scope`/`check:ci-triage`/`check:pr-policy`/`check:pr-mergeability`) | +| `check-outstanding-issues.mjs`, `check-pr-mergeability-workflow.mjs` | Outstanding-issues ID/marker/union guard + PR mergeability workflow contract | +| `check-installed-lock-parity.mjs`, `phone-chrome-plan.mjs`, `verify-phone-chrome.mjs` | Lock-trust preflight plus change-scoped phone contracts, ownership journeys, and smart full-UI escalation | +| `final-merge-audit.mjs` | Fail-closed local merge-tree audit; explicit provider mode adds PR/check/thread/tree/deployment proof | +| `child-process-result.mjs`, `cli-utils.ts`, `productivity-core.mjs` | Shared helpers | +| `test-focused.mjs`, `test-run-selection.mjs`, `test-cache-path.mjs`, `test-environment.mjs` | Backs `npm run test:focused` — change-scoped selection, cache pathing, env setup; fails closed for deleted files and test infrastructure | +| `primary-checkout-lease.mjs`, `test-run-lock.mjs`, `clean-worktree.mjs` | Cross-worktree lease arbitration for the primary checkout, plus worktree cleanup | +| `resolve-tsx-cli.mjs`, `register-server-only.mjs`, `enable-server-only-stub.mjs` | tsx CLI resolution and `server-only` import shims | +| `check-format-changed.mjs`, `check-base-freshness.mjs`, `check-local-presence.mjs` | Push-time helpers behind `guard-push.mjs`: changed-file formatting, stale-base and local-presence checks | +| `yaml-contract.mjs`, `sensitive-text.mjs`, `design-system-contract-utils.mjs` | Shared parsing/redaction/contract helpers used by the gates | ## Verification gates [live] @@ -35,6 +45,14 @@ migration has shipped (see `docs/maturity-backlog-workorders.md` L1). `verify-release-offline.mjs`. `check-gate-manifest.mjs` cross-checks that every gate in the `verify:cheap:internal` chain also runs in CI's `static-pr` job, so the two lists can't drift. +Also in the gate set: `check-assets.mjs`, `check-branch-review-ledger.mjs`, +`check-hosted-migration-role.mjs` (`check:migration-role` — pins the immutable applied migration and +the `postgres` role), `check-edge-functions.mjs`, `check-env-parity.mjs`, `check-ci-env.mjs`, +`run-gitleaks-pinned.mjs`, `rag-offline-contract.mjs` + `test-rag-offline.mjs` (offline RAG +contract), `check-lighthouse-budget.mjs` + `run-lighthouse-budget.mjs`, and the workflow-contract +guards `check-pr-policy-workflow.mjs` and `check-codex-autofix-workflow.mjs`. +`audit-formatting-fixtures.ts` checks the formatting fixtures themselves. + For executable phone-chrome changes, use `verify:phone-chrome` before the broad UI gate. It checks installed-lock parity, then selects focused contracts and Playwright owners from the changed paths; shared foundations add `verify:ui` last. Documentation-only scopes run only documentation guards. `audit:final-merge` is local-only unless both `--providers` and `ALLOW_PROVIDER_READS=true` are supplied. ## Ingestion, indexing & reindex [live] @@ -57,9 +75,13 @@ For executable phone-chrome changes, use `verify:phone-chrome` before the broad `eval-rag.ts`, `eval-rag-offline.mjs`, `eval-retrieval.ts`, `eval-quality.ts`, `eval-answer-quality.ts`, `eval-search.ts`, `eval-search-api.ts`, `eval-assertions.ts`, `compare-retrieval-eval.ts`, `retrieval-health.ts`, `profile-retrieval-rpcs.ts`, -`warm-retrieval-cache.ts`, `tune-search-weights.ts`, `check-rag-fixtures.mjs`. Golden fixtures: +`warm-retrieval-cache.ts`, `tune-search-weights.ts`, `check-rag-fixtures.mjs`, `eval-trend.mjs` +(trend across runs), `eval-utils.ts` (shared harness helpers). Golden fixtures: `scripts/fixtures/rag-retrieval-golden.json`, `scripts/fixtures/assertion-golden.json`. +Editing anything in this section is a protected-surface change — read `docs/rag-behaviour/` and flag +the task before you start. + ## Registry / catalogue content [live] `seed-registry-records.ts`, `embed-registry-records.ts`, `reconcile-registry-governance.ts`, @@ -77,7 +99,32 @@ For executable phone-chrome changes, use `verify:phone-chrome` before the broad `cleanup-storage.ts`, `purge-query-logs.ts`, `audit-tables.ts`, `supabase-recovery-status.ts`, `promote-query-misses.ts`, `flake-ledger.mjs`, `sweep-branch-ledger.mjs`, `dependency-report.mjs`, -`set-site-administrator.ts`. +`set-site-administrator.ts`, `ops-digest.mjs`, `build-clinical-review-queue.ts`, +`verify-locality-metadata.ts`. + +### Review ledger, branches and skills [live] + +- `branch-review-ledger.mjs` — the **only** way to read or write `docs/branch-review-ledger.md` + (`ledger:lookup` / `ledger:append` / `ledger:dedupe` / `ledger:rotate`). Never hand-write a row. +- `merge-branch-review-ledger.mjs` — the `merge=ledger` union driver from `.gitattributes`; + `check-branch-review-ledger.mjs` fails if that protection is lost. +- `sync-open-pr-branches.mjs` (`sync:pr-branches`) — anti-churn sync for stale open PR heads; + refuses a missing or bot `gh` identity. `sweep-merged-branches.mjs` — merged-branch sweep. +- `reconciliation-preflight.mjs`, `reconciliation-evidence-pack.mjs` — broad chat/worktree + reconciliation entry point and its evidence bundle; see `docs/reconciliation-playbook.md`. +- `list-database-skills.mjs` (`skills` / `check:skills`), `sync-skills.mjs`, `skill-create.mjs` — + the `.agents/skills/` catalogue. + +### Live/staging verification [live] + +`soak-test.ts`, `test-cross-tenant-staging.ts` (the executable owner-boundary proof behind +`docs/staging-tenancy-release-evidence.md`), `deployment-boot-smoke.mjs`, `run-live-tests.mjs`. +These reach live providers — they need explicit confirmation before running. + +### Browser and performance capture [infra] + +`playwright-base-url.ts`, `classify-playwright-failures.mjs`, `capture-chrome-parity.ts`, +`summarise-web-vitals.mjs`. ## One-shot / dated — archive candidates [one-shot] @@ -92,7 +139,8 @@ out of the `tests/**` run. **Remaining candidates** (still in `scripts/`, retire once each is confirmed retired): `check-retrieval-owner-migration.ts`, `backfill-source-metadata.ts`, `backfill-text-normalization.ts`, `backfill-visual-intelligence.ts`, `backfill-document-tags.ts`, `backfill-enrichment.ts`, -`derive-unknown-status.ts`, `reindex-image-generation-metadata.ts`, `measure-wrapped-dose-prevalence.ts`. +`derive-unknown-status.ts`, `reindex-image-generation-metadata.ts`, `measure-wrapped-dose-prevalence.ts`, +`decompose-indexing-v3.mjs`, `repro-coalesce-poison-race.mjs` (a one-off race reproducer). ## Workflow planners [infra] From 977807f624186fc6b90fa86313672a20bfebb74c Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Thu, 30 Jul 2026 19:34:33 +0800 Subject: [PATCH 06/15] issues: record the pre-commit fail-open mitigation and why #137 stays open Co-Authored-By: Claude Opus 5 --- docs/outstanding-issues.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/outstanding-issues.md b/docs/outstanding-issues.md index c3c3fce470..50e547e037 100644 --- a/docs/outstanding-issues.md +++ b/docs/outstanding-issues.md @@ -161,7 +161,7 @@ removed after current-main verification; it is not missing recommended work. | #134 | P2 | issue | Ledger union-merge driver is absent wherever `npm install` was skipped | **Outcome:** the ledger's union-merge protection is present wherever a merge happens, or its absence is loud. **Detail:** `.gitattributes` declares `docs/branch-review-ledger.md merge=ledger`, but the driver itself lives in git _config_, installed by `postinstall` -> `scripts/install-git-hooks.mjs`. A container that skips `npm install` (this repo's remote agent sessions do — the session hook reports "node_modules matches the lockfile, skipping install") therefore has the attribute without the driver, and git silently falls back to an ordinary merge. On 2026-07-30 a `git merge origin/main` on PR #1424 produced **conflict markers inside the append-only ledger** at three lines; `git merge` itself did not name the file, so only `npm run check:branch-review-ledger` caught it. Committing that would have corrupted the file the guard exists to protect. **Next:** make the absence loud — have `check:branch-review-ledger` (already in `verify:cheap` and `static-pr`) fail when `.gitattributes` declares `merge=ledger` but `git config merge.ledger.driver` is unset, so the environment is caught before a merge rather than after. `npm run hooks:install` is the one-line fix once detected. **Stop:** never trust a `merge=union`-style attribute to be active just because `.gitattributes` declares it; the driver is per-checkout config. | PR #1424; session 2026-07-30 | 2026-07-30 | | #135 | P2 | issue | `check:docs-index` has no repo-root directory coverage | **Outcome:** a new top-level directory cannot stay absent from the orientation maps. **Detail:** `scripts/check-codebase-index-coverage.mjs` exists precisely to catch "a module that never gets added to the map, silently staling it", but its granularity is route groups, `src/lib` module dirs and schema tables — it never looks at repo-root directories. That blind spot is how root `data/` stayed undocumented in both `CLAUDE.md` and `docs/codebase-index.md` while seven `src/lib` modules loaded it at runtime (differentials, forms, medications, services, specifiers), and how it stayed easy to confuse with the unrelated `src/data/`. PR #1436 documented `data/`, `mockups/`, `plugins/`, `eslint-rules/`, `.agents/`, `.claude/` and `.githooks/` by hand, so the maps are correct today with nothing stopping the next one from drifting. **Next:** extend the checker with a repo-root pass plus an allowlist for directories that are deliberately unmapped (build output, `.git`, vendored dirs). Kept out of #1436 deliberately — widening a blocking gate that runs in `verify:cheap` and `static-pr` deserves its own PR and its own red-then-green proof. | PR #1436; `scripts/check-codebase-index-coverage.mjs:1-17`; session 2026-07-30 | 2026-07-30 | | #136 | P3 | task | Four loose dated docs need source and migration edits before they can be filed | **Outcome:** every dated point-in-time doc lives in `docs/audit/` or `docs/archive/` as `docs/README.md` requires, not loose at the `docs/` top level. **Detail:** PR #1436 filed the five that were docs-only moves. These four are referenced from outside `docs/`, so relocating them means editing source, tests and migration SQL comments — a different risk class than a docs tidy, and not worth bundling into one: `capacity-review.md` (`scripts/soak-test.ts`), `tenancy-defense-in-depth-review.md` (`src/lib/owner-scope.ts`, `tests/owner-scope-guard.test.ts`, two migrations, `SECURITY.md`, `.claude/agents/clinical-governance-reviewer.md`), `operator-apply-july8-batch.md` (three migrations plus `supabase/schema.sql`), `scale-readiness-review.md` (one migration). Also note `forward-codify-retrieval-rpcs-workorder.md` is indexed as a completed workorder but live is still ahead of the repo on those RPCs, so archiving it would misrepresent open operator work. **Next:** treat as low priority — the docs are correctly indexed and reachable where they are; only file them if a pass is already editing those migrations. Editing applied migration SQL is subject to `npm run check:migration-role`'s immutability pin. | PR #1436; session 2026-07-30 | 2026-07-30 | -| #137 | P2 | issue | An uncommitted hook in the main checkout aborts commits in every worktree | **Outcome:** a worktree commit is not blocked by unfinished work sitting in a different checkout. **Detail:** `core.hooksPath` is an absolute path to the primary checkout's `.githooks` (`C:\Dev\Apps\Database\.githooks`), and it is shared by every linked worktree because `git config` writes to the common config file. That primary checkout currently has an **uncommitted** `.githooks/pre-commit` plus an `update-docs-inventory.mjs` under `scripts/`; neither is on `origin/main` (so that path deliberately appears un-linked here — it does not resolve in this repo). The hook therefore fires in worktrees whose branch does not contain the script and dies: `Error: Cannot find module '/scripts/update-docs-inventory.mjs'` — `[pre-commit] Synchronizing generated documentation...` then `MODULE_NOT_FOUND`, commit aborted. Hit directly on PR #1436, worked around per-command with `git -c core.hooksPath=/.githooks commit` (not `--no-verify`, and without touching the shared checkout). **Next:** whoever owns that WIP either commits the hook together with its script or removes the hook; independently, the hook should fail open when its script is missing, the way `.githooks/pre-push` already fails open when `node` is absent. Inverse blind spot to #132: there the hook never runs, here it runs from the wrong tree. | PR #1436 commit attempt; session 2026-07-30 | 2026-07-30 | +| #137 | P2 | issue | An uncommitted hook in the main checkout aborts commits in every worktree | **Outcome:** a worktree commit is not blocked by unfinished work sitting in a different checkout. **Detail:** `core.hooksPath` is an absolute path to the primary checkout's `.githooks` (`C:\Dev\Apps\Database\.githooks`), and it is shared by every linked worktree because `git config` writes to the common config file. That primary checkout currently has an **uncommitted** `.githooks/pre-commit` plus an `update-docs-inventory.mjs` under `scripts/`; neither is on `origin/main` (so that path deliberately appears un-linked here — it does not resolve in this repo). The hook therefore fires in worktrees whose branch does not contain the script and dies: `Error: Cannot find module '/scripts/update-docs-inventory.mjs'` — `[pre-commit] Synchronizing generated documentation...` then `MODULE_NOT_FOUND`, commit aborted. Hit directly on PR #1436, worked around per-command with `git -c core.hooksPath=/.githooks commit` (not `--no-verify`, and without touching the shared checkout). **Mitigated 2026-07-30, NOT closed:** the hook now fails open — if the inventory task is selected but its script is absent from the committing worktree it prints `skipping inventory sync`, drops that task, and re-checks the all-tasks-empty early exit (without that re-check an empty `docs_to_check` makes the trailing `git diff --name-only --` match every modified file in the tree). Proven by committing from a linked worktree with the shared `core.hooksPath` untouched: exit 0. **Why this is not a fix:** that hook file is _untracked in the primary checkout and committed on no branch_, so the mitigation is not version-controlled — it disappears on overwrite and is absent from any fresh clone or other machine. The script itself IS committed, on `codex/docs-sync-automation-pr` (3 commits ahead of `main`), so the durable fix is to commit `.githooks/pre-commit` alongside it on that branch and let `scripts/install-git-hooks.mjs` distribute it. Inverse blind spot to #132: there the hook never runs, here it runs from the wrong tree. | PR #1436 commit attempt; session 2026-07-30 | 2026-07-30 | ## Resolved / archive From 880ac31d18c29758e50f8a53448f4538604a0595 Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Thu, 30 Jul 2026 20:07:41 +0800 Subject: [PATCH 07/15] docs: record final organization review --- docs/branch-review-ledger.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md index d51dea00b7..e106a1d87e 100644 --- a/docs/branch-review-ledger.md +++ b/docs/branch-review-ledger.md @@ -173,3 +173,4 @@ Records before 2026-07-28 were written by hand and had drifted: 146 lines carrie | 2026-07-30 | PR #1427 / claude/ci-testing-review-2l8klp | b9de34d40d2dc5ab164bb1eb582db1cfcd1009c3 | ci-testing-review | SUPERSEDES the 2026-07-30 db8209be record, which asserted a root cause now REFUTED. That record claimed dragScrollBy clamping made the ui-phone-scroll red; main's #127 carries trace evidence (PR #1404 run 30521269873) that the drag delivered in full (scrollTop 1272 = 552+720) with ~1300px runway spare and a 10s non-flip is a latched state. The change is a diagnostic and guard, NOT a fix, and is now labelled so in the docstring, commit, PR body and #127. Remaining candidates: scrollHidden false vs sharedChromePinned latched; they are indistinguishable from the DOM because only the composite data-scroll-hidden is exposed. Prime suspect in source: composerFocusPinsChrome has a still-the-active-owner guard, headerFocusPinsChrome has none (master-search-header.tsx:397-398). ALSO: this PR ran zero pull_request workflows for ~2h (no CI/Gitleaks/Semgrep, only pull_request_target) because a real conflict blocked refs/pull/1427/merge - issue #116, caught by main's new PR mergeability check. Merging main fixed it and CI ran green first try. | CI run 30530618838 SUCCESS (13m39). MEASURED shard result, correcting the ~7min prediction: Production UI (1) 121 tests 9m36, (2) 111 tests 6m54, (3) 110 tests 6m20 - per-test cost is NOT uniform, shard 1 holds the slow specs, so the largest shard is 9m36 not the predicted 6.8min. ui-critical-fast 3m14. PR required SUCCESS. verify:cheap on merged tree PASS (434 files / 4563 passed, 4 skipped); prettier --check . PASS; ui-phone-scroll ran locally 1x via PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH: 56 passed (5.3m) - three-run protocol NOT completed and not applicable, since this is not a flake fix. | | 2026-07-30 | claude/ci-testing-review-2l8klp | 2e2160bc8b9d2d824209c217c67cb9cac1be3a8d | open PR changed-scope review | APPROVE: three-way UI sharding, critical-first gating, measured drag travel, and gate-manifest updates preserve required-check aggregation and deterministic Playwright settings. | check:github-actions PASS; check:ci-scope PASS; check:gate-manifest PASS; ledger guards PASS; exact-head sharded Production UI required | | 2026-07-30 | PR #1430 | a9ae22ac4915e86d51ee05787059382a39bd8ba8 | phone chrome diagnostics and merge repair | fixed and ready for CI | issues guard; ledger guard; 37 focused tests; phone-chrome dry-run | +| 2026-07-30 | PR-1436 | 9d8e081f3e7003d4f2210b00a7b7e54bf7ca2f0b | PR #1436 documentation organization and link repair | fixed stale no-driver wording and renumbered three union-collided issue records; no remaining findings | docs index, links, scripts, outstanding-issues, and ledger guards pass | From c8169d0f23bb4375d82114c6bd491116a467ed9a Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Thu, 30 Jul 2026 20:19:08 +0800 Subject: [PATCH 08/15] docs: format reconciled issue ledger --- docs/outstanding-issues.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/outstanding-issues.md b/docs/outstanding-issues.md index d49d0ae044..5186d6b096 100644 --- a/docs/outstanding-issues.md +++ b/docs/outstanding-issues.md @@ -82,7 +82,6 @@ removed after current-main verification; it is not missing recommended work. | 34 | `#105` | Optional | High — browser/UI verification | When the heavy-run lock is free | 20–40 minutes | Run `verify:ui` over the ten `LoadingPanel` fallbacks and confirm the Supabase `preconnect` reaches `` on a live page. Implementation already shipped; this row is the outstanding verification only. | | 35 | `#126` | Optional | Standard — repository hygiene | Once per UTC calendar quarter, or when the live ledger grows large | 5–15 minutes | Run `npm run ledger:rotate -- --dry-run`, then `npm run ledger:rotate` if the preview looks right; commit the live+archive diff. Stop if dry-run shows unexpected mass moves or archive path collisions. | - ## Open items From 804780b2eddb171f9cf0506ffade7f2b2e7d6b87 Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Thu, 30 Jul 2026 20:29:18 +0800 Subject: [PATCH 09/15] docs: correct historical CI readiness verdict --- docs/branch-review-ledger.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md index e106a1d87e..243a4f0513 100644 --- a/docs/branch-review-ledger.md +++ b/docs/branch-review-ledger.md @@ -174,3 +174,4 @@ Records before 2026-07-28 were written by hand and had drifted: 146 lines carrie | 2026-07-30 | claude/ci-testing-review-2l8klp | 2e2160bc8b9d2d824209c217c67cb9cac1be3a8d | open PR changed-scope review | APPROVE: three-way UI sharding, critical-first gating, measured drag travel, and gate-manifest updates preserve required-check aggregation and deterministic Playwright settings. | check:github-actions PASS; check:ci-scope PASS; check:gate-manifest PASS; ledger guards PASS; exact-head sharded Production UI required | | 2026-07-30 | PR #1430 | a9ae22ac4915e86d51ee05787059382a39bd8ba8 | phone chrome diagnostics and merge repair | fixed and ready for CI | issues guard; ledger guard; 37 focused tests; phone-chrome dry-run | | 2026-07-30 | PR-1436 | 9d8e081f3e7003d4f2210b00a7b7e54bf7ca2f0b | PR #1436 documentation organization and link repair | fixed stale no-driver wording and renumbered three union-collided issue records; no remaining findings | docs index, links, scripts, outstanding-issues, and ledger guards pass | +| 2026-07-30 | cursor/ci-hygiene-gates-1bf5 | b660dbc5a10d7ca3da03541028017f0abc6b5bd3 | ci-hygiene-gates-merge-readiness | NOT READY: cancel-to-green behavior still allowed required PR CI to pass incorrectly; fixed at subsequent head 8f3283d00da274dee507a1b8e9b611321d1f35be | check:ci-scope; check:gitleaks-pinned; scope-classify PR files ui_changed=false; cancelled-as-neutral simulation exposed #095 | From 15d8ed129e1c166636bc6b970b3db3c81f3e48ba Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Thu, 30 Jul 2026 21:48:36 +0800 Subject: [PATCH 10/15] feat(gates): make docs:check-index cover tracked repo-root directories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit check-codebase-index-coverage.mjs exists to catch "a module that never gets added to the map, silently staling it", but it only looked inside src/ and at supabase/schema.sql. Nothing looked at repo-root directories, which is how root data/ came to be loaded at runtime by seven src/lib modules while appearing in neither CLAUDE.md nor docs/codebase-index.md — and how it stayed easy to confuse with the unrelated src/data/. The new root pass discovers directories from `git ls-files`, not the filesystem: the index documents the repository rather than one machine, so an untracked local scratch directory or node_modules can never fail the gate. Run red-then-green: the gate first reported .cursor, .design-sync and .vscode as unindexed — three real gaps — and passes once documented, covering 49 top-level entries where it previously covered 31. Also corrects two stale counts. docs/scripts-index.md said 188 files and 203 npm entries against an actual 191 and 206, having drifted within the hour as main merged new scripts. CLAUDE.md's hardcoded "~160 files backing 194 npm scripts" is removed rather than restated, because a hand-maintained count in a second place is what produced the drift; it now points at the scripts index. Co-Authored-By: Claude Opus 5 --- CLAUDE.md | 2 +- docs/codebase-index.md | 8 +++++ docs/scripts-index.md | 8 ++--- scripts/check-codebase-index-coverage.mjs | 42 +++++++++++++++++++---- tests/codebase-index-coverage.test.ts | 36 +++++++++++++++++++ 5 files changed, 85 insertions(+), 11 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 498b51f8f9..3bea29332e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -90,7 +90,7 @@ src/data/ Static clinical content (DSM, formulation, therapies indexes) data/ Generated clinical snapshot exports loaded at runtime — regenerate, never hand-edit supabase/ migrations/ (source of truth), schema.sql (mirror), functions/ worker/ Ingestion worker; worker/python/ is the OCR stack -scripts/ ~160 files backing 194 npm scripts: gates, eval, reindex, governance, dev +scripts/ gates, eval, reindex, governance, dev — counted and mapped in docs/scripts-index.md tests/ Vitest unit + Playwright E2E, side by side docs/ Runbooks, governance, plans; docs/README.md categorises them eslint-rules/ Repo-specific lint rules (see Conventions below) diff --git a/docs/codebase-index.md b/docs/codebase-index.md index d0afc40070..4c40680280 100644 --- a/docs/codebase-index.md +++ b/docs/codebase-index.md @@ -43,9 +43,17 @@ Smaller top-level directories that are easy to miss: | `.agents/` | Single-word skill catalogue (`npm run skills`, validated by `npm run check:skills`) | | `.claude/` | Claude Code agents, skills, hooks, settings — plus the `.claude/worktrees/` working copies | | `.githooks/` | Installed by `npm install`; `pre-push` runs `scripts/guard-push.mjs` (format, auto-merge race, drift staleness) | +| `.cursor/` | Cursor's agent definitions, skills and `mcp.json` — the Cursor-side counterpart to `.claude/` | +| `.design-sync/` | State and conventions for the `/design-sync` skill (config, entry component, font vars, notes) | +| `.vscode/` | Recommended-extensions manifest only | **Do not commit:** `.next/`, `node_modules/`, `coverage/`, `.env*`, `sample-documents/`, logs. +`npm run docs:check-index` fails when a tracked repo-root directory, `src/app` route +group, `src/app/api` route, `src/lib` module directory, or `supabase/schema.sql` table is +absent from this file — add the entry, or allowlist it with a reason in +`scripts/check-codebase-index-coverage.mjs`. + --- ## Application architecture diff --git a/docs/scripts-index.md b/docs/scripts-index.md index e2c848a67e..10bddb9cae 100644 --- a/docs/scripts-index.md +++ b/docs/scripts-index.md @@ -1,11 +1,11 @@ # Scripts index -Curated map of `scripts/` (188 files) and the `package.json` script surface (203 entries), +Curated map of `scripts/` (191 files) and the `package.json` script surface (206 entries), grouped by purpose. This is orientation, not an exhaustive per-file listing — the authoritative command list is `package.json`, and `npm run docs:check-scripts` verifies every `npm run ` -referenced in docs resolves to a real script. Every one of the 168 top-level `.mjs`/`.ts`/`.cjs` -scripts is named below; the rest of the 188 are fixtures, SQL and subfolder helpers, and small -shared helpers are grouped rather than itemised. +referenced in docs resolves to a real script. Every top-level `.mjs`/`.ts`/`.cjs`/`.sh` script is +named below; the remainder are fixtures, SQL and subfolder helpers, and small shared helpers are +grouped rather than itemised. > The two counts in the sentence above are generated facts, not prose. Keep them in the exact > `(N files)` / `(N entries)` shape — tooling rewrites that sentence by regex. diff --git a/scripts/check-codebase-index-coverage.mjs b/scripts/check-codebase-index-coverage.mjs index f7ccaad67c..a78e81590c 100644 --- a/scripts/check-codebase-index-coverage.mjs +++ b/scripts/check-codebase-index-coverage.mjs @@ -9,13 +9,19 @@ * staling it. This checks that each top-level directory the index organizes around * is referenced somewhere in it. * - * Granularity is deliberately top-level directories (route groups + src/lib module - * dirs), not every file — the index maps modules by theme, so per-file coverage - * would be pure noise. + * Granularity is deliberately top-level directories (tracked repo-root dirs + + * route groups + src/lib module dirs), not every file — the index maps modules by + * theme, so per-file coverage would be pure noise. + * + * The repo-root pass exists because root `data/` was loaded at runtime by seven + * src/lib modules while appearing in neither CLAUDE.md nor codebase-index.md, and + * nothing caught it: the earlier passes only looked inside src/. Root dirs come + * from `git ls-files`, so an untracked local directory cannot fail the gate. * * Run: `npm run docs:check-index`. Blocking — runs in `verify:cheap:internal` and in * CI (`.github/workflows/ci.yml`, the "Codebase index coverage" step). Exit 1 on gaps. */ +import { execFileSync } from "node:child_process"; import { readFileSync, readdirSync } from "node:fs"; import path from "node:path"; import { fileURLToPath, pathToFileURL } from "node:url"; @@ -38,10 +44,12 @@ function dirsIn(relativeDir) { export function coverageCandidates(kind, name) { if (kind === "api") return [`/api/${name}`]; if (kind === "route") return [`/${name}`]; + if (kind === "root") return [`${name}/`]; return [`${name}/`, `src/lib/${name}/`]; } const SECTION_BOUNDS = { + root: ["## Top-level layout", "## Application architecture"], route: ["### Product pages (`src/app/`)", "### API routes (`src/app/api/`)"], api: ["### API routes (`src/app/api/`)", "## `src/lib/` module map"], lib: ["## `src/lib/` module map", "## Supabase"], @@ -74,10 +82,12 @@ function candidateMatches(span, candidate) { /** Pure: given the index text and the discovered groups, return the uncovered entries. */ export function coverageGaps(indexText, groups, allowlist = ALLOWLIST) { - const spansByKind = new Map(["lib", "route", "api"].map((kind) => [kind, codeSpans(sectionText(indexText, kind))])); + const spansByKind = new Map( + ["lib", "route", "api", "root"].map((kind) => [kind, codeSpans(sectionText(indexText, kind))]), + ); const gaps = []; for (const { kind, dir, name } of groups) { - const full = `${dir}/${name}`; + const full = dir === "." ? name : `${dir}/${name}`; if (allowlist.has(full)) continue; const tried = coverageCandidates(kind, name); const spans = spansByKind.get(kind) ?? []; @@ -103,8 +113,28 @@ export function schemaTableGaps(indexText, schemaText) { }; } +/** + * Tracked top-level directories, read from git rather than the filesystem: the + * index documents the repository, not one machine, so an untracked local + * scratch directory (or node_modules) must never fail this gate. + */ +function trackedRootDirs() { + const output = execFileSync("git", ["ls-files", "-z"], { + cwd: repoRoot, + encoding: "utf8", + maxBuffer: 64 * 1024 * 1024, + }); + const dirs = new Set(); + for (const file of output.split("\0")) { + const slash = file.indexOf("/"); + if (slash > 0) dirs.add(file.slice(0, slash)); + } + return [...dirs].sort(); +} + function discoverGroups() { const groups = []; + for (const name of trackedRootDirs()) groups.push({ kind: "root", dir: ".", name }); for (const name of dirsIn("src/lib")) groups.push({ kind: "lib", dir: "src/lib", name }); for (const name of dirsIn("src/app")) { if (name === "api") continue; @@ -122,7 +152,7 @@ function main() { const tables = schemaTableGaps(indexText, schemaText); if (gaps.length > 0 || tables.missing.length > 0 || tables.stale.length > 0) { - console.error(`\n${INDEX_PATH} is missing ${gaps.length} top-level module(s)/route(s):`); + console.error(`\n${INDEX_PATH} is missing ${gaps.length} top-level directory/module(s)/route(s):`); for (const g of gaps) console.error(` UNINDEXED ${g.full} (${g.kind}) — add it or allowlist it`); for (const table of tables.missing) console.error(` UNINDEXED public.${table} (schema table)`); for (const table of tables.stale) console.error(` STALE ${table} (not present in ${SCHEMA_PATH})`); diff --git a/tests/codebase-index-coverage.test.ts b/tests/codebase-index-coverage.test.ts index b69045f94a..c63cfea7fc 100644 --- a/tests/codebase-index-coverage.test.ts +++ b/tests/codebase-index-coverage.test.ts @@ -2,6 +2,17 @@ import { describe, expect, it } from "vitest"; import { coverageGaps, schemaTableGaps } from "../scripts/check-codebase-index-coverage.mjs"; const index = ` +## Top-level layout + +| Path | Purpose | +| ---- | ------- | +| \`src/\` | app code | +| \`data/\` | generated snapshot exports | + +**Do not commit:** \`node_modules/\`. + +## Application architecture + ### Product pages (\`src/app/\`) Routes: \`/documents\`, \`/reference/colour-coding\`. @@ -53,6 +64,31 @@ describe("coverageGaps", () => { expect(gaps.map((gap) => gap.full)).toEqual(["src/app/api/medications"]); }); + it("reports a tracked repo-root directory that the layout section never names", () => { + const gaps = coverageGaps(index, [{ kind: "root", dir: ".", name: "worker" }]); + expect(gaps.map((gap) => gap.full)).toEqual(["worker"]); + }); + + it("treats a root directory named in the layout section as covered", () => { + const gaps = coverageGaps(index, [ + { kind: "root", dir: ".", name: "src" }, + { kind: "root", dir: ".", name: "data" }, + ]); + expect(gaps).toEqual([]); + }); + + it("does not let a src/lib module name satisfy a repo-root directory", () => { + // `validation/` is named in the src/lib section only; root coverage must not + // borrow it, otherwise a root dir sharing a module name is silently covered. + const gaps = coverageGaps(index, [{ kind: "root", dir: ".", name: "validation" }]); + expect(gaps.map((gap) => gap.full)).toEqual(["validation"]); + }); + + it("honours the allowlist for root directories", () => { + const gaps = coverageGaps(index, [{ kind: "root", dir: ".", name: "worker" }], new Set(["worker"])); + expect(gaps).toEqual([]); + }); + it("honours the allowlist", () => { const gaps = coverageGaps(index, [{ kind: "route", dir: "src/app", name: "icons" }], new Set(["src/app/icons"])); expect(gaps).toEqual([]); From 8bb9ea51520ac5c6c0ef0e1bb5c60feac46fae25 Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Thu, 30 Jul 2026 21:48:36 +0800 Subject: [PATCH 11/15] =?UTF-8?q?issues:=20correct=20#137=20=E2=80=94=20th?= =?UTF-8?q?e=20hook=20was=20committed=20all=20along,=20the=20MSYS=20ref:pa?= =?UTF-8?q?th=20check=20lied?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5 --- docs/outstanding-issues.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/outstanding-issues.md b/docs/outstanding-issues.md index 5186d6b096..383646fc08 100644 --- a/docs/outstanding-issues.md +++ b/docs/outstanding-issues.md @@ -161,7 +161,7 @@ removed after current-main verification; it is not missing recommended work. | #134 | P2 | issue | Ledger union-merge driver is absent wherever `npm install` was skipped | **Outcome:** the ledger's union-merge protection is present wherever a merge happens, or its absence is loud. **Detail:** `.gitattributes` declares `docs/branch-review-ledger.md merge=ledger`, but the driver itself lives in git _config_, installed by `postinstall` -> `scripts/install-git-hooks.mjs`. A container that skips `npm install` (this repo's remote agent sessions do — the session hook reports "node_modules matches the lockfile, skipping install") therefore has the attribute without the driver, and git silently falls back to an ordinary merge. On 2026-07-30 a `git merge origin/main` on PR #1424 produced **conflict markers inside the append-only ledger** at three lines; `git merge` itself did not name the file, so only `npm run check:branch-review-ledger` caught it. Committing that would have corrupted the file the guard exists to protect. **Next:** make the absence loud — have `check:branch-review-ledger` (already in `verify:cheap` and `static-pr`) fail when `.gitattributes` declares `merge=ledger` but `git config merge.ledger.driver` is unset, so the environment is caught before a merge rather than after. `npm run hooks:install` is the one-line fix once detected. **Stop:** never trust a `merge=union`-style attribute to be active just because `.gitattributes` declares it; the driver is per-checkout config. | PR #1424; session 2026-07-30 | 2026-07-30 | | #141 | P2 | issue | `check:docs-index` has no repo-root directory coverage | **Outcome:** a new top-level directory cannot stay absent from the orientation maps. **Detail:** `scripts/check-codebase-index-coverage.mjs` exists precisely to catch "a module that never gets added to the map, silently staling it", but its granularity is route groups, `src/lib` module dirs and schema tables — it never looks at repo-root directories. That blind spot is how root `data/` stayed undocumented in both `CLAUDE.md` and `docs/codebase-index.md` while seven `src/lib` modules loaded it at runtime (differentials, forms, medications, services, specifiers), and how it stayed easy to confuse with the unrelated `src/data/`. PR #1436 documented `data/`, `mockups/`, `plugins/`, `eslint-rules/`, `.agents/`, `.claude/` and `.githooks/` by hand, so the maps are correct today with nothing stopping the next one from drifting. **Next:** extend the checker with a repo-root pass plus an allowlist for directories that are deliberately unmapped (build output, `.git`, vendored dirs). Kept out of #1436 deliberately — widening a blocking gate that runs in `verify:cheap` and `static-pr` deserves its own PR and its own red-then-green proof. | PR #1436; `scripts/check-codebase-index-coverage.mjs:1-17`; session 2026-07-30 | 2026-07-30 | | #142 | P3 | task | Four loose dated docs need source and migration edits before they can be filed | **Outcome:** every dated point-in-time doc lives in `docs/audit/` or `docs/archive/` as `docs/README.md` requires, not loose at the `docs/` top level. **Detail:** PR #1436 filed the five that were docs-only moves. These four are referenced from outside `docs/`, so relocating them means editing source, tests and migration SQL comments — a different risk class than a docs tidy, and not worth bundling into one: `capacity-review.md` (`scripts/soak-test.ts`), `tenancy-defense-in-depth-review.md` (`src/lib/owner-scope.ts`, `tests/owner-scope-guard.test.ts`, two migrations, `SECURITY.md`, `.claude/agents/clinical-governance-reviewer.md`), `operator-apply-july8-batch.md` (three migrations plus `supabase/schema.sql`), `scale-readiness-review.md` (one migration). Also note `forward-codify-retrieval-rpcs-workorder.md` is indexed as a completed workorder but live is still ahead of the repo on those RPCs, so archiving it would misrepresent open operator work. **Next:** treat as low priority — the docs are correctly indexed and reachable where they are; only file them if a pass is already editing those migrations. Editing applied migration SQL is subject to `npm run check:migration-role`'s immutability pin. | PR #1436; session 2026-07-30 | 2026-07-30 | -| #143 | P2 | issue | An uncommitted hook in the main checkout aborts commits in every worktree | **Outcome:** a worktree commit is not blocked by unfinished work sitting in a different checkout. **Detail:** `core.hooksPath` is an absolute path to the primary checkout's `.githooks` (`C:\Dev\Apps\Database\.githooks`), and it is shared by every linked worktree because `git config` writes to the common config file. That primary checkout currently has an **uncommitted** `.githooks/pre-commit` plus an `update-docs-inventory.mjs` under `scripts/`; neither is on `origin/main` (so that path deliberately appears un-linked here — it does not resolve in this repo). The hook therefore fires in worktrees whose branch does not contain the script and dies: `Error: Cannot find module '/scripts/update-docs-inventory.mjs'` — `[pre-commit] Synchronizing generated documentation...` then `MODULE_NOT_FOUND`, commit aborted. Hit directly on PR #1436, worked around per-command with `git -c core.hooksPath=/.githooks commit` (not `--no-verify`, and without touching the shared checkout). **Mitigated 2026-07-30, NOT closed:** the hook now fails open — if the inventory task is selected but its script is absent from the committing worktree it prints `skipping inventory sync`, drops that task, and re-checks the all-tasks-empty early exit (without that re-check an empty `docs_to_check` makes the trailing `git diff --name-only --` match every modified file in the tree). Proven by committing from a linked worktree with the shared `core.hooksPath` untouched: exit 0. **Why this is not a fix:** that hook file is _untracked in the primary checkout and committed on no branch_, so the mitigation is not version-controlled — it disappears on overwrite and is absent from any fresh clone or other machine. The script itself IS committed, on `codex/docs-sync-automation-pr` (3 commits ahead of `main`), so the durable fix is to commit `.githooks/pre-commit` alongside it on that branch and let `scripts/install-git-hooks.mjs` distribute it. Inverse blind spot to #132: there the hook never runs, here it runs from the wrong tree. | PR #1436 commit attempt; session 2026-07-30 | 2026-07-30 | +| #143 | P2 | issue | An uncommitted hook in the main checkout aborts commits in every worktree | **Outcome:** a worktree commit is not blocked by unfinished work sitting in a different checkout. **Detail:** `core.hooksPath` is an absolute path to the primary checkout's `.githooks` (`C:\Dev\Apps\Database\.githooks`), and it is shared by every linked worktree because `git config` writes to the common config file. That primary checkout currently has an **uncommitted** `.githooks/pre-commit` plus an `update-docs-inventory.mjs` under `scripts/`; neither is on `origin/main` (so that path deliberately appears un-linked here — it does not resolve in this repo). The hook therefore fires in worktrees whose branch does not contain the script and dies: `Error: Cannot find module '/scripts/update-docs-inventory.mjs'` — `[pre-commit] Synchronizing generated documentation...` then `MODULE_NOT_FOUND`, commit aborted. Hit directly on PR #1436, worked around per-command with `git -c core.hooksPath=/.githooks commit` (not `--no-verify`, and without touching the shared checkout). **Mitigated 2026-07-30, NOT closed:** the hook now fails open — if the inventory task is selected but its script is absent from the committing worktree it prints `skipping inventory sync`, drops that task, and re-checks the all-tasks-empty early exit (without that re-check an empty `docs_to_check` makes the trailing `git diff --name-only --` match every modified file in the tree). Proven by committing from a linked worktree with the shared `core.hooksPath` untouched: exit 0. **Why this is not a fix:** that hook file is _untracked in the primary checkout and untracked in the primary checkout_, so a mitigation applied there is not version-controlled — it disappears on overwrite and is absent from any fresh clone. **Correction:** an earlier revision of this row claimed the hook was committed on no branch. That was wrong — it came from MSYS mangling a `ref:path` argument into `codex\docs-sync-automation-pr;.githooks\pre-commit`, so `git cat-file -e` failed for path reasons and the failure was misread as absence; `git ls-tree` shows blob `ce148e948`. Both the hook and its script are committed on `codex/docs-sync-automation-pr`, and the fail-open now is too (`d2fd16d54`, applied on top of that branch's newer version, which carries a mixed-inputs guard the primary checkout's untracked copy lacks). **What remains:** that branch has never been pushed, so nothing is distributed yet — the fix lands only when it is pushed, reviewed and merged, after which `scripts/install-git-hooks.mjs` propagates the hook. Until then every fresh checkout still has the untracked-only copy. Inverse blind spot to #132: there the hook never runs, here it runs from the wrong tree. | PR #1436 commit attempt; session 2026-07-30 | 2026-07-30 | | #135 | P2 | rec | UI scope overfires: `ui_changed` matches every `src/app` path | **Outcome:** a change that cannot alter a rendered journey stops paying the longest job in CI. **Detail:** `uiPatterns` in `scripts/ci-change-scope.mjs` matches all of `src/app`, so an edit confined to `src/app/api/**` sets `ui_changed` and runs the full Chromium gate — measured 2026-07-30 at 15m26 of an 18m36 run, the entire critical path. **Next:** decide whether API-only diffs can be excluded. **Not done blind, deliberately:** the journeys exercise a production build that serves those routes, so a naive exclusion can hide a real regression; this needs a decision plus a compensating check, not a quieter filter. Sharding `ui-critical` (PR #1427) cut the cost of over-firing but did not remove it. | `scripts/ci-change-scope.mjs`; CI runs 30520443076 / 30519912667; session 2026-07-30 | 2026-07-30 | | #136 | P2 | rec | Playwright's isolated production build cannot reuse Next's build cache | **Outcome:** the fixed ~2 min build stops being repaid on every UI job and every shard. **Detail:** `scripts/run-playwright.mjs` builds into `.next-playwright/${pid}-${Date.now()}/dist`, so Next's webpack filesystem cache (which lives under `distDir`) is cold every run — ~1m56 of the 15m26 `Chromium production journeys` step measured 2026-07-30, and a larger share of the sharded critical path. The `build` job already caches `.next/cache` correctly; this path simply cannot hit it. **Next:** allow the run root to be pinned via an env var (defaulting to today's behaviour) and cache it in `ui-critical`. **Blocker:** the runner removes the run root on every exit path, which `docs/testing.md` states as a contract, so caching needs an explicit keep flag and must not ship without executing the runner. | `scripts/run-playwright.mjs`; `docs/testing.md`; session 2026-07-30 | 2026-07-30 | | #137 | P3 | rec | Advisory UI spends ~3 min per UI PR on five mockup tests | **Outcome:** the advisory lane costs what its signal is worth. **Detail:** `ui-advisory` runs on every UI PR (3m14 measured 2026-07-30) to cover `@quarantine` plus `@mockup` journeys — but `tests/flake-ledger.json` is empty and there are **zero** `@quarantine` tests in the suite, so it executes 5 `@mockup` tests. It is `continue-on-error` and outside `pr-required`, so it can also rot unnoticed. **Next:** gate it on mockup-file scope, or accept the cost as the price of keeping the lane warm for future quarantines. Either is defensible; the current state is just unmeasured. | `.github/workflows/ci.yml` `ui-advisory`; `tests/flake-ledger.json`; session 2026-07-30 | 2026-07-30 | From 0fc4e093b7503c4b923b46475197993b34ba4d9c Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Thu, 30 Jul 2026 21:50:29 +0800 Subject: [PATCH 12/15] docs(ledger): record the docs:check-index root-coverage review for PR #1458 Co-Authored-By: Claude Opus 5 --- docs/branch-review-ledger.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md index 243a4f0513..eaed2c5fd2 100644 --- a/docs/branch-review-ledger.md +++ b/docs/branch-review-ledger.md @@ -175,3 +175,4 @@ Records before 2026-07-28 were written by hand and had drifted: 146 lines carrie | 2026-07-30 | PR #1430 | a9ae22ac4915e86d51ee05787059382a39bd8ba8 | phone chrome diagnostics and merge repair | fixed and ready for CI | issues guard; ledger guard; 37 focused tests; phone-chrome dry-run | | 2026-07-30 | PR-1436 | 9d8e081f3e7003d4f2210b00a7b7e54bf7ca2f0b | PR #1436 documentation organization and link repair | fixed stale no-driver wording and renumbered three union-collided issue records; no remaining findings | docs index, links, scripts, outstanding-issues, and ledger guards pass | | 2026-07-30 | cursor/ci-hygiene-gates-1bf5 | b660dbc5a10d7ca3da03541028017f0abc6b5bd3 | ci-hygiene-gates-merge-readiness | NOT READY: cancel-to-green behavior still allowed required PR CI to pass incorrectly; fixed at subsequent head 8f3283d00da274dee507a1b8e9b611321d1f35be | check:ci-scope; check:gitleaks-pinned; scope-classify PR files ui_changed=false; cancelled-as-neutral simulation exposed #095 | +| 2026-07-30 | claude/root-dir-coverage-gate-v2 | 8bb9ea51520ac5c6c0ef0e1bb5c60feac46fae25 | docs:check-index repo-root coverage pass, stale script counts, #137 correction | PR #1458 opened (stacked on #1436 — merge that first). docs:check-index now discovers tracked repo-root dirs via git ls-files; red-then-green proven (flagged .cursor/.design-sync/.vscode, then 49 entries covered vs 31). scripts-index counts corrected 188/203 to 191/206; CLAUDE.md hardcoded count removed in favour of the index; ledger #137 corrected after an MSYS ref:path mangling was misread as the hook being uncommitted | verify:cheap exit 0 — 435 test files, 4574 tests pass, 3 skipped; codebase-index-coverage 10/10 incl 4 new root cases; eslint clean; docs:check-links 1401 refs; docs:check-scripts 396; check:outstanding-issues 141 rows; prettier clean | From f275fddcb0e2b91806f1badee3287d3bbe79964c Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Thu, 30 Jul 2026 22:23:09 +0800 Subject: [PATCH 13/15] docs: clarify untracked hook mitigation --- docs/branch-review-ledger.md | 1 + docs/outstanding-issues.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md index 015ecb4b67..74a0a216b9 100644 --- a/docs/branch-review-ledger.md +++ b/docs/branch-review-ledger.md @@ -178,3 +178,4 @@ Records before 2026-07-28 were written by hand and had drifted: 146 lines carrie | 2026-07-30 | claude/root-dir-coverage-gate-v2 | 8bb9ea51520ac5c6c0ef0e1bb5c60feac46fae25 | docs:check-index repo-root coverage pass, stale script counts, #137 correction | PR #1458 opened (stacked on #1436 — merge that first). docs:check-index now discovers tracked repo-root dirs via git ls-files; red-then-green proven (flagged .cursor/.design-sync/.vscode, then 49 entries covered vs 31). scripts-index counts corrected 188/203 to 191/206; CLAUDE.md hardcoded count removed in favour of the index; ledger #137 corrected after an MSYS ref:path mangling was misread as the hook being uncommitted | verify:cheap exit 0 — 435 test files, 4574 tests pass, 3 skipped; codebase-index-coverage 10/10 incl 4 new root cases; eslint clean; docs:check-links 1401 refs; docs:check-scripts 396; check:outstanding-issues 141 rows; prettier clean | | 2026-07-30 | PR-1440 | f7260cc6a0da87cb4df1ac95ef962967e667c3f0 | PR #1440 issue #102 ordering correction | accurately restores the two canary-gated retrieval ordering constraints; no findings | outstanding-issues and ledger guards pass; documentation-only diff | | 2026-07-30 | PR-1445 | 07933e08cff6c7d81345e02c03727032ccf522b6 | PR #1445 close duplicate issue | correctly archives duplicate #140 while preserving #133 as the surviving open conflict-frequency record; no findings | outstanding-issues and docs-link guards pass; docs-only diff | +| 2026-07-30 | PR #1458 | b100657229242671221c8aebf387f08ff83c21d1 | tracked root-directory documentation coverage | APPROVE after fix: tracked-root discovery is fail-closed without local scratch noise, and the hook-distribution note now identifies the untracked fail-open copy precisely. | codebase-index focused test; docs index and link guards; issue and ledger guards; one review finding fixed | diff --git a/docs/outstanding-issues.md b/docs/outstanding-issues.md index 7380fa2c79..413901c629 100644 --- a/docs/outstanding-issues.md +++ b/docs/outstanding-issues.md @@ -160,7 +160,7 @@ removed after current-main verification; it is not missing recommended work. | #134 | P2 | issue | Ledger union-merge driver is absent wherever `npm install` was skipped | **Outcome:** the ledger's union-merge protection is present wherever a merge happens, or its absence is loud. **Detail:** `.gitattributes` declares `docs/branch-review-ledger.md merge=ledger`, but the driver itself lives in git _config_, installed by `postinstall` -> `scripts/install-git-hooks.mjs`. A container that skips `npm install` (this repo's remote agent sessions do — the session hook reports "node_modules matches the lockfile, skipping install") therefore has the attribute without the driver, and git silently falls back to an ordinary merge. On 2026-07-30 a `git merge origin/main` on PR #1424 produced **conflict markers inside the append-only ledger** at three lines; `git merge` itself did not name the file, so only `npm run check:branch-review-ledger` caught it. Committing that would have corrupted the file the guard exists to protect. **Next:** make the absence loud — have `check:branch-review-ledger` (already in `verify:cheap` and `static-pr`) fail when `.gitattributes` declares `merge=ledger` but `git config merge.ledger.driver` is unset, so the environment is caught before a merge rather than after. `npm run hooks:install` is the one-line fix once detected. **Stop:** never trust a `merge=union`-style attribute to be active just because `.gitattributes` declares it; the driver is per-checkout config. | PR #1424; session 2026-07-30 | 2026-07-30 | | #144 | P2 | issue | `check:docs-index` has no repo-root directory coverage | **Outcome:** a new top-level directory cannot stay absent from the orientation maps. **Detail:** `scripts/check-codebase-index-coverage.mjs` exists precisely to catch "a module that never gets added to the map, silently staling it", but its granularity is route groups, `src/lib` module dirs and schema tables — it never looks at repo-root directories. That blind spot is how root `data/` stayed undocumented in both `CLAUDE.md` and `docs/codebase-index.md` while seven `src/lib` modules loaded it at runtime (differentials, forms, medications, services, specifiers), and how it stayed easy to confuse with the unrelated `src/data/`. PR #1436 documented `data/`, `mockups/`, `plugins/`, `eslint-rules/`, `.agents/`, `.claude/` and `.githooks/` by hand, so the maps are correct today with nothing stopping the next one from drifting. **Next:** extend the checker with a repo-root pass plus an allowlist for directories that are deliberately unmapped (build output, `.git`, vendored dirs). Kept out of #1436 deliberately — widening a blocking gate that runs in `verify:cheap` and `static-pr` deserves its own PR and its own red-then-green proof. | PR #1436; `scripts/check-codebase-index-coverage.mjs:1-17`; session 2026-07-30 | 2026-07-30 | | #142 | P3 | task | Four loose dated docs need source and migration edits before they can be filed | **Outcome:** every dated point-in-time doc lives in `docs/audit/` or `docs/archive/` as `docs/README.md` requires, not loose at the `docs/` top level. **Detail:** PR #1436 filed the five that were docs-only moves. These four are referenced from outside `docs/`, so relocating them means editing source, tests and migration SQL comments — a different risk class than a docs tidy, and not worth bundling into one: `capacity-review.md` (`scripts/soak-test.ts`), `tenancy-defense-in-depth-review.md` (`src/lib/owner-scope.ts`, `tests/owner-scope-guard.test.ts`, two migrations, `SECURITY.md`, `.claude/agents/clinical-governance-reviewer.md`), `operator-apply-july8-batch.md` (three migrations plus `supabase/schema.sql`), `scale-readiness-review.md` (one migration). Also note `forward-codify-retrieval-rpcs-workorder.md` is indexed as a completed workorder but live is still ahead of the repo on those RPCs, so archiving it would misrepresent open operator work. **Next:** treat as low priority — the docs are correctly indexed and reachable where they are; only file them if a pass is already editing those migrations. Editing applied migration SQL is subject to `npm run check:migration-role`'s immutability pin. | PR #1436; session 2026-07-30 | 2026-07-30 | -| #143 | P2 | issue | An uncommitted hook in the main checkout aborts commits in every worktree | **Outcome:** a worktree commit is not blocked by unfinished work sitting in a different checkout. **Detail:** `core.hooksPath` is an absolute path to the primary checkout's `.githooks` (`C:\Dev\Apps\Database\.githooks`), and it is shared by every linked worktree because `git config` writes to the common config file. That primary checkout currently has an **uncommitted** `.githooks/pre-commit` plus an `update-docs-inventory.mjs` under `scripts/`; neither is on `origin/main` (so that path deliberately appears un-linked here — it does not resolve in this repo). The hook therefore fires in worktrees whose branch does not contain the script and dies: `Error: Cannot find module '/scripts/update-docs-inventory.mjs'` — `[pre-commit] Synchronizing generated documentation...` then `MODULE_NOT_FOUND`, commit aborted. Hit directly on PR #1436, worked around per-command with `git -c core.hooksPath=/.githooks commit` (not `--no-verify`, and without touching the shared checkout). **Mitigated 2026-07-30, NOT closed:** the hook now fails open — if the inventory task is selected but its script is absent from the committing worktree it prints `skipping inventory sync`, drops that task, and re-checks the all-tasks-empty early exit (without that re-check an empty `docs_to_check` makes the trailing `git diff --name-only --` match every modified file in the tree). Proven by committing from a linked worktree with the shared `core.hooksPath` untouched: exit 0. **Why this is not a fix:** that hook file is _untracked in the primary checkout and untracked in the primary checkout_, so a mitigation applied there is not version-controlled — it disappears on overwrite and is absent from any fresh clone. **Correction:** an earlier revision of this row claimed the hook was committed on no branch. That was wrong — it came from MSYS mangling a `ref:path` argument into `codex\docs-sync-automation-pr;.githooks\pre-commit`, so `git cat-file -e` failed for path reasons and the failure was misread as absence; `git ls-tree` shows blob `ce148e948`. Both the hook and its script are committed on `codex/docs-sync-automation-pr`, and the fail-open now is too (`d2fd16d54`, applied on top of that branch's newer version, which carries a mixed-inputs guard the primary checkout's untracked copy lacks). **What remains:** that branch has never been pushed, so nothing is distributed yet — the fix lands only when it is pushed, reviewed and merged, after which `scripts/install-git-hooks.mjs` propagates the hook. Until then every fresh checkout still has the untracked-only copy. Inverse blind spot to #132: there the hook never runs, here it runs from the wrong tree. | PR #1436 commit attempt; session 2026-07-30 | 2026-07-30 | +| #143 | P2 | issue | An uncommitted hook in the main checkout aborts commits in every worktree | **Outcome:** a worktree commit is not blocked by unfinished work sitting in a different checkout. **Detail:** `core.hooksPath` is an absolute path to the primary checkout's `.githooks` (`C:\Dev\Apps\Database\.githooks`), and it is shared by every linked worktree because `git config` writes to the common config file. That primary checkout currently has an **uncommitted** `.githooks/pre-commit` plus an `update-docs-inventory.mjs` under `scripts/`; neither is on `origin/main` (so that path deliberately appears un-linked here — it does not resolve in this repo). The hook therefore fires in worktrees whose branch does not contain the script and dies: `Error: Cannot find module '/scripts/update-docs-inventory.mjs'` — `[pre-commit] Synchronizing generated documentation...` then `MODULE_NOT_FOUND`, commit aborted. Hit directly on PR #1436, worked around per-command with `git -c core.hooksPath=/.githooks commit` (not `--no-verify`, and without touching the shared checkout). **Mitigated 2026-07-30, NOT closed:** the hook now fails open — if the inventory task is selected but its script is absent from the committing worktree it prints `skipping inventory sync`, drops that task, and re-checks the all-tasks-empty early exit (without that re-check an empty `docs_to_check` makes the trailing `git diff --name-only --` match every modified file in the tree). Proven by committing from a linked worktree with the shared `core.hooksPath` untouched: exit 0. **Why this is not a fix:** the fail-open copy used by the primary checkout's shared `core.hooksPath` is untracked, so the mitigation is not version-controlled — it disappears on overwrite and is absent from any fresh clone. **Correction:** an earlier revision of this row claimed the hook was committed on no branch. That was wrong — it came from MSYS mangling a `ref:path` argument into `codex\docs-sync-automation-pr;.githooks\pre-commit`, so `git cat-file -e` failed for path reasons and the failure was misread as absence; `git ls-tree` shows blob `ce148e948`. Both the hook and its script are committed on `codex/docs-sync-automation-pr`, and the fail-open now is too (`d2fd16d54`, applied on top of that branch's newer version, which carries a mixed-inputs guard the primary checkout's untracked copy lacks). **What remains:** that branch has never been pushed, so nothing is distributed yet — the fix lands only when it is pushed, reviewed and merged, after which `scripts/install-git-hooks.mjs` propagates the hook. Until then every fresh checkout still has the untracked-only copy. Inverse blind spot to #132: there the hook never runs, here it runs from the wrong tree. | PR #1436 commit attempt; session 2026-07-30 | 2026-07-30 | | #135 | P2 | rec | UI scope overfires: `ui_changed` matches every `src/app` path | **Outcome:** a change that cannot alter a rendered journey stops paying the longest job in CI. **Detail:** `uiPatterns` in `scripts/ci-change-scope.mjs` matches all of `src/app`, so an edit confined to `src/app/api/**` sets `ui_changed` and runs the full Chromium gate — measured 2026-07-30 at 15m26 of an 18m36 run, the entire critical path. **Next:** decide whether API-only diffs can be excluded. **Not done blind, deliberately:** the journeys exercise a production build that serves those routes, so a naive exclusion can hide a real regression; this needs a decision plus a compensating check, not a quieter filter. Sharding `ui-critical` (PR #1427) cut the cost of over-firing but did not remove it. **VALIDATED 2026-07-30, and it is already implemented:** `isUiChangedPath` in `scripts/ci-change-scope.mjs` already excludes `src/app/api/**`. A naive grep suggested a coverage hole — 16 of 17 API route groups appear in Playwright specs — but 92 of those references are `page.route(` / `context.route(` **stubs**, not real calls: the journeys mock the API layer, so an API handler change genuinely cannot move them. The exclusion is correct and the measurement now says so. **Stop:** do not re-open on a bare grep for `/api/` in specs; check whether the reference is an interception before concluding anything. | `scripts/ci-change-scope.mjs`; CI runs 30520443076 / 30519912667; session 2026-07-30 | 2026-07-30 | | #136 | P2 | rec | Playwright's isolated production build cannot reuse Next's build cache | **Outcome:** the fixed ~2 min build stops being repaid on every UI job and every shard. **Detail:** `scripts/run-playwright.mjs` builds into `.next-playwright/${pid}-${Date.now()}/dist`, so Next's webpack filesystem cache (which lives under `distDir`) is cold every run — ~1m56 of the 15m26 `Chromium production journeys` step measured 2026-07-30, and a larger share of the sharded critical path. The `build` job already caches `.next/cache` correctly; this path simply cannot hit it. **Next:** allow the run root to be pinned via an env var (defaulting to today's behaviour) and cache it in `ui-critical`. **Blocker:** the runner removes the run root on every exit path, which `docs/testing.md` states as a contract, so caching needs an explicit keep flag and must not ship without executing the runner. **MEASURED AND REJECTED 2026-07-30 — do not retry as specified.** Implemented and benchmarked end to end: `/cache` symlinked to a directory outside the run root (so the runner's always-delete cleanup contract stays untouched — `rmSync` removes the symlink, not the target; proven directly). Cold compile 97s, warm 63s: **34s saved for a 804 MB cache**. That does not pay. Worse, a per-SHA key writes a fresh multi-hundred-MB entry per commit against a 10 GB repo-wide budget with LRU eviction, which would evict the Playwright browser caches that save considerably more. The symlink trick is sound and reusable if the cache ever shrinks; the arithmetic is what fails. **Stop:** do not key any large cache on `github.sha`. | `scripts/run-playwright.mjs`; `docs/testing.md`; session 2026-07-30 | 2026-07-30 | | #137 | P3 | rec | Advisory UI spends ~3 min per UI PR on five mockup tests | **Outcome:** the advisory lane costs what its signal is worth. **Detail:** `ui-advisory` runs on every UI PR (3m14 measured 2026-07-30) to cover `@quarantine` plus `@mockup` journeys — but `tests/flake-ledger.json` is empty and there are **zero** `@quarantine` tests in the suite, so it executes 5 `@mockup` tests. It is `continue-on-error` and outside `pr-required`, so it can also rot unnoticed. **Next:** gate it on mockup-file scope, or accept the cost as the price of keeping the lane warm for future quarantines. Either is defensible; the current state is just unmeasured. **DONE 2026-07-30:** `advisory_ui_changed` gates the lane on a mockup surface having changed or the flake ledger being non-empty. Reading the ledger rather than hard-coding "no quarantines exist" makes it self-correcting — quarantining a test brings the lane straight back. Fails OPEN on an unreadable ledger. Five self-test cases cover both directions plus the fail-open path. | `.github/workflows/ci.yml` `ui-advisory`; `tests/flake-ledger.json`; session 2026-07-30 | 2026-07-30 | From 77b7aaa7e854b64fe6dc3d500ce8e62c3268efc2 Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Fri, 31 Jul 2026 02:26:40 +0800 Subject: [PATCH 14/15] docs: record reconciled PR #1458 review --- docs/branch-review-ledger.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md index 13e4b1469f..54c8d8fca1 100644 --- a/docs/branch-review-ledger.md +++ b/docs/branch-review-ledger.md @@ -254,3 +254,4 @@ Records before 2026-07-28 were written by hand and had drifted: 146 lines carrie | 2026-07-30 | PR #1480 | 6c1e76f53aee87be8408cebc295744fbdce05367 | PR #1480 bounded outstanding reliability fixes | Fixed both review findings: documented the dark accent role and added partial favourites retry without hiding valid counts; no other actionable defects found. | focused Vitest 119 passed; docs index; issue and ledger guards; Actions and Codex workflow guards; Prettier; diff check; typecheck coordinator-blocked | | 2026-07-30 | PR-1469 | 02108d5424f8a3ab50f45808a6cc3cbd872e7555 | PR #1469 component state matrix coverage | PASS after current-main sync; tests execute enabled and disabled popup transitions plus document search loading, empty, and fault states | focused Vitest 2 files, 10 tests passed; outstanding-issues and branch-review-ledger guards passed; no unresolved review threads | | 2026-07-30 | codex/close-pr1480-issues | bf8ac88b024642eb45d1fead86f4ee30fce3f98d | archive PR 1480 issue resolutions | approved: five resolved rows moved intact to archive | check:outstanding-issues; prettier check; diff check | +| 2026-07-30 | PR-1458 | 8c1975b178c67e4c54acffc395d85e38c43d39f5 | PR #1458 superseded root-gate reconciliation | PASS: retained only unique documentation corrections after PR #1480 landed the stronger tracked-root gate; archived resolved shared-hook issue #143 | docs index and links passed; outstanding-issues and branch-review-ledger guards passed; diff check passed | From 398660144d93aeefc2e5649c156948a68925cb64 Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Fri, 31 Jul 2026 02:52:33 +0800 Subject: [PATCH 15/15] docs: format archived issue record --- docs/outstanding-issues.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/outstanding-issues.md b/docs/outstanding-issues.md index 39ec4b6bb5..f60009838e 100644 --- a/docs/outstanding-issues.md +++ b/docs/outstanding-issues.md @@ -166,14 +166,14 @@ Move resolved rows here with the resolution date and a one-line outcome. Keep th | ---- | ----- | --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | | #127 | issue | Document-route phone header intermittently failed to hide | Resolved 2026-07-30 by PR #1427, which fixed the short/clamped drag mechanism. Its runway polling and delivered-travel assertions then passed across the four recorded post-fix runs and the later PR #1480 exact-head browser/PWA document-header journeys, with no recurrence. | 2026-07-30 | -| ID | Type | Summary | Outcome | Resolved | -| ---- | ----- | ------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | +| ID | Type | Summary | Outcome | Resolved | +| ---- | ----- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- | | #143 | issue | Shared pre-commit hook could abort commits in linked worktrees | Resolved by PR #1442. `.githooks/pre-commit` and `scripts/update-docs-inventory.mjs` are tracked on `main`; the installed shared hook now fails open when a committing worktree lacks the inventory script, so the mitigation is durable in fresh clones and linked worktrees. | 2026-07-30 | -| #091 | issue | Results band could not express a partial-source failure | Resolved by PR #1480. Favourites and shared result bands now retain only the honest loaded count, visibly report unavailable sources, and expose a tested Retry recovery path without masking partial failures as ready. | 2026-07-30 | -| #128 | issue | Draft-to-ready alone did not retrigger required CI | Resolved by PR #1480. The CI pull-request trigger now includes ready_for_review alongside opened, synchronize, and reopened, with the workflow contract and exact-head Actions runs passing. | 2026-07-30 | -| #134 | issue | Ledger merge driver could be absent when install was skipped | Resolved by PR #1480. The branch-review-ledger guard now fails loudly when merge=ledger is declared but merge.ledger.driver is not configured, and its self-test covers the missing-driver case. | 2026-07-30 | -| #141 | issue | Production --clinical-accent-strong token was undefined | Resolved by PR #1480. The token is defined for light, dark, and forced-colors themes, documented in the permanent colour direction, and protected by focused design-token tests. | 2026-07-30 | -| #144 | issue | check:docs-index lacked repository-root directory coverage | Resolved by PR #1480. The checker now discovers tracked top-level directories, applies an explicit infrastructure/output allowlist, verifies both orientation maps, and reports all 49 covered roots/modules/routes plus schema tables. | 2026-07-30 | +| #091 | issue | Results band could not express a partial-source failure | Resolved by PR #1480. Favourites and shared result bands now retain only the honest loaded count, visibly report unavailable sources, and expose a tested Retry recovery path without masking partial failures as ready. | 2026-07-30 | +| #128 | issue | Draft-to-ready alone did not retrigger required CI | Resolved by PR #1480. The CI pull-request trigger now includes ready_for_review alongside opened, synchronize, and reopened, with the workflow contract and exact-head Actions runs passing. | 2026-07-30 | +| #134 | issue | Ledger merge driver could be absent when install was skipped | Resolved by PR #1480. The branch-review-ledger guard now fails loudly when merge=ledger is declared but merge.ledger.driver is not configured, and its self-test covers the missing-driver case. | 2026-07-30 | +| #141 | issue | Production --clinical-accent-strong token was undefined | Resolved by PR #1480. The token is defined for light, dark, and forced-colors themes, documented in the permanent colour direction, and protected by focused design-token tests. | 2026-07-30 | +| #144 | issue | check:docs-index lacked repository-root directory coverage | Resolved by PR #1480. The checker now discovers tracked top-level directories, applies an explicit infrastructure/output allowlist, verifies both orientation maps, and reports all 49 covered roots/modules/routes plus schema tables. | 2026-07-30 | | ID | Type | Summary | Outcome | Resolved | | ---- | ----- | ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |