From f159844f1c5e8cf22871479a58f0deea00691a81 Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Wed, 2 Sep 2026 00:24:19 +0800 Subject: [PATCH 1/3] Add governed clinical Sources catalogue (rebased onto main) --- data/repo-awareness-snapshot.json | 1347 ++++++++--------- docs/codebase-index.md | 19 +- docs/design-system/ADOPTION.md | 8 +- docs/design-system/adoption-contract.json | 9 +- docs/design-system/adoption-manifest.json | 77 +- docs/scripts-index.md | 2 +- docs/site-map.md | 44 +- .../plans/2026-09-01-sources-mode.md | 1032 +++++++++++++ .../specs/2026-09-01-sources-mode-design.md | 204 +++ package.json | 1 + playwright.config.ts | 4 +- scripts/check-source-catalogue.ts | 56 + scripts/generate-site-map.ts | 14 +- scripts/playwright-pr-shards.mjs | 4 +- .../(search-app)/dictionary/sources/page.tsx | 24 +- .../(search-app)/sources/[sourceId]/page.tsx | 13 + src/app/(search-app)/sources/loading.tsx | 5 + src/app/(search-app)/sources/method/page.tsx | 12 + src/app/(search-app)/sources/page.tsx | 12 + .../(search-app)/sources/publishers/page.tsx | 12 + src/app/(search-app)/sources/topics/page.tsx | 12 + .../clinical-dashboard/ClinicalSidebar.tsx | 1 + .../clinical-dashboard/use-sidebar-pins.ts | 1 + src/components/mode-nav/registry-mode-nav.tsx | 7 + .../sources/sources-catalogue-client.tsx | 431 ++++++ src/components/sources/sources-pages.tsx | 450 ++++++ src/lib/app-modes.ts | 25 + src/lib/category-identity-icons.ts | 2 + src/lib/category-identity.ts | 4 + src/lib/information-pages.ts | 5 +- src/lib/mode-secondary-navigation.ts | 25 + src/lib/search-command-surface.ts | 10 + src/lib/search-route-ownership.ts | 11 +- src/lib/search-shell-props.ts | 10 + src/lib/sources/catalogue-core.ts | 482 ++++++ src/lib/sources/catalogue-types.ts | 136 ++ src/lib/sources/catalogue-view.ts | 172 +++ src/lib/sources/document-source-loader.ts | 108 ++ src/lib/sources/load-source-catalogue.ts | 19 + src/lib/sources/repository-providers.ts | 638 ++++++++ src/lib/sources/source-date-policy.ts | 10 + src/lib/sources/source-url-policy.ts | 83 + src/lib/tools-catalog.ts | 17 + src/lib/ui-copy.ts | 5 + src/lib/universal-search-mode-context.ts | 1 + tests/app-modes.test.ts | 21 + tests/category-identity.test.ts | 8 + tests/design-system-adoption.test.ts | 4 +- tests/mode-home-loading-contract.test.ts | 1 + tests/mode-secondary-navigation.test.ts | 52 +- tests/route-reachability.test.ts | 18 + tests/search-route-ownership.test.ts | 17 +- tests/search-shell-props.test.ts | 9 + tests/shared-home-empty-state.dom.test.tsx | 6 + tests/sidebar-pins.test.ts | 13 +- tests/sidebar-production.dom.test.tsx | 1 + tests/site-map.test.ts | 14 + tests/source-catalogue-core.test.ts | 577 +++++++ tests/source-catalogue-providers.test.ts | 313 ++++ tests/source-document-loader.test.ts | 212 +++ tests/source-url-policy.test.ts | 37 + tests/sources-mode.dom.test.tsx | 314 ++++ tests/tools-catalog.test.ts | 11 + tests/ui-copy.test.ts | 15 +- tests/ui-dictionary.spec.ts | 1 - tests/ui-mode-nav-density.spec.ts | 1 + tests/ui-sources.spec.ts | 69 + 67 files changed, 6536 insertions(+), 742 deletions(-) create mode 100644 docs/superpowers/plans/2026-09-01-sources-mode.md create mode 100644 docs/superpowers/specs/2026-09-01-sources-mode-design.md create mode 100644 scripts/check-source-catalogue.ts create mode 100644 src/app/(search-app)/sources/[sourceId]/page.tsx create mode 100644 src/app/(search-app)/sources/loading.tsx create mode 100644 src/app/(search-app)/sources/method/page.tsx create mode 100644 src/app/(search-app)/sources/page.tsx create mode 100644 src/app/(search-app)/sources/publishers/page.tsx create mode 100644 src/app/(search-app)/sources/topics/page.tsx create mode 100644 src/components/sources/sources-catalogue-client.tsx create mode 100644 src/components/sources/sources-pages.tsx create mode 100644 src/lib/sources/catalogue-core.ts create mode 100644 src/lib/sources/catalogue-types.ts create mode 100644 src/lib/sources/catalogue-view.ts create mode 100644 src/lib/sources/document-source-loader.ts create mode 100644 src/lib/sources/load-source-catalogue.ts create mode 100644 src/lib/sources/repository-providers.ts create mode 100644 src/lib/sources/source-date-policy.ts create mode 100644 src/lib/sources/source-url-policy.ts create mode 100644 tests/source-catalogue-core.test.ts create mode 100644 tests/source-catalogue-providers.test.ts create mode 100644 tests/source-document-loader.test.ts create mode 100644 tests/source-url-policy.test.ts create mode 100644 tests/sources-mode.dom.test.tsx create mode 100644 tests/ui-sources.spec.ts diff --git a/data/repo-awareness-snapshot.json b/data/repo-awareness-snapshot.json index 1bbcc71753..49d03e7ede 100644 --- a/data/repo-awareness-snapshot.json +++ b/data/repo-awareness-snapshot.json @@ -1,8 +1,8 @@ { "version": "repo-awareness-snapshot-v1", "captured_revision": { - "sha": "a4d600782727ffbd4fc0e899a3c502c5a668bf5e", - "committed_at": "2026-09-01T23:34:27+08:00" + "sha": "075ff1f962cc7e4e39fece581cab4416cc33f3ce", + "committed_at": "2026-09-01T15:33:13Z" }, "routes": { "modes": [ @@ -78,6 +78,12 @@ "home": "/?mode=services", "dev_only": false }, + { + "id": "sources", + "label": "Sources", + "home": "/sources", + "dev_only": false + }, { "id": "specifiers", "label": "Specifiers", @@ -173,11 +179,6 @@ "file": "src/app/(search-app)/dictionary/search/page.tsx", "area": "product" }, - { - "path": "/dictionary/sources", - "file": "src/app/(search-app)/dictionary/sources/page.tsx", - "area": "product" - }, { "path": "/dictionary/topics", "file": "src/app/(search-app)/dictionary/topics/page.tsx", @@ -1028,6 +1029,31 @@ "file": "src/app/(search-app)/services/search/page.tsx", "area": "product" }, + { + "path": "/sources", + "file": "src/app/(search-app)/sources/page.tsx", + "area": "product" + }, + { + "path": "/sources/[sourceId]", + "file": "src/app/(search-app)/sources/[sourceId]/page.tsx", + "area": "product" + }, + { + "path": "/sources/method", + "file": "src/app/(search-app)/sources/method/page.tsx", + "area": "product" + }, + { + "path": "/sources/publishers", + "file": "src/app/(search-app)/sources/publishers/page.tsx", + "area": "product" + }, + { + "path": "/sources/topics", + "file": "src/app/(search-app)/sources/topics/page.tsx", + "area": "product" + }, { "path": "/specifiers/[slug]", "file": "src/app/(search-app)/specifiers/[slug]/page.tsx", @@ -1120,6 +1146,11 @@ "file": "src/app/(search-app)/dictionary/browse/page.tsx", "target": "/dictionary/search" }, + { + "path": "/dictionary/sources", + "file": "src/app/(search-app)/dictionary/sources/page.tsx", + "target": "/sources?usedBy=dictionary" + }, { "path": "/differentials", "file": "src/app/(search-app)/differentials/page.tsx", @@ -1429,16 +1460,21 @@ } ], "counts": { - "modes": 15, - "pages": 200, - "product_pages": 63, + "modes": 16, + "pages": 204, + "product_pages": 67, "mockup_pages": 137, - "redirects": 17, + "redirects": 18, "api": 60 } }, "documentation": { "documents": [ + { + "path": "docs/README.md", + "section": "root", + "catalogued": false + }, { "path": "docs/adr/0001-use-a-shared-local-first-clinical-ask-orchestrator.md", "section": "adr", @@ -1504,6 +1540,16 @@ "section": "archive", "catalogued": false }, + { + "path": "docs/archive/COLOR_REDESIGN_PLAN.md", + "section": "archive", + "catalogued": false + }, + { + "path": "docs/archive/TOOLS_CONTEXT_FOR_NEW_CHAT.md", + "section": "archive", + "catalogued": false + }, { "path": "docs/archive/branch-cleanup-2026-06-28.md", "section": "archive", @@ -1539,11 +1585,6 @@ "section": "archive", "catalogued": false }, - { - "path": "docs/archive/COLOR_REDESIGN_PLAN.md", - "section": "archive", - "catalogued": false - }, { "path": "docs/archive/design-qa-2026-07-15.md", "section": "archive", @@ -1649,11 +1690,6 @@ "section": "archive", "catalogued": true }, - { - "path": "docs/archive/TOOLS_CONTEXT_FOR_NEW_CHAT.md", - "section": "archive", - "catalogued": false - }, { "path": "docs/audit/2026-07-20-repository-maturity.md", "section": "audit", @@ -1775,37 +1811,37 @@ "catalogued": false }, { - "path": "docs/care-plan/accessibility-acceptance.md", + "path": "docs/care-plan/CLAUDE-START-HERE.md", "section": "care-plan", "catalogued": false }, { - "path": "docs/care-plan/claude-build-handover-2026-08-21.md", + "path": "docs/care-plan/HANDOFF-START-HERE.md", "section": "care-plan", "catalogued": false }, { - "path": "docs/care-plan/CLAUDE-START-HERE.md", + "path": "docs/care-plan/accessibility-acceptance.md", "section": "care-plan", "catalogued": false }, { - "path": "docs/care-plan/clinical-language-trace.md", + "path": "docs/care-plan/claude-build-handover-2026-08-21.md", "section": "care-plan", "catalogued": false }, { - "path": "docs/care-plan/complete-work-ledger.md", + "path": "docs/care-plan/clinical-language-trace.md", "section": "care-plan", "catalogued": false }, { - "path": "docs/care-plan/conversation-transcript-2026-08-21.md", + "path": "docs/care-plan/complete-work-ledger.md", "section": "care-plan", "catalogued": false }, { - "path": "docs/care-plan/HANDOFF-START-HERE.md", + "path": "docs/care-plan/conversation-transcript-2026-08-21.md", "section": "care-plan", "catalogued": false }, @@ -1934,6 +1970,11 @@ "section": "care-plan", "catalogued": false }, + { + "path": "docs/caring-contacts/PROGRESS-LEDGER.md", + "section": "caring-contacts", + "catalogued": false + }, { "path": "docs/caring-contacts/accessibility-acceptance.md", "section": "caring-contacts", @@ -2195,17 +2236,17 @@ "catalogued": false }, { - "path": "docs/caring-contacts/phase-2b-build-record.md", + "path": "docs/caring-contacts/phase-2b-CONTINUATION-PROMPT.md", "section": "caring-contacts", "catalogued": false }, { - "path": "docs/caring-contacts/phase-2b-CONTINUATION-PROMPT.md", + "path": "docs/caring-contacts/phase-2b-HANDOVER.md", "section": "caring-contacts", "catalogued": false }, { - "path": "docs/caring-contacts/phase-2b-HANDOVER.md", + "path": "docs/caring-contacts/phase-2b-build-record.md", "section": "caring-contacts", "catalogued": false }, @@ -2214,6 +2255,11 @@ "section": "caring-contacts", "catalogued": false }, + { + "path": "docs/caring-contacts/phase-2b-sdd-archive/STANDING-DISCIPLINE.md", + "section": "caring-contacts", + "catalogued": false + }, { "path": "docs/caring-contacts/phase-2b-sdd-archive/group-4-review.md", "section": "caring-contacts", @@ -2239,11 +2285,6 @@ "section": "caring-contacts", "catalogued": false }, - { - "path": "docs/caring-contacts/phase-2b-sdd-archive/STANDING-DISCIPLINE.md", - "section": "caring-contacts", - "catalogued": false - }, { "path": "docs/caring-contacts/phase-2b-sdd-archive/task-1-brief.md", "section": "caring-contacts", @@ -2549,11 +2590,6 @@ "section": "caring-contacts", "catalogued": false }, - { - "path": "docs/caring-contacts/PROGRESS-LEDGER.md", - "section": "caring-contacts", - "catalogued": false - }, { "path": "docs/caring-contacts/task-seed-timeline-report.md", "section": "caring-contacts", @@ -2764,6 +2800,11 @@ "section": "design-system", "catalogued": true }, + { + "path": "docs/design-system/TOKENS.md", + "section": "design-system", + "catalogued": true + }, { "path": "docs/design-system/sweep-2026-08-29-structure.md", "section": "design-system", @@ -2804,11 +2845,6 @@ "section": "design-system", "catalogued": false }, - { - "path": "docs/design-system/TOKENS.md", - "section": "design-system", - "catalogued": true - }, { "path": "docs/development-speed-playbook.md", "section": "root", @@ -3125,12 +3161,12 @@ "catalogued": true }, { - "path": "docs/rag-behaviour/behaviour-map.md", + "path": "docs/rag-behaviour/README.md", "section": "rag-behaviour", "catalogued": false }, { - "path": "docs/rag-behaviour/README.md", + "path": "docs/rag-behaviour/behaviour-map.md", "section": "rag-behaviour", "catalogued": false }, @@ -3160,50 +3196,45 @@ "catalogued": true }, { - "path": "docs/rag-improvement/baseline-record.md", + "path": "docs/rag-improvement/COORDINATION.md", "section": "rag-improvement", "catalogued": true }, { - "path": "docs/rag-improvement/COORDINATION.md", + "path": "docs/rag-improvement/HANDOVER.md", "section": "rag-improvement", "catalogued": true }, { - "path": "docs/rag-improvement/data-flow-register.md", + "path": "docs/rag-improvement/README.md", "section": "rag-improvement", "catalogued": true }, { - "path": "docs/rag-improvement/gate-b-decision-record-2026-08-18.md", + "path": "docs/rag-improvement/baseline-record.md", "section": "rag-improvement", - "catalogued": false + "catalogued": true }, { - "path": "docs/rag-improvement/gate-b-decision-record.md", + "path": "docs/rag-improvement/data-flow-register.md", "section": "rag-improvement", - "catalogued": false + "catalogued": true }, { - "path": "docs/rag-improvement/HANDOVER.md", + "path": "docs/rag-improvement/gate-b-decision-record-2026-08-18.md", "section": "rag-improvement", - "catalogued": true + "catalogued": false }, { - "path": "docs/rag-improvement/README.md", + "path": "docs/rag-improvement/gate-b-decision-record.md", "section": "rag-improvement", - "catalogued": true + "catalogued": false }, { "path": "docs/rag-injection-threat-model.md", "section": "root", "catalogued": true }, - { - "path": "docs/README.md", - "section": "root", - "catalogued": false - }, { "path": "docs/reconciliation-playbook.md", "section": "root", @@ -3585,47 +3616,57 @@ "catalogued": false }, { - "path": "docs/superpowers/plans/2026-09-01-native-smart-catalogue-search.md", + "path": "docs/superpowers/plans/2026-09-01-services-safety-provenance.md", "section": "superpowers", "catalogued": false }, { - "path": "docs/superpowers/plans/2026-09-01-services-safety-provenance.md", + "path": "docs/superpowers/plans/2026-09-01-sources-mode.md", "section": "superpowers", "catalogued": false }, { - "path": "docs/superpowers/rag-upgrade/canonical/approval-matrix.md", + "path": "docs/superpowers/rag-upgrade/CLOUD-EXECUTION-PROMPT.md", "section": "superpowers", "catalogued": false }, { - "path": "docs/superpowers/rag-upgrade/canonical/connected-execution.md", + "path": "docs/superpowers/rag-upgrade/LOCAL-CONNECTED-EXECUTION-PROMPT.md", "section": "superpowers", "catalogued": false }, { - "path": "docs/superpowers/rag-upgrade/canonical/execution-order.md", + "path": "docs/superpowers/rag-upgrade/canonical/START-HERE.cloud.md", "section": "superpowers", "catalogued": false }, { - "path": "docs/superpowers/rag-upgrade/canonical/sdd-execution.md", + "path": "docs/superpowers/rag-upgrade/canonical/START-HERE.local.md", "section": "superpowers", "catalogued": false }, { - "path": "docs/superpowers/rag-upgrade/canonical/START-HERE.cloud.md", + "path": "docs/superpowers/rag-upgrade/canonical/approval-matrix.md", "section": "superpowers", "catalogued": false }, { - "path": "docs/superpowers/rag-upgrade/canonical/START-HERE.local.md", + "path": "docs/superpowers/rag-upgrade/canonical/connected-execution.md", "section": "superpowers", "catalogued": false }, { - "path": "docs/superpowers/rag-upgrade/CLOUD-EXECUTION-PROMPT.md", + "path": "docs/superpowers/rag-upgrade/canonical/execution-order.md", + "section": "superpowers", + "catalogued": false + }, + { + "path": "docs/superpowers/rag-upgrade/canonical/sdd-execution.md", + "section": "superpowers", + "catalogued": false + }, + { + "path": "docs/superpowers/rag-upgrade/cloud/START-HERE.md", "section": "superpowers", "catalogued": false }, @@ -3699,11 +3740,6 @@ "section": "superpowers", "catalogued": false }, - { - "path": "docs/superpowers/rag-upgrade/cloud/START-HERE.md", - "section": "superpowers", - "catalogued": false - }, { "path": "docs/superpowers/rag-upgrade/execution-artifacts/rag-answer-quality-and-repository-coverage-v1/README.md", "section": "superpowers", @@ -3715,7 +3751,7 @@ "catalogued": false }, { - "path": "docs/superpowers/rag-upgrade/LOCAL-CONNECTED-EXECUTION-PROMPT.md", + "path": "docs/superpowers/rag-upgrade/local/START-HERE.md", "section": "superpowers", "catalogued": false }, @@ -3789,11 +3825,6 @@ "section": "superpowers", "catalogued": false }, - { - "path": "docs/superpowers/rag-upgrade/local/START-HERE.md", - "section": "superpowers", - "catalogued": false - }, { "path": "docs/superpowers/specs/2026-07-02-triage-security-reliability-design.md", "section": "superpowers", @@ -3885,12 +3916,12 @@ "catalogued": false }, { - "path": "docs/superpowers/specs/2026-09-01-native-smart-catalogue-search-design.md", + "path": "docs/superpowers/specs/2026-09-01-services-safety-provenance-design.md", "section": "superpowers", "catalogued": false }, { - "path": "docs/superpowers/specs/2026-09-01-services-safety-provenance-design.md", + "path": "docs/superpowers/specs/2026-09-01-sources-mode-design.md", "section": "superpowers", "catalogued": false }, @@ -3944,6 +3975,11 @@ "section": "root", "catalogued": false }, + { + "path": "docs/ward-flow-phase-3-workspace/README.md", + "section": "ward-flow-phase-3-workspace", + "catalogued": false + }, { "path": "docs/ward-flow-phase-3-workspace/clinical-changes-report.md", "section": "ward-flow-phase-3-workspace", @@ -3979,11 +4015,6 @@ "section": "ward-flow-phase-3-workspace", "catalogued": false }, - { - "path": "docs/ward-flow-phase-3-workspace/README.md", - "section": "ward-flow-phase-3-workspace", - "catalogued": false - }, { "path": "docs/ward-flow-phase-3-workspace/task-1-brief.md", "section": "ward-flow-phase-3-workspace", @@ -4341,14 +4372,6 @@ }, "review_state": { "records": [ - { - "date": "2026-09-01", - "ref": "codex/smart-local-modes-20260901 (PR #2508)", - "head": "a1e1b973599e9bb301360be90c051986c172670f", - "scope": "PR #2508 native Smart catalogue matching", - "outcome": "Fixed P1 Compare result-order regression; no additional P0-P3 findings.", - "checks": "Focused Vitest 10/10; npm run format; full suite stopped before provider-backed path." - }, { "date": "2026-09-01", "ref": "PR-2504", @@ -4357,30 +4380,6 @@ "outcome": "Replaced inaccessible authenticated-table reads with an independently administrator-gated service-role boundary that filters every query to the verified owner; restored the complete implementation after an intervening placeholder-only commit.", "checks": "Focused developer corpus-health test: 16 passed; explicit owner-filter and non-administrator coverage; diff check." }, - { - "date": "2026-09-01", - "ref": "PR-2504", - "head": "3b1dc7c8bc997a4ea4bac44dc7de01632e676e63", - "scope": "Resolve Codex P1: corpus-health table access", - "outcome": "Verified the authenticated role lacks table SELECT; the administrator-gated server-only service-role path scopes every documents and document_index_quality query to the verified owner, with current access-control documentation.", - "checks": "Focused corpus-health suite: 18 passed; Prettier check passed; schema grants verified; independent review found no runtime access-control defect." - }, - { - "date": "2026-09-01", - "ref": "PR-2507", - "head": "ebb57785958888c2703ccb6cadac76ce344065ee", - "scope": "Run PR sweep: enforce Favourites phone tap-target minimum", - "outcome": "Replaced the blacklist-only target guard with a positive 48px-or-row-wide requirement and mutation fixtures for undersized or implicit controls.", - "checks": "Focused Favourites phone mockup test: 9 passed; diff check." - }, - { - "date": "2026-09-01", - "ref": "PR-2508", - "head": "14a99d0c412a3c53bf92b684c5b7e5b57ca1ccd9", - "scope": "Run PR sweep: prioritise embedded catalogue identities", - "outcome": "Ranked named Factsheet titles or brands and Dictionary terms or abbreviations above related Smart expansion matches in natural-language queries.", - "checks": "Focused Factsheets and Dictionary tests: 35 passed; direct-identity regression coverage; diff check." - }, { "date": "2026-08-31", "ref": "codex/answer-surface-compact-20260830", @@ -4410,7 +4409,7 @@ "ref": "gemini/pr-group-3-ui-a11y-caring-contacts-ward-flow (PR #2479)", "head": "8ff3f26c6e4f5302c1883f940f4cc1b22fbeec5c", "scope": "Run PR sweep: existing unresolved review threads", - "outcome": "0 → 2 threads resolved: useful-actions disclosure semantics, workspace route registration assertion", + "outcome": "0 \u2192 2 threads resolved: useful-actions disclosure semantics, workspace route registration assertion", "checks": "Focused Vitest 18/18; typecheck passed; no provider-backed checks run" }, { @@ -4482,7 +4481,7 @@ "ref": "codex/dsm-search-ux-elevation (PR #2415)", "head": "958a6b4f7c969f07cb118ccc0c581939fd81bcab", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Before: mergeable_state dirty again (main advanced one more commit, #2416, past the prior sweep's merge, re-conflicting the generated repo-awareness snapshot); required CI red on the prior head (5b22edb2) with Production UI (1) failing tests/ui-route-coverage.spec.ts 'DSM home renders responsively and opens comparison' (expected /dsm/compare$ but got /dsm/compare?q=major+depressive, because the prior sweep's merge silently dropped a same-PR fix commit's dropped $ anchor while keeping its other hunks) and PR mergeability failing on the dirty state; 0 unresolved review threads (6 PR comments were all bot rate-limit/housekeeping noise: Codex usage limit, CodeRabbit review limit, Cursor Bugbot limit x2, Supabase preview skip, CI-triage bot). After: merged origin/main resolving the sole conflict (data/repo-awareness-snapshot.json, a generated file) by regenerating via npm run snapshot:repo-awareness rather than hand-editing; separately fixed the real route-coverage regression by dropping the stale $ anchor on the /dsm/compare URL assertion (restoring intended behaviour: Compare now carries q/ids from DSM search, matching this PR's own preserve-filters design) — both included in merge commit 958a6b4f. No review threads needed action (still zero unresolved). Pushed 958a6b4f; new CI run 33062342217 kicked off on the synced head and was still in progress at time of recording; left for a human or later session to confirm green.", + "outcome": "Before: mergeable_state dirty again (main advanced one more commit, #2416, past the prior sweep's merge, re-conflicting the generated repo-awareness snapshot); required CI red on the prior head (5b22edb2) with Production UI (1) failing tests/ui-route-coverage.spec.ts 'DSM home renders responsively and opens comparison' (expected /dsm/compare$ but got /dsm/compare?q=major+depressive, because the prior sweep's merge silently dropped a same-PR fix commit's dropped $ anchor while keeping its other hunks) and PR mergeability failing on the dirty state; 0 unresolved review threads (6 PR comments were all bot rate-limit/housekeeping noise: Codex usage limit, CodeRabbit review limit, Cursor Bugbot limit x2, Supabase preview skip, CI-triage bot). After: merged origin/main resolving the sole conflict (data/repo-awareness-snapshot.json, a generated file) by regenerating via npm run snapshot:repo-awareness rather than hand-editing; separately fixed the real route-coverage regression by dropping the stale $ anchor on the /dsm/compare URL assertion (restoring intended behaviour: Compare now carries q/ids from DSM search, matching this PR's own preserve-filters design) \u2014 both included in merge commit 958a6b4f. No review threads needed action (still zero unresolved). Pushed 958a6b4f; new CI run 33062342217 kicked off on the synced head and was still in progress at time of recording; left for a human or later session to confirm green.", "checks": "npm run lint (clean, gate-receipts recorded pass), npm run typecheck (clean, gate-receipts recorded pass), npm run test -- tests/mode-secondary-navigation.test.ts tests/dsm-compare-chrome.dom.test.tsx tests/dsm-search-empty-state.dom.test.tsx tests/app-modes.test.ts tests/dsm-comparison-page.dom.test.tsx (68 passed, gate-receipts recorded pass). git merge-tree confirmed the only conflict was the generated snapshot file before merging. No provider-backed checks run; hosted CI run 33062342217 in progress as of last observation." }, { @@ -4498,7 +4497,7 @@ "ref": "codex/therapy-compare-phone-ux (PR #2410)", "head": "4042bdd7af523746d4c9b7a9c6a732e36c886b7d", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Before: mergeable_state dirty (real conflict in src/components/dsm/dsm-compare-chrome.tsx vs main's #2409 DSM redesign), CI red (Build/Static PR checks/Production UI x4/Lighthouse all failing on one root-cause TS2783 duplicate-prop typecheck error in the PR's own new test), 0 unresolved review threads (all 5 PR comments were bot noise: Codex/CodeRabbit/Bugbot usage-limit notices and a CI-triage bot comment). After: merged origin/main cleanly (dsm-compare-chrome.tsx conflict resolved by combining HEAD's phoneLayout/slotSummaryLabel props with main's onCommit, verified equivalent since idsCompareHref already null-filters internally), fixed the duplicate actionLabel JSX prop in tests/compare-ids-chrome.dom.test.tsx (removed the redundant explicit prop since chromeProps spread already supplies it and the test asserts nothing about its value), pushed 2 commits (13efa061 merge, 4042bdd7 fix). No review threads needed action. New CI run (33051244071) at 4042bdd7 still in_progress after 30+ min observation window (PR mergeability + PR policy + Safety and config checks + Caring Contacts database already green); Build/Static PR checks/Unit coverage/Production UI x3/Production UI critical/Lighthouse budget not yet settled — deferred to the user per babysit budget, run: https://github.com/BigSimmo/Database/actions/runs/33051244071", + "outcome": "Before: mergeable_state dirty (real conflict in src/components/dsm/dsm-compare-chrome.tsx vs main's #2409 DSM redesign), CI red (Build/Static PR checks/Production UI x4/Lighthouse all failing on one root-cause TS2783 duplicate-prop typecheck error in the PR's own new test), 0 unresolved review threads (all 5 PR comments were bot noise: Codex/CodeRabbit/Bugbot usage-limit notices and a CI-triage bot comment). After: merged origin/main cleanly (dsm-compare-chrome.tsx conflict resolved by combining HEAD's phoneLayout/slotSummaryLabel props with main's onCommit, verified equivalent since idsCompareHref already null-filters internally), fixed the duplicate actionLabel JSX prop in tests/compare-ids-chrome.dom.test.tsx (removed the redundant explicit prop since chromeProps spread already supplies it and the test asserts nothing about its value), pushed 2 commits (13efa061 merge, 4042bdd7 fix). No review threads needed action. New CI run (33051244071) at 4042bdd7 still in_progress after 30+ min observation window (PR mergeability + PR policy + Safety and config checks + Caring Contacts database already green); Build/Static PR checks/Unit coverage/Production UI x3/Production UI critical/Lighthouse budget not yet settled \u2014 deferred to the user per babysit budget, run: https://github.com/BigSimmo/Database/actions/runs/33051244071", "checks": "npx vitest run tests/compare-slot-strip.dom.test.tsx tests/compare-ids-chrome.dom.test.tsx tests/therapy-compare-phone-layout.dom.test.tsx tests/therapy-compare-tray.dom.test.tsx tests/phone-dock-addon-contract.test.ts tests/dsm-comparison-page.dom.test.tsx -- 6 files / 53 passed; npm run typecheck -- passed after fix (5604 input files); npx eslint on touched files -- clean; no provider-backed checks run" }, { @@ -4506,15 +4505,15 @@ "ref": "codex/therapy-compare-phone-ux (PR #2410)", "head": "4af5895f48cca785333272ece41e25bcaccb7441", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Static PR checks failing (check:repo-awareness-snapshot: committed snapshot behind — review_state differs) -> merged origin/main@603da96 (clean, no conflicts) then regenerated snapshot via npm run snapshot:repo-awareness and committed; 0 unresolved review threads found (none to fix/reply/resolve). Local full gate now green. Note: main advanced again mid-sweep to be65b8a1b (PR #2415, same DSM/compare files) producing a real post-push content conflict — left unresolved for the user, not auto-resolved.", - "checks": "npm run verify:cheap equivalent set run piecewise: check:repo-awareness-snapshot (fail -> pass after regenerate), full static-pr check chain (34 gates, all pass), npm run lint (pass), npm run typecheck (pass), npm run test (893 files / 10824 tests passed, 4 skipped — two initially-failing tests (clinical-hazard-controls.test.ts, privacy-readiness-contract.test.ts) were a local shallow-clone ancestry artifact, confirmed pre-existing on plain origin/main and resolved by git fetch --deepen, not a code fix). No provider-backed checks run." + "outcome": "Static PR checks failing (check:repo-awareness-snapshot: committed snapshot behind \u2014 review_state differs) -> merged origin/main@603da96 (clean, no conflicts) then regenerated snapshot via npm run snapshot:repo-awareness and committed; 0 unresolved review threads found (none to fix/reply/resolve). Local full gate now green. Note: main advanced again mid-sweep to be65b8a1b (PR #2415, same DSM/compare files) producing a real post-push content conflict \u2014 left unresolved for the user, not auto-resolved.", + "checks": "npm run verify:cheap equivalent set run piecewise: check:repo-awareness-snapshot (fail -> pass after regenerate), full static-pr check chain (34 gates, all pass), npm run lint (pass), npm run typecheck (pass), npm run test (893 files / 10824 tests passed, 4 skipped \u2014 two initially-failing tests (clinical-hazard-controls.test.ts, privacy-readiness-contract.test.ts) were a local shallow-clone ancestry artifact, confirmed pre-existing on plain origin/main and resolved by git fetch --deepen, not a code fix). No provider-backed checks run." }, { "date": "2026-08-27", "ref": "codex/therapy-compare-phone-ux (PR #2410)", "head": "871df2793ccb63ffe92f70225e8be64e25619da7", "scope": "Resolve merge conflict against origin/main (requested follow-up after Run PR sweep)", - "outcome": "Real content conflict in compare-ids-chrome.tsx, compare-slot-strip.tsx, dsm-compare-chrome.tsx, and tests/ui-route-coverage.spec.ts caused by PR #2415 (already merged) independently reworking DsmCompareChrome to a compact horizontal rail + separate starter-chip row, while this PR added a phoneLayout=hybrid pip-summary/2x2-grid design to the same shared CompareIdsChrome/CompareSlotStrip components. Resolved by merging both prop sets into the shared components (showEmptyState/slotLayout from main plus phoneLayout/slotSummaryLabel from this PR, now coexisting) and, for the one screen both PRs redesigned (DSM compare), keeping origin/main's already-shipped compact-rail design rather than overwriting it — so this PR's hybrid layout still lands in full for Therapy compare (untouched by #2415), while DSM compare keeps its most recently reviewed design. Regenerated data/repo-awareness-snapshot.json. Pushed as merge commit 871df2793.", + "outcome": "Real content conflict in compare-ids-chrome.tsx, compare-slot-strip.tsx, dsm-compare-chrome.tsx, and tests/ui-route-coverage.spec.ts caused by PR #2415 (already merged) independently reworking DsmCompareChrome to a compact horizontal rail + separate starter-chip row, while this PR added a phoneLayout=hybrid pip-summary/2x2-grid design to the same shared CompareIdsChrome/CompareSlotStrip components. Resolved by merging both prop sets into the shared components (showEmptyState/slotLayout from main plus phoneLayout/slotSummaryLabel from this PR, now coexisting) and, for the one screen both PRs redesigned (DSM compare), keeping origin/main's already-shipped compact-rail design rather than overwriting it \u2014 so this PR's hybrid layout still lands in full for Therapy compare (untouched by #2415), while DSM compare keeps its most recently reviewed design. Regenerated data/repo-awareness-snapshot.json. Pushed as merge commit 871df2793.", "checks": "npx vitest run tests/compare-slot-strip.dom.test.tsx tests/compare-ids-chrome.dom.test.tsx tests/dsm-compare-chrome.dom.test.tsx tests/therapy-compare-phone-layout.dom.test.tsx tests/therapy-compare-tray.dom.test.tsx tests/phone-dock-addon-contract.test.ts -- 53 passed; npx tsc --noEmit -- clean; npx eslint on the 4 resolved files -- clean; npm run check:repo-awareness-snapshot -- in step; npx prettier --check on the 4 resolved files -- all match. No provider-backed checks run." }, { @@ -4546,7 +4545,7 @@ "ref": "codex/therapy-pathways-redesign (PR #2413)", "head": "be2d9b0291965258e5933006dc9b914961bb0dc3", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "CI was already green pre-sweep (PR required: success on d3f39c4); branch was already current with main (0 behind), so no drift merge needed. Fixed 3 unresolved CodeRabbit review threads: (1) pathway/step 'linked steps' counts used total steps.length instead of counting only steps with a matched therapySlug — added pathwayLinkedStepCount() and wired it into pathway-review-label.ts, pathway-picker-sheet.tsx (x2), pathway-step-stack.tsx; (2) ui-therapy-pathways.spec.ts readCautionGeometry substituted +/-Infinity for a missing caution/dock element, masking a broken overlap assertion — now throws if either is absent; (3) the 'Change pathway' Playwright test only re-clicked the already-active Anxiety pathway row, which could pass with a broken selectPathway — now selects Mood pathway, asserts the URL/heading changed, then switches back to Anxiety before the anxiety-scoped scroll assertions. All 3 threads replied with commit SHA and resolved.", + "outcome": "CI was already green pre-sweep (PR required: success on d3f39c4); branch was already current with main (0 behind), so no drift merge needed. Fixed 3 unresolved CodeRabbit review threads: (1) pathway/step 'linked steps' counts used total steps.length instead of counting only steps with a matched therapySlug \u2014 added pathwayLinkedStepCount() and wired it into pathway-review-label.ts, pathway-picker-sheet.tsx (x2), pathway-step-stack.tsx; (2) ui-therapy-pathways.spec.ts readCautionGeometry substituted +/-Infinity for a missing caution/dock element, masking a broken overlap assertion \u2014 now throws if either is absent; (3) the 'Change pathway' Playwright test only re-clicked the already-active Anxiety pathway row, which could pass with a broken selectPathway \u2014 now selects Mood pathway, asserts the URL/heading changed, then switches back to Anxiety before the anxiety-scoped scroll assertions. All 3 threads replied with commit SHA and resolved.", "checks": "npx vitest run tests/therapy-pathways-mobile.dom.test.tsx tests/therapy-compass-responsive-contract.test.ts tests/playwright-pr-shards.test.ts tests/therapy-compass-pathways.test.ts -- 34 passed; npm run lint -- exit 0 (gate-receipts pass); npm run typecheck -- exit 0, run foreground twice, gate-receipts recorded pass for typecheck:internal (5613 input files); npm run format -- applied (1 file reformatted, amended into commit); no provider-backed checks run" }, { @@ -4562,7 +4561,7 @@ "ref": "codex/therapy-pathways-redesign (PR #2413)", "head": "f8537abbef36b5e9f72eb1c745f565253a276153", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Before: PR required failing (Static PR checks red on check:repo-awareness-snapshot — committed data/repo-awareness-snapshot.json review_state was stale after prior sweep's ledger/docs commits); 0 unresolved review threads; branch already contained origin/main (no drift). After: ran npm run snapshot:repo-awareness to regenerate the snapshot, verified npm run check:repo-awareness-snapshot and npm run format:changed pass, committed and pushed f8537ab. All other required jobs (Build, Unit coverage, Production UI critical, Safety and config checks, Production UI shards 1-3, Lighthouse budget) were already green before this fix and untouched by it. No review threads existed to address. No main-sync needed (branch already up to date).", + "outcome": "Before: PR required failing (Static PR checks red on check:repo-awareness-snapshot \u2014 committed data/repo-awareness-snapshot.json review_state was stale after prior sweep's ledger/docs commits); 0 unresolved review threads; branch already contained origin/main (no drift). After: ran npm run snapshot:repo-awareness to regenerate the snapshot, verified npm run check:repo-awareness-snapshot and npm run format:changed pass, committed and pushed f8537ab. All other required jobs (Build, Unit coverage, Production UI critical, Safety and config checks, Production UI shards 1-3, Lighthouse budget) were already green before this fix and untouched by it. No review threads existed to address. No main-sync needed (branch already up to date).", "checks": "npm run check:repo-awareness-snapshot (PASS, reproduces prior CI failure then passes after regen); npm run format:changed (PASS); npm run snapshot:repo-awareness (regenerated data/repo-awareness-snapshot.json); no provider-backed checks run" }, { @@ -4578,7 +4577,7 @@ "ref": "ds-hazard-1-2-sweep", "head": "19ee085b1cc952e8c40e893fb2fce99538415259", "scope": "design-system", - "outcome": "Findings — 0 P0/P1; 4 structural P2 (disabled-send border jump, hero leading on composer, --leading-prose on chrome, stale conventions.md per-step type scale); residuals on specifier focus ring and leftover Lucide sizes", + "outcome": "Findings \u2014 0 P0/P1; 4 structural P2 (disabled-send border jump, hero leading on composer, --leading-prose on chrome, stale conventions.md per-step type scale); residuals on specifier focus ring and leftover Lucide sizes", "checks": "read-only origin/main...HEAD token/UI/docs inspection; ledger lookup NOT REVIEWED; no contract gate, browser, or providers" }, { @@ -4602,7 +4601,7 @@ "ref": "update_documentation_structure (PR #2444)", "head": "c619671065422373f746f69bca5f94147767f877", "scope": "PR 2444 review: main sync + CI fix + review thread", - "outcome": "before: PR policy/Static PR checks/Unit coverage failing, 1 unresolved review thread, behind main by 2 commits (clean merge). after: merged origin/main (no conflicts), regenerated docs/site-map.md to drop deleted signed-urls alias route (fixes docs:check-links + site-map.test.ts), fixed CodeRabbit Major finding — upload error-path storage_cleanup_jobs ledger now carries document_id when document deletion is not confirmed so the janitor live-document guard can protect it, added required PR-body Clinical Governance Preflight + Risk and rollout sections (fixes PR policy check). Thread resolved with fix commit reference.", + "outcome": "before: PR policy/Static PR checks/Unit coverage failing, 1 unresolved review thread, behind main by 2 commits (clean merge). after: merged origin/main (no conflicts), regenerated docs/site-map.md to drop deleted signed-urls alias route (fixes docs:check-links + site-map.test.ts), fixed CodeRabbit Major finding \u2014 upload error-path storage_cleanup_jobs ledger now carries document_id when document deletion is not confirmed so the janitor live-document guard can protect it, added required PR-body Clinical Governance Preflight + Risk and rollout sections (fixes PR policy check). Thread resolved with fix commit reference.", "checks": "npm run typecheck (clean), npm run lint (clean), npm run test:focused -- --files src/app/api/upload/route.ts (184 passed), npm run docs:check-links (passed), npm run sitemap:check (passed), npm run format (no changes needed). No provider-backed checks run." }, { @@ -4625,8 +4624,8 @@ "date": "2026-08-26", "ref": "claude/ward-flow-phase-5-p8rwcm", "head": "47b51405bf3938096411895d28a4bba351d7d050", - "scope": "Ward Flow Phase 5 — bed availability lifecycle, leave beds, discharge board, capacity bands, freshness", - "outcome": "Whole-branch review: approved with findings, 0 P0, 0 P1, 7 P2 — all seven fixed and mutation-tested. Four earlier automated findings: three fixed, one rejected with reasons.", + "scope": "Ward Flow Phase 5 \u2014 bed availability lifecycle, leave beds, discharge board, capacity bands, freshness", + "outcome": "Whole-branch review: approved with findings, 0 P0, 0 P1, 7 P2 \u2014 all seven fixed and mutation-tested. Four earlier automated findings: three fixed, one rejected with reasons.", "checks": "npm run test (3 pre-existing failures, identical on clean origin/main); npm run typecheck; npm run lint (eslint cache cleared); prettier --check on all changed files; chromium-mockups ward-management + ward-coordinator + ward-discharges; screenshots at 390/820/1440 on five screens, looked at" }, { @@ -4706,7 +4705,7 @@ "ref": "backup/pr-2333-prelinear-20260824", "head": "7c5bb84e45d6925c6950cf5b96fff3a8cc479a7b", "scope": "pr-ci-fix", - "outcome": "Fixed: prettier format:changed; PR_POLICY_BODY sync for Clinical Governance Preflight; empty commit retriggered PR Policy after body sync race. Review threads already resolved (fb8adf92). Required checks green (PR policy, Static PR, PR required). mergeStateStatus BEHIND vs moving main — merge-tree clean.", + "outcome": "Fixed: prettier format:changed; PR_POLICY_BODY sync for Clinical Governance Preflight; empty commit retriggered PR Policy after body sync race. Review threads already resolved (fb8adf92). Required checks green (PR policy, Static PR, PR required). mergeStateStatus BEHIND vs moving main \u2014 merge-tree clean.", "checks": "vitest:54/54; prettier:pass; pr-policy:pass; static-pr:pass; pr-required:pass" }, { @@ -4778,7 +4777,7 @@ "ref": "claude/browser-test-gate-handoff-d5c1db (PR #2347)", "head": "d3f5edc26b319f5feccebd628fd537855321f33c", "scope": "Run PR sweep: CI fixes (owner closed mid-sweep)", - "outcome": "Before: PR required failing (Static PR checks: stale outstanding-issues snapshot + 3 broken docs-links; PR policy: Clinical Governance Preflight unchecked) and behind main. Fixed: (1) regenerated data/outstanding-issues-snapshot.json via its generator script; (2) added 3 scoped docs-link-checker allowlist entries in scripts/check-docs-links.mjs for historical/quoted-diagnostic path references in the Phase 2B SDD archive docs (verified locally, not a broken link). Synced origin/main in (clean merge-tree) both times. Static PR checks went green after both fixes. PR policy remained red (Clinical Governance Preflight checkboxes require a PR-body edit, outside this sweep's authorization). The PR owner (BigSimmo) then closed the PR at 14:42 UTC for unrelated reasons (auto-merge armed on incomplete work; a known-false workspace-coverage claim; explained in PR comment) — not an action taken by this sweep. Both fix commits remain on the branch per the owner's own comment (nothing lost).", + "outcome": "Before: PR required failing (Static PR checks: stale outstanding-issues snapshot + 3 broken docs-links; PR policy: Clinical Governance Preflight unchecked) and behind main. Fixed: (1) regenerated data/outstanding-issues-snapshot.json via its generator script; (2) added 3 scoped docs-link-checker allowlist entries in scripts/check-docs-links.mjs for historical/quoted-diagnostic path references in the Phase 2B SDD archive docs (verified locally, not a broken link). Synced origin/main in (clean merge-tree) both times. Static PR checks went green after both fixes. PR policy remained red (Clinical Governance Preflight checkboxes require a PR-body edit, outside this sweep's authorization). The PR owner (BigSimmo) then closed the PR at 14:42 UTC for unrelated reasons (auto-merge armed on incomplete work; a known-false workspace-coverage claim; explained in PR comment) \u2014 not an action taken by this sweep. Both fix commits remain on the branch per the owner's own comment (nothing lost).", "checks": "node scripts/generate-outstanding-issues-snapshot.mjs + node scripts/check-outstanding-issues-snapshot.mjs (pass); node scripts/check-docs-links.mjs (pass, 3322 refs resolve); prettier --check scripts/check-docs-links.mjs (pass). No provider-backed checks run." }, { @@ -4786,8 +4785,8 @@ "ref": "claude/review-queue-header-design-of7baq (PR #2338)", "head": "c934541ceca611481073c4b761da98b99545b05a", "scope": "Run PR sweep: drift sync", - "outcome": "No code fix needed; branch was only behind origin/main (clean merge-tree). Merged origin/main and pushed. Both existing review threads already resolved. Remaining CI failure: PR policy blocks on missing Clinical Governance Preflight section (src/lib/mode-secondary-navigation.ts change triggers clinicalRisk) — left open, PR body edits are out of scope for this sweep.", - "checks": "npx vitest run tests/therapy-compass-pathways.test.ts tests/route-reachability.test.ts tests/therapy-compass-mode-wiring.test.ts tests/therapy-review-regressions.test.ts tests/mode-nav-contract.test.ts tests/mode-secondary-navigation.test.ts tests/therapy-compass-responsive-contract.test.ts — 113 passed; no provider-backed checks run" + "outcome": "No code fix needed; branch was only behind origin/main (clean merge-tree). Merged origin/main and pushed. Both existing review threads already resolved. Remaining CI failure: PR policy blocks on missing Clinical Governance Preflight section (src/lib/mode-secondary-navigation.ts change triggers clinicalRisk) \u2014 left open, PR body edits are out of scope for this sweep.", + "checks": "npx vitest run tests/therapy-compass-pathways.test.ts tests/route-reachability.test.ts tests/therapy-compass-mode-wiring.test.ts tests/therapy-review-regressions.test.ts tests/mode-nav-contract.test.ts tests/mode-secondary-navigation.test.ts tests/therapy-compass-responsive-contract.test.ts \u2014 113 passed; no provider-backed checks run" }, { "date": "2026-08-24", @@ -4795,7 +4794,7 @@ "head": "6ef5b3617956ba8e0a4fa69a1953ec51cba1336f", "scope": "Run PR sweep: branch sync", "outcome": "Already fully green (PR required success) before sweep; only action was syncing origin/main in (clean merge-tree, no conflicts) via update_pull_request_branch. All 5 review threads were already resolved by the author. Post-sync CI reconfirmed green (PR required success at run 32741127269).", - "checks": "No local gates run — no code change, only a merge-from-main sync; CI (Static PR checks, Lint, Typecheck, Unit coverage, Build, Production UI x3, Production UI critical, Lighthouse budget, PR policy, PR required) reran green on GitHub. No provider-backed checks run." + "checks": "No local gates run \u2014 no code change, only a merge-from-main sync; CI (Static PR checks, Lint, Typecheck, Unit coverage, Build, Production UI x3, Production UI critical, Lighthouse budget, PR policy, PR required) reran green on GitHub. No provider-backed checks run." }, { "date": "2026-08-24", @@ -4827,23 +4826,23 @@ "head": "1683edfbd66d2e13bee9f7e533e87218ea9237d8", "scope": "Run PR sweep: main sync + conflict resolution", "outcome": "Before: draft mockup PR reported mergeable_state=dirty. git merge-tree confirmed a real conflict, isolated to generated docs/site-map.md (plus a clean auto-merge in src/app/mockups/mockups-layout-client.tsx). No failing CI, no unresolved review threads. Fix: merged origin/main in an isolated worktree, kept ours for site-map.md then regenerated it via npm run sitemap:update (pre-commit doc-sync hook ran clean), pushed the merge commit. After: mergeable_state=blocked pending checks then PR required green at 1683edfb.", - "checks": "npx vitest run tests/answer-chat-redesign-mockups.test.ts tests/answer-chat-redesign-mockups.dom.test.tsx — 2 files, 7 passed. CI (hosted): PR required success at 1683edfb. No provider-backed checks run." + "checks": "npx vitest run tests/answer-chat-redesign-mockups.test.ts tests/answer-chat-redesign-mockups.dom.test.tsx \u2014 2 files, 7 passed. CI (hosted): PR required success at 1683edfb. No provider-backed checks run." }, { "date": "2026-08-24", "ref": "cursor/calculators-show-all-mockups-7ce3 (PR #2337)", "head": "ff09c24260e2616b7b7c7bb12e19572aa03fba85", "scope": "Run PR sweep: CI fix", - "outcome": "Fixed real CI failure: Static PR checks failed on check:design-system-contract arbitraryTracking ratchet — tracking-[-0.01em] in show-all-chip.tsx switched to the sanctioned tracking-[var(--tracking-display)] token (folds per globals.css letterspacing scale doc). Branch was not behind main (0 behind). Sole open review thread already resolved; no unresolved threads found. PR title/body/head changed mid-sweep via a concurrent author push (Cursor cloud agent) before this fix; re-verified against the latest head before pushing.", - "checks": "npm run check:design-system-contract — pass (arbitrary tracking 0); npx vitest run tests/calculators-mode.dom.test.tsx tests/consolidated-mode-home-redirect.test.ts tests/favourites-auth-gate.dom.test.tsx tests/calculators-show-all-mockups.dom.test.tsx — 48 passed; npx eslint on changed file — clean; no provider-backed checks run" + "outcome": "Fixed real CI failure: Static PR checks failed on check:design-system-contract arbitraryTracking ratchet \u2014 tracking-[-0.01em] in show-all-chip.tsx switched to the sanctioned tracking-[var(--tracking-display)] token (folds per globals.css letterspacing scale doc). Branch was not behind main (0 behind). Sole open review thread already resolved; no unresolved threads found. PR title/body/head changed mid-sweep via a concurrent author push (Cursor cloud agent) before this fix; re-verified against the latest head before pushing.", + "checks": "npm run check:design-system-contract \u2014 pass (arbitrary tracking 0); npx vitest run tests/calculators-mode.dom.test.tsx tests/consolidated-mode-home-redirect.test.ts tests/favourites-auth-gate.dom.test.tsx tests/calculators-show-all-mockups.dom.test.tsx \u2014 48 passed; npx eslint on changed file \u2014 clean; no provider-backed checks run" }, { "date": "2026-08-24", "ref": "cursor/dictionary-control-row-polish-4ee0 (PR #2316)", "head": "090c5f274e293fa5209cff6fa1565e2e50fa3c6d", "scope": "Run PR sweep: main sync", - "outcome": "Before: ready-for-review PR behind main (mergeable_state=behind); 2 review threads present, both already resolved (P1 alignment finding fixed in e475f236/5498f030; CodeRabbit letter-chip tap-target finding fixed in 6de85d94) — no unresolved threads, no new actionable comments. Synced via update_pull_request_branch (clean fast-forward merge of origin/main, no conflicts). After: mergeable_state=blocked pending checks then PR required green at 090c5f27 (all 13 constituent jobs incl. Unit coverage, Build, 3x Production UI, Lighthouse, Static PR checks succeeded).", - "checks": "CI (hosted): PR required success at 090c5f27. No local gate run — sync-only, no source files changed by the sweep. No provider-backed checks run." + "outcome": "Before: ready-for-review PR behind main (mergeable_state=behind); 2 review threads present, both already resolved (P1 alignment finding fixed in e475f236/5498f030; CodeRabbit letter-chip tap-target finding fixed in 6de85d94) \u2014 no unresolved threads, no new actionable comments. Synced via update_pull_request_branch (clean fast-forward merge of origin/main, no conflicts). After: mergeable_state=blocked pending checks then PR required green at 090c5f27 (all 13 constituent jobs incl. Unit coverage, Build, 3x Production UI, Lighthouse, Static PR checks succeeded).", + "checks": "CI (hosted): PR required success at 090c5f27. No local gate run \u2014 sync-only, no source files changed by the sweep. No provider-backed checks run." }, { "date": "2026-08-24", @@ -4851,23 +4850,23 @@ "head": "271e506d6e3ca024a9bfefae51c99dc9f669ec93", "scope": "Run PR sweep: main sync", "outcome": "Before: draft mockup PR behind main (mergeable_state=behind), no failing CI, no unresolved review threads. Synced via update_pull_request_branch (clean fast-forward merge of origin/main, no conflicts). After: mergeable_state=clean, latest CI run green (PR required: success).", - "checks": "CI (hosted): PR required success at 271e506d. No local gate run — sync-only, no source files changed by the sweep. No provider-backed checks run." + "checks": "CI (hosted): PR required success at 271e506d. No local gate run \u2014 sync-only, no source files changed by the sweep. No provider-backed checks run." }, { "date": "2026-08-24", "ref": "cursor/dictionary-persistent-filter-band-4ee0 (PR #2341)", "head": "cc99fef611bcb3ed4d7bb2b79434a136b8f61c99", "scope": "Run PR sweep: CI diagnosis + drift sync", - "outcome": "Before: PR required failing (Production UI shard 3 red on an unrelated differentials-compare-queue test); behind main. Diagnosed via job log: failure was in tests/ui-tools.spec.ts differentials compare queue test, unrelated to this PR's dictionary-only diff. Re-ran the failed job on the pre-sync head — it passed, confirming flake not regression. Synced origin/main in (clean merge-tree) via update_pull_request_branch. Post-sync full CI green (PR required success at run 32741127269). All 4 review threads were already resolved by the author before the sweep; none required action.", - "checks": "No local code changes and no local gates run for this PR — root cause was CI-side (rerun) and branch drift (sync), both diagnosed/fixed via GitHub. No provider-backed checks run." + "outcome": "Before: PR required failing (Production UI shard 3 red on an unrelated differentials-compare-queue test); behind main. Diagnosed via job log: failure was in tests/ui-tools.spec.ts differentials compare queue test, unrelated to this PR's dictionary-only diff. Re-ran the failed job on the pre-sync head \u2014 it passed, confirming flake not regression. Synced origin/main in (clean merge-tree) via update_pull_request_branch. Post-sync full CI green (PR required success at run 32741127269). All 4 review threads were already resolved by the author before the sweep; none required action.", + "checks": "No local code changes and no local gates run for this PR \u2014 root cause was CI-side (rerun) and branch drift (sync), both diagnosed/fixed via GitHub. No provider-backed checks run." }, { "date": "2026-08-24", "ref": "cursor/factsheets-topics-page-ec19 (PR #2333)", "head": "7fe94b6198fb8b78674b0b423be57851704f86c7", "scope": "Run PR sweep: CI fix + drift sync", - "outcome": "Fixed real CI failure: legacyTapClasses (h-11/w-11) in factsheets-topics-browse.tsx bumped to h-12/w-12; merged origin/main (clean); a concurrent upstream push (b2c23389d) then rewrote the same component, resolved by merge taking upstream's version (no more -11 class) and regenerating COMPONENTS.md. 4 review threads already resolved, none new. Remaining CI failure: PR policy blocks on missing Clinical Governance Preflight section (src/lib/mode-secondary-navigation.ts triggers clinicalRisk) — left open, PR body edits are out of scope for this sweep.", - "checks": "npm run check:design-system-contract (incl. design-system-adoption, design-sync-contract) — pass; npx vitest run tests/factsheets-topics-page.dom.test.tsx tests/factsheets-topics-phone-mockups.test.ts tests/factsheets-data.test.ts tests/design-system-adoption.test.ts tests/mode-secondary-navigation.test.ts — 109 passed; npx eslint on changed file — clean; no provider-backed checks run" + "outcome": "Fixed real CI failure: legacyTapClasses (h-11/w-11) in factsheets-topics-browse.tsx bumped to h-12/w-12; merged origin/main (clean); a concurrent upstream push (b2c23389d) then rewrote the same component, resolved by merge taking upstream's version (no more -11 class) and regenerating COMPONENTS.md. 4 review threads already resolved, none new. Remaining CI failure: PR policy blocks on missing Clinical Governance Preflight section (src/lib/mode-secondary-navigation.ts triggers clinicalRisk) \u2014 left open, PR body edits are out of scope for this sweep.", + "checks": "npm run check:design-system-contract (incl. design-system-adoption, design-sync-contract) \u2014 pass; npx vitest run tests/factsheets-topics-page.dom.test.tsx tests/factsheets-topics-phone-mockups.test.ts tests/factsheets-data.test.ts tests/design-system-adoption.test.ts tests/mode-secondary-navigation.test.ts \u2014 109 passed; npx eslint on changed file \u2014 clean; no provider-backed checks run" }, { "date": "2026-08-24", @@ -5018,7 +5017,7 @@ "ref": "claude/ed-care-plans-impl-7f44cd (PR #2291)", "head": "620743d434dfcc158811720ca53d09caf9c4b750", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Before: mergeable_state dirty (main-sync merge conflict never attempted — hard-stopped and reported per clinical-content-conflict policy since the PR branch and main both independently built the care-plan feature after PR #2274 landed), PR mergeability + PR policy both failing, 0 of 6 unresolved P1 review threads addressed, real CI (pr-required) never triggered. After: PR owner (BigSimmo) resolved the main-sync merge conflict live and independently fixed all 6 P1 Codex findings on the branch while this sweep was in progress; this session's own independent fixes for the same 6 findings were reconciled against the owner's landed versions (kept the owner's naming/implementation where duplicated, kept this session's unique patient-plan-print-stale-in-subtree fix which the owner's merge did not touch, removed this session's now-dead-code duplicate blocks e.g. two near-identical withdrawal stale-trigger blocks and two approve-patient-plan-version refusal blocks left by concurrent independent 3-way merges, added 3 new regression tests). mergeable_state now blocked (not dirty) — no more content conflict. PR mergeability: success. PR policy: still failing (only blocker: PR body Clinical Governance Preflight all 7 boxes unchecked plus advisory warnings on blank Summary/Verification/Risk sections — PR body left untouched per this sweep's explicit instruction not to edit it). Real CI (pr-required aggregate) triggered for the first time on this PR and was still in progress after 25 minutes of observation (Build, Unit coverage, Static PR checks, Production UI x4, Advisory UI, Lighthouse budget all in_progress; Change scope/Gitleaks/Semgrep/Safety and config checks/GitGuardian all green) — not yet settled at end of this sweep's observation window. All 6 review threads already resolved by BigSimmo before this session's push landed; nothing left to reply/resolve. 3 commits pushed: 61c6b562 (own fixes), 70e700db (merge #1, resolving owner's first live main-sync push), 620743d4 (merge #2, resolving owner's second live push that independently fixed the exact same contact-guard finding).", + "outcome": "Before: mergeable_state dirty (main-sync merge conflict never attempted \u2014 hard-stopped and reported per clinical-content-conflict policy since the PR branch and main both independently built the care-plan feature after PR #2274 landed), PR mergeability + PR policy both failing, 0 of 6 unresolved P1 review threads addressed, real CI (pr-required) never triggered. After: PR owner (BigSimmo) resolved the main-sync merge conflict live and independently fixed all 6 P1 Codex findings on the branch while this sweep was in progress; this session's own independent fixes for the same 6 findings were reconciled against the owner's landed versions (kept the owner's naming/implementation where duplicated, kept this session's unique patient-plan-print-stale-in-subtree fix which the owner's merge did not touch, removed this session's now-dead-code duplicate blocks e.g. two near-identical withdrawal stale-trigger blocks and two approve-patient-plan-version refusal blocks left by concurrent independent 3-way merges, added 3 new regression tests). mergeable_state now blocked (not dirty) \u2014 no more content conflict. PR mergeability: success. PR policy: still failing (only blocker: PR body Clinical Governance Preflight all 7 boxes unchecked plus advisory warnings on blank Summary/Verification/Risk sections \u2014 PR body left untouched per this sweep's explicit instruction not to edit it). Real CI (pr-required aggregate) triggered for the first time on this PR and was still in progress after 25 minutes of observation (Build, Unit coverage, Static PR checks, Production UI x4, Advisory UI, Lighthouse budget all in_progress; Change scope/Gitleaks/Semgrep/Safety and config checks/GitGuardian all green) \u2014 not yet settled at end of this sweep's observation window. All 6 review threads already resolved by BigSimmo before this session's push landed; nothing left to reply/resolve. 3 commits pushed: 61c6b562 (own fixes), 70e700db (merge #1, resolving owner's first live main-sync push), 620743d4 (merge #2, resolving owner's second live push that independently fixed the exact same contact-guard finding).", "checks": "Local only, no provider-backed checks run: npm run typecheck (clean, 4695 files), npm run lint (clean, 4695 files), node scripts/run-vitest.mjs run tests/care-plan-patient-plan.test.ts tests/care-plan-linked-routes.dom.test.tsx tests/care-plan-prototype-state.test.ts tests/care-plan-domain.test.ts tests/care-plan-route-files.test.ts (440 passed), npm run test full suite (8476 passed, 1 skipped, 1 unrelated pre-existing async-timer-after-teardown flake in caring-contact-shell-frame.tsx unrelated to this diff), npx prettier --check on touched files (clean). No eval:rag, eval:quality, eval:retrieval:quality, verify:release, check:supabase-project, or test:live run." }, { @@ -5026,15 +5025,15 @@ "ref": "claude/post-drift-ledger-tidy", "head": "5ff3f0419d6696f59eb638cfbbf4f28c2f964ba6", "scope": "post-drift ledger tidying: close #M54C4N/#056/#3514B7, re-scope #47M1XD, escalate #M6JNR8; read-only staging+production verification", - "outcome": "pass — three rows closed with quoted evidence (live-drift run 32514326022; staging 211-row parity), #47M1XD advanced with a second production window that strengthened the zero-scan retraction and showed the proposed ANALYZE experiment cannot discriminate (n_mod_since_analyze=0 on four of five tables); owner chose to skip ANALYZE so no production mutation. #231 queue row could NOT be corrected: hand edit and same-PR reconcile both empirically refused by check:ledger-write-discipline, escalated as #M6JNR8 P1", + "outcome": "pass \u2014 three rows closed with quoted evidence (live-drift run 32514326022; staging 211-row parity), #47M1XD advanced with a second production window that strengthened the zero-scan retraction and showed the proposed ANALYZE experiment cannot discriminate (n_mod_since_analyze=0 on four of five tables); owner chose to skip ANALYZE so no production mutation. #231 queue row could NOT be corrected: hand edit and same-PR reconcile both empirically refused by check:ledger-write-discipline, escalated as #M6JNR8 P1", "checks": "check:ledger-write-discipline, check:outstanding-issues, check:branch-review-ledger, prettier --check on changed files" }, { "date": "2026-08-22", "ref": "claude/rag-quality-predicate-gap-uw320a", "head": "957b76afa20c4b4667f41cbb0725d71482171228", - "scope": "Packet 2 (#NPQJKP): answer-quality predicate gap — src/lib/rag/rag-extractive-answer.ts, tests/rag-guidance-wrapper-quality-gate.test.ts, docs/rag-improvement/HANDOVER.md pointer line", - "outcome": "SHIPPED as PR #2285 (draft). Falsification confirmed the premise first: generatedAnswerQualityFailureReason returned null for both captured incoherent answers at their real query classes (medication_dose_risk, document_lookup) against unmodified source. Two corrections to the recorded diagnosis: (1) the gate is NOT unreachable on the grounded extractive path — the enforcing call is unconditional inside finalizeRagAnswerQualityCore, reached via finalizeAnswer, so NO reachability change was made; only the preformatted-and-grounded early return remains as a bypass and is now pinned by test. (2) the wrapper is not purely laundering — a first predicate keyed on openingSentenceActionPattern broke the ECT 'places the patient onto BASE' answer pinned by rag-extractive-procedural-artifact, so the shipped predicate rejects only a '>' breadcrumb aimed at a word and a bare coordinated noun list. Placed after the other prose gates so nothing is relabelled; outside the shouldPreserveSourceBackedGeneratedAnswer rescue allowlist. NO ranking, selection, retrieval, prompt or budget change; answerRouteBudgetMs untouched. Live eval-canary pair still owed under owner approval.", + "scope": "Packet 2 (#NPQJKP): answer-quality predicate gap \u2014 src/lib/rag/rag-extractive-answer.ts, tests/rag-guidance-wrapper-quality-gate.test.ts, docs/rag-improvement/HANDOVER.md pointer line", + "outcome": "SHIPPED as PR #2285 (draft). Falsification confirmed the premise first: generatedAnswerQualityFailureReason returned null for both captured incoherent answers at their real query classes (medication_dose_risk, document_lookup) against unmodified source. Two corrections to the recorded diagnosis: (1) the gate is NOT unreachable on the grounded extractive path \u2014 the enforcing call is unconditional inside finalizeRagAnswerQualityCore, reached via finalizeAnswer, so NO reachability change was made; only the preformatted-and-grounded early return remains as a bypass and is now pinned by test. (2) the wrapper is not purely laundering \u2014 a first predicate keyed on openingSentenceActionPattern broke the ECT 'places the patient onto BASE' answer pinned by rag-extractive-procedural-artifact, so the shipped predicate rejects only a '>' breadcrumb aimed at a word and a bare coordinated noun list. Placed after the other prose gates so nothing is relabelled; outside the shouldPreserveSourceBackedGeneratedAnswer rescue allowlist. NO ranking, selection, retrieval, prompt or budget change; answerRouteBudgetMs untouched. Live eval-canary pair still owed under owner approval.", "checks": "verify:pr-local exit 0, all 19 gates completed / none failed (lint, typecheck, test, build, eval:rag:offline, eval:rag:adversarial:offline); a concurrent second invocation exited 75 DATABASE_HEAVY_RUN_ADMISSION_BUSY on self-inflicted lease contention, and a later confirmation re-run hit a PRE-EXISTING unrelated flake (ReferenceError: document is not defined from a 250ms setTimeout in src/components/caring-contacts/mockups/caring-contact-shell-frame.tsx:104 firing after jsdom teardown; 714 files / 8359 tests still passed). typecheck:internal exit 0 on the committed tree. Focused 300/300 across the seven suites exercising this predicate. eval:rag:offline 627/627 and eval:rag:adversarial:offline 25/25, identical before and after with the baseline re-run under GATE_RECEIPTS=refresh. No provider-backed command run; no canary dispatched." }, { @@ -5186,8 +5185,8 @@ "ref": "codex/ward-management-design (PR #2289)", "head": "6e1300fa6dcb31ba63727b9d5b3b52cab0b05cb5", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Before: mergeable_state dirty (PR mergeability + PR policy both failing; real CI never triggered), 3 unresolved P1 review threads. After: all 6 review threads resolved (3 fixed with regression tests + pushed commit 6e1300fa; 3 pre-existing already resolved). mergeable_state remains dirty and was deliberately left unresolved: git merge-tree shows 34 conflicts (14 content, 20 add/add) against origin/main, all traced to PR #2140 (\"Add Ward Flow: synthetic ward/bed-management coordination prototype\", already merged to main) independently re-implementing the same ward-management/legal-detention-workflow feature this PR builds from a much older, unrelated base (zero common history until git fetch --deepen=5000 recovered a real merge-base 752 commits back). This is a genuine duplicate-feature conflict on clinical workflow content (Mental Health Act detention forms, bed/patient placement), not staleness — hard-stopped per policy rather than resolved with ours/theirs. Real CI (static-pr/pr-required/build/etc.) cannot run until a human resolves this at the product level.", - "checks": "Local only, no provider-backed checks: npx vitest run on 9 touched/related ward-flow test files (84 passed, including 2 new regression tests — one for the reducer closure/capacity-release fix, one for the provider clock-monotonicity fix, both confirmed to fail against pre-fix code), npx tsc --noEmit -p tsconfig.json (0 errors, full project), npx eslint on all 6 changed files (0 findings), npx prettier --check on all 6 changed files (all formatted). No verify:cheap/verify:pr-local/verify:ui run (diff too large and blocked on unrelated merge conflict; would not have exercised anything beyond the focused tests already run). No eval:rag, eval:quality, eval:retrieval:quality, verify:release, check:supabase-project, test:live, or any other provider-backed gate was run." + "outcome": "Before: mergeable_state dirty (PR mergeability + PR policy both failing; real CI never triggered), 3 unresolved P1 review threads. After: all 6 review threads resolved (3 fixed with regression tests + pushed commit 6e1300fa; 3 pre-existing already resolved). mergeable_state remains dirty and was deliberately left unresolved: git merge-tree shows 34 conflicts (14 content, 20 add/add) against origin/main, all traced to PR #2140 (\"Add Ward Flow: synthetic ward/bed-management coordination prototype\", already merged to main) independently re-implementing the same ward-management/legal-detention-workflow feature this PR builds from a much older, unrelated base (zero common history until git fetch --deepen=5000 recovered a real merge-base 752 commits back). This is a genuine duplicate-feature conflict on clinical workflow content (Mental Health Act detention forms, bed/patient placement), not staleness \u2014 hard-stopped per policy rather than resolved with ours/theirs. Real CI (static-pr/pr-required/build/etc.) cannot run until a human resolves this at the product level.", + "checks": "Local only, no provider-backed checks: npx vitest run on 9 touched/related ward-flow test files (84 passed, including 2 new regression tests \u2014 one for the reducer closure/capacity-release fix, one for the provider clock-monotonicity fix, both confirmed to fail against pre-fix code), npx tsc --noEmit -p tsconfig.json (0 errors, full project), npx eslint on all 6 changed files (0 findings), npx prettier --check on all 6 changed files (all formatted). No verify:cheap/verify:pr-local/verify:ui run (diff too large and blocked on unrelated merge conflict; would not have exercised anything beyond the focused tests already run). No eval:rag, eval:quality, eval:retrieval:quality, verify:release, check:supabase-project, test:live, or any other provider-backed gate was run." }, { "date": "2026-08-22", @@ -5362,7 +5361,7 @@ "ref": "claude/auto-close-next-servers-7ymzsx", "head": "fbeb67c2e4f8a7e144d790bd3c94129b9c95cf4f", "scope": "scripts/dev-free-port.mjs, scripts/ensure-local-server.mjs, src/lib/local-server-utils.mjs, tests/local-server-utils.test.ts, README.md", - "outcome": "approved — self-authored PR #2212, idle-timeout self-shutdown for ensure-started background dev servers", + "outcome": "approved \u2014 self-authored PR #2212, idle-timeout self-shutdown for ensure-started background dev servers", "checks": "eslint (clean), vitest tests/local-server-utils.test.ts (5 passed), prettier --check . (clean), manual smoke test of idle shutdown against a real next dev boot" }, { @@ -5370,23 +5369,23 @@ "ref": "claude/clever-bohr-w87uiz", "head": "0fcd789a8625f1abfe120cd1a274166948537d71", "scope": "Claude Code web container parity, code half of the PR #2227 split: tiered provisioner, cloud-profile applier, CLAUDE.md/settings/memory snapshot, SessionStart registration, contract doc, 18 tests", - "outcome": "PR #2236 opened (draft), replacing #2227. Vendored skill tree moved to PR #2238 so this diff is 28 files instead of 543; CodeRabbit's 150-file limit is why #2227 received no automated review at all. The applier already guarded skills on existsSync; the test file now states which assertions need the tree and a new test pins that guard, so this PR stands alone. Container tiers plugins/gh/deno/browsers/python remain unexecuted anywhere — no Linux container was available to run them in, and the first real cloud session is the acceptance test", + "outcome": "PR #2236 opened (draft), replacing #2227. Vendored skill tree moved to PR #2238 so this diff is 28 files instead of 543; CodeRabbit's 150-file limit is why #2227 received no automated review at all. The applier already guarded skills on existsSync; the test file now states which assertions need the tree and a new test pins that guard, so this PR stands alone. Container tiers plugins/gh/deno/browsers/python remain unexecuted anywhere \u2014 no Linux container was available to run them in, and the first real cloud session is the acceptance test", "checks": "lint gate-receipts pass 3950 files, typecheck gate-receipts pass 3950 files, npm run test full offline suite 697 files 7694 passed 6 skipped exit 0, vitest tests/claude-cloud-profile.test.ts 16 passed 2 skipped without the tree and 18 passed with it, format:changed whole-tree escalation all files pass, docs:update no drift 254 scripts 255 npm scripts, docs:check-links 2082 refs resolve, check:branch-review-ledger pass, git merge-tree against the #2238 branch exit 0 no conflict" }, { "date": "2026-08-21", "ref": "claude/clever-bohr-w87uiz", "head": "5d4aedb86809debbc277f534eae35fe015e9f5a1", - "scope": "tests/claude-cloud-profile.test.ts — sandbox HOME for every provisioner spawn so the suite stops reading the machine's real marker/lock directory", + "scope": "tests/claude-cloud-profile.test.ts \u2014 sandbox HOME for every provisioner spawn so the suite stops reading the machine's real marker/lock directory", "outcome": "Fixes a false red that landed via PR #2236: the held-lock test planted its fixture in the real ~/.cache/clinical-kb-claude-cloud, so a completed-tier marker short-circuited the deno tier before the code under test ran. Failed on any provisioned container, passed on CI's clean runners, which is how it reached main. HOME override suffices because the provisioner is a shell script; the applier still needs CLAUDE_CONFIG_DIR for the Windows os.homedir() reason. No production code changed. Adds a guard test pinning the isolation", - "checks": "vitest tests/claude-cloud-profile.test.ts in all three states with a real deno.marker on the container — before 1 failed 22 passed, after with marker present 24 passed, after with marker absent 24 passed; full offline suite 695 files 7726 passed 1 skipped exit 0; lint gate-receipts pass 4365 files; typecheck gate-receipts pass 4365 files; format:changed all files pass" + "checks": "vitest tests/claude-cloud-profile.test.ts in all three states with a real deno.marker on the container \u2014 before 1 failed 22 passed, after with marker present 24 passed, after with marker absent 24 passed; full offline suite 695 files 7726 passed 1 skipped exit 0; lint gate-receipts pass 4365 files; typecheck gate-receipts pass 4365 files; format:changed all files pass" }, { "date": "2026-08-21", "ref": "claude/frontend-design-6sl1ft", "head": "8b26a5c4ce836db00e031e2ad3ee3980e8a9d1a9", "scope": "design-review remediation + loose ends + nested-mockup CI scope routing", - "outcome": "applied — 20 review findings resolved or dispositioned, 5 loose ends closed, 1 CI scope gap fixed; 3 architectural items recorded as decisions in TOKENS.md §9 / COMPONENTS.md §0.4", + "outcome": "applied \u2014 20 review findings resolved or dispositioned, 5 loose ends closed, 1 CI scope gap fixed; 3 architectural items recorded as decisions in TOKENS.md \u00a79 / COMPONENTS.md \u00a70.4", "checks": "verify:pr-local exit 0 (28/28 gates after CI-scope widening; 7599 tests passed, 4 skipped, 0 errors; build ok); full suite green with no gh CLI; verify:ui delegated to CI Production UI (playwright revision drift #255, and heavy jobs are draft-gated)" }, { @@ -5394,7 +5393,7 @@ "ref": "claude/frontend-design-6sl1ft", "head": "ca7b187ae74991d3135437c79c8cc41e8db1e567", "scope": "prlanded", - "outcome": "landed clean — PR #2210 merged 2026-08-21T11:07:02Z by BigSimmo via merge commit ca7b187 (merge method 'merge', not squash); content diff ca7b187..3dde98d empty, 0 of 11 commits orphaned, remote branch auto-deleted", + "outcome": "landed clean \u2014 PR #2210 merged 2026-08-21T11:07:02Z by BigSimmo via merge commit ca7b187 (merge method 'merge', not squash); content diff ca7b187..3dde98d empty, 0 of 11 commits orphaned, remote branch auto-deleted", "checks": "git diff --stat ca7b187 3dde98d empty; per-commit ancestry 11/11 reachable from origin/main; final CI green incl. Production UI (1)(2)(3), Production UI critical, Advisory UI, Unit coverage, Build, Static PR checks; Lighthouse mobile-root CLS confirmed as the documented bistable 0.016/0.223 flake, not a diff regression" }, { @@ -5402,7 +5401,7 @@ "ref": "claude/frontend-design-6sl1ft", "head": "eaae8bde3066749f105233c1492d6f044671b91b", "scope": "full-frontend design review remediation: tokens, ward a11y, answer support label, gate gaps", - "outcome": "applied — 20 review findings resolved or dispositioned; 3 architectural items deliberately deferred", + "outcome": "applied \u2014 20 review findings resolved or dispositioned; 3 architectural items deliberately deferred", "checks": "verify:pr-local exit 0 (19/19 gates; 7599 tests passed, 4 skipped, 0 errors; build 1871 pages); verify:ui delegated to CI Production UI (playwright revision drift #255)" }, { @@ -5417,9 +5416,9 @@ "date": "2026-08-21", "ref": "claude/gate-e-verdict-record", "head": "be62c06371039cafec9f4504ca696d1ad2c67be1", - "scope": "docs/rag-improvement/HANDOVER.md — Gate E blinded-read verdict recorded in the S2 and Gate E rows", + "scope": "docs/rag-improvement/HANDOVER.md \u2014 Gate E blinded-read verdict recorded in the S2 and Gate E rows", "outcome": "Docs-only. Owner blinded read complete: v18 4ea310e48 3 / v19 cdfcbaccd 3 / tie 24 / neither 0 across 30 pairs; recorded with its three caveats (after-half is cdfcbaccd not current main; 24/30 pairs byte-identical and v18 20/30 vs v19 21/30 source_only so the tally partly measures the #231 fallback rate; baseline-record section 4 readability confound). #E0N0QC was already resolved on main at 1cc0d2987 by a separate fix, so no ledger close was queued.", - "checks": "verify:pr-local docs scope — completed check:runtime, check:installed-lock-parity, format:changed, sitemap:check, docs:check-index, docs:check-inventory, docs:check-scripts, docs:check-links, check:branch-review-ledger, check:outstanding-issues, check:ledger-write-discipline; failed: (none); not reached: (none)" + "checks": "verify:pr-local docs scope \u2014 completed check:runtime, check:installed-lock-parity, format:changed, sitemap:check, docs:check-index, docs:check-inventory, docs:check-scripts, docs:check-links, check:branch-review-ledger, check:outstanding-issues, check:ledger-write-discipline; failed: (none); not reached: (none)" }, { "date": "2026-08-21", @@ -5427,15 +5426,15 @@ "head": "9d8a03f1ea8f7ff00b5a9766476593c0271315db", "scope": "prlanded", "outcome": "merged clean, content diff empty, no orphaned commits", - "checks": "PR required, Static PR checks, PR policy, PR mergeability, Change scope, Gitleaks, Semgrep, GitGuardian — all green on head" + "checks": "PR required, Static PR checks, PR policy, PR mergeability, Change scope, Gitleaks, Semgrep, GitGuardian \u2014 all green on head" }, { "date": "2026-08-21", "ref": "claude/issues-reconcile-post-2206", "head": "02d1bcaab01f933b8af3eefa3a7f085e95aac661", "scope": "docs(issues): reconcile the queued inbox batch into the canonical ledger (#2218)", - "outcome": "Backfilled record — PR #2218 merged 2026-08-21 (squash 02d1bcaab01f933b8af3eefa3a7f085e95aac661) with no review record captured at the time. Diff inspected post hoc: 29 immutable inbox requests applied verbatim into docs/outstanding-issues.md plus 2 closures (#VZN8G3 dup of #BSBE9B, #Q5JHBJ archived) verified against the ledger by the PR author; docs-only, classifyPullRequestFiles clinicalRisk:false, no RAG/src/worker/supabase paths touched. Approved by content.", - "checks": "PR-reported: reconciler applied 29/29 requests cleanly; pre-push guard ran check:ledger-write-discipline on pushed commit 42dc0e0f4 with no rejection; Prettier clean on changed markdown; CI static-pr required checks green (merged). Not independently re-run in this session — docs-truth backfill only." + "outcome": "Backfilled record \u2014 PR #2218 merged 2026-08-21 (squash 02d1bcaab01f933b8af3eefa3a7f085e95aac661) with no review record captured at the time. Diff inspected post hoc: 29 immutable inbox requests applied verbatim into docs/outstanding-issues.md plus 2 closures (#VZN8G3 dup of #BSBE9B, #Q5JHBJ archived) verified against the ledger by the PR author; docs-only, classifyPullRequestFiles clinicalRisk:false, no RAG/src/worker/supabase paths touched. Approved by content.", + "checks": "PR-reported: reconciler applied 29/29 requests cleanly; pre-push guard ran check:ledger-write-discipline on pushed commit 42dc0e0f4 with no rejection; Prettier clean on changed markdown; CI static-pr required checks green (merged). Not independently re-run in this session \u2014 docs-truth backfill only." }, { "date": "2026-08-21", @@ -5483,7 +5482,7 @@ "head": "653712cbeda0059979e71131e828241f921f17da", "scope": "PR #2250 review-thread sweep: Codex P1/P2 + CodeRabbit findings on the Phase 5 close-out docs and ledger inbox", "outcome": "Fixed and resolved. P1 db-push contradiction removed (db push reserved for authorised staging/recovery); plan-flip and index-units deliverables left explicitly OPEN; never-reset claim qualified to database-wide only; Perth/UTC boundary made explicit; four MD040 fences labelled. Supersedes the c3ca68fa record, whose checks cell compressed the gate output.", - "checks": "verify:pr-local decisive line — \"PR-local verification summary: - completed: check:runtime, check:installed-lock-parity, format:changed, sitemap:check, docs:check-index, docs:check-inventory, docs:check-scripts, docs:check-links, check:branch-review-ledger, check:outstanding-issues, check:ledger-write-discipline / - failed: (none) / - not reached: (none)\"; format (whole tree, committed)" + "checks": "verify:pr-local decisive line \u2014 \"PR-local verification summary: - completed: check:runtime, check:installed-lock-parity, format:changed, sitemap:check, docs:check-index, docs:check-inventory, docs:check-scripts, docs:check-links, check:branch-review-ledger, check:outstanding-issues, check:ledger-write-discipline / - failed: (none) / - not reached: (none)\"; format (whole tree, committed)" }, { "date": "2026-08-21", @@ -5498,8 +5497,8 @@ "ref": "claude/phase-5-closeout", "head": "c3ca68fa7f13e2d7ae6c4c96ccfcafb67a59135a", "scope": "Phase 5 close-out: measurement baselines, staging parity, D4 documentation correction (#316) (supersedes 2026-08-21)", - "outcome": "Supersedes the 2026-08-21 record for the same head. No finding changed: the review outcome stands as self-review with no blocking findings. This record exists solely to satisfy the AGENTS.md rule that evidence is never compressed — the prior record summarised verify:pr-local as `(11/11, failed: none)`, which paraphrases rather than pastes the gate's decisive line. Raised by CodeRabbit on PR #2250 (comment 3833079990) and accepted. Records are immutable and content-addressed, so the correction is made by appending this superseding record rather than editing the original, per the review-ledger contract.", - "checks": "verify:pr-local — decisive output verbatim: `- completed: check:runtime, check:installed-lock-parity, format:changed, sitemap:check, docs:check-index, docs:check-inventory, docs:check-scripts, docs:check-links, check:branch-review-ledger, check:outstanding-issues, check:ledger-write-discipline` / `- failed: (none)` / `- not reached: (none)`. check:production-readiness — `READY: no blocking production-readiness failures.` with `PASS (9)` and `Project: Clinical KB Database (sjrfecxgysukkwxsowpy)`. check:ledger-write-discipline — `Ledger write discipline passed for 70a050752f97..HEAD.` check:outstanding-issues — `Outstanding-issues guard passed: 423 rows (67 open, 356 archived)`. format — whole tree via `npm run format`, result committed before push. live-drift run 32514326022 (workflow_dispatch on main) — `No unexpected schema drift between live and supabase/schema.sql.` / `Remote migration versions: 211 (read via rpc)` / `Remote-only (Preview blockers): 0`; every step success." + "outcome": "Supersedes the 2026-08-21 record for the same head. No finding changed: the review outcome stands as self-review with no blocking findings. This record exists solely to satisfy the AGENTS.md rule that evidence is never compressed \u2014 the prior record summarised verify:pr-local as `(11/11, failed: none)`, which paraphrases rather than pastes the gate's decisive line. Raised by CodeRabbit on PR #2250 (comment 3833079990) and accepted. Records are immutable and content-addressed, so the correction is made by appending this superseding record rather than editing the original, per the review-ledger contract.", + "checks": "verify:pr-local \u2014 decisive output verbatim: `- completed: check:runtime, check:installed-lock-parity, format:changed, sitemap:check, docs:check-index, docs:check-inventory, docs:check-scripts, docs:check-links, check:branch-review-ledger, check:outstanding-issues, check:ledger-write-discipline` / `- failed: (none)` / `- not reached: (none)`. check:production-readiness \u2014 `READY: no blocking production-readiness failures.` with `PASS (9)` and `Project: Clinical KB Database (sjrfecxgysukkwxsowpy)`. check:ledger-write-discipline \u2014 `Ledger write discipline passed for 70a050752f97..HEAD.` check:outstanding-issues \u2014 `Outstanding-issues guard passed: 423 rows (67 open, 356 archived)`. format \u2014 whole tree via `npm run format`, result committed before push. live-drift run 32514326022 (workflow_dispatch on main) \u2014 `No unexpected schema drift between live and supabase/schema.sql.` / `Remote migration versions: 211 (read via rpc)` / `Remote-only (Preview blockers): 0`; every step success." }, { "date": "2026-08-21", @@ -5514,15 +5513,15 @@ "ref": "claude/shadow-runbook-operator-answers", "head": "1fe3c60c94822f61a60e5b61858114274fb8b340", "scope": "docs(worker): answer two of the four B4 operator unknowns from measured evidence (#2228)", - "outcome": "Backfilled record — PR #2228 merged 2026-08-21 (squash 1fe3c60c94822f61a60e5b61858114274fb8b340) with no review record captured at the time. Diff inspected post hoc: docs/worker-deploy-runbook.md updated with measured Railway variable-change and memory-headroom evidence (read-only lookups only, no mutation), plus a one-line worker/main.ts startup log-message correction (rollback now states set-then-deploy, no behaviour change) and one queued issues:update inbox request. classifyPullRequestFiles clinicalRisk:false; shadow extraction remains default-off everywhere. Approved by content.", - "checks": "PR-reported: npm run docs:check-links passed (2063 references resolve); Prettier clean on both changed files; CI static-pr required checks green (merged). verify:pr-local full and provider-backed gates explicitly not run per PR body (docs/log-message scope). Not independently re-run in this session — docs-truth backfill only." + "outcome": "Backfilled record \u2014 PR #2228 merged 2026-08-21 (squash 1fe3c60c94822f61a60e5b61858114274fb8b340) with no review record captured at the time. Diff inspected post hoc: docs/worker-deploy-runbook.md updated with measured Railway variable-change and memory-headroom evidence (read-only lookups only, no mutation), plus a one-line worker/main.ts startup log-message correction (rollback now states set-then-deploy, no behaviour change) and one queued issues:update inbox request. classifyPullRequestFiles clinicalRisk:false; shadow extraction remains default-off everywhere. Approved by content.", + "checks": "PR-reported: npm run docs:check-links passed (2063 references resolve); Prettier clean on both changed files; CI static-pr required checks green (merged). verify:pr-local full and provider-backed gates explicitly not run per PR body (docs/log-message scope). Not independently re-run in this session \u2014 docs-truth backfill only." }, { "date": "2026-08-21", "ref": "claude/specifiers-dead-exports", "head": "569c8fe11192f29728bf9e436e52bd10270f4640", "scope": "src/lib/specifiers-content.ts dead-export removal + outstanding-issues inbox request", - "outcome": "Approved — 9 deleted lines of unreferenced code, no behaviour change; AGENTS.md context-load finding filed as inbox request", + "outcome": "Approved \u2014 9 deleted lines of unreferenced code, no behaviour change; AGENTS.md context-load finding filed as inbox request", "checks": "typecheck exit 0; test:focused src/lib/specifiers-content.ts 2 files / 60 tests passed; prettier --check clean; verify:pr-local NOT run (worktree removed mid-session, no node_modules)" }, { @@ -5577,7 +5576,7 @@ "date": "2026-08-20", "ref": "claude/docling-shadow-extraction-runbook-942862", "head": "47deb7c42e398c39c2337b5e1cd6a5529afc9e40", - "scope": "packet B4 docling shadow extraction Gate F operator runbook (docs only) — post-review pass", + "scope": "packet B4 docling shadow extraction Gate F operator runbook (docs only) \u2014 post-review pass", "outcome": "two-codex-P2-findings-verified-against-code-and-fixed;search-delay-claim-was-wrong-status-set-at-commit;cohort-widening-needs-reindex-stated;two-coderabbit-nits-on-queued-request-fixed;coderabbit-ledger-entry-finding-rejected-invented-scope", "checks": "check:outstanding-issues:pass;prettier:clean;code-verified:commit_document_index_generation-sets-status-before-shadow" }, @@ -5602,7 +5601,7 @@ "ref": "claude/settings-portability-b38ea3", "head": "411ed4c9a92b8d6060d55f696b1fd66f4ede42c5", "scope": "Move project-specific autoMode allow/soft_deny/environment block from user settings to .claude/settings.json", - "outcome": "Clean — verbatim move, no behaviour change intended; 41 added lines, no removals", + "outcome": "Clean \u2014 verbatim move, no behaviour change intended; 41 added lines, no removals", "checks": "tests/claude-code-settings.test.ts + tests/session-start-hook.test.ts (2 files, 100 tests passed); prettier clean; pr-policy risk all false" }, { @@ -5641,17 +5640,17 @@ "date": "2026-08-20", "ref": "PR #2199", "head": "175c641321e58089d452ed76718972b8d7f705ca", - "scope": "PR #2199 on-demand document search — Codex P2 review-comment resolution", - "outcome": "Fixed: the document-viewer visual-baseline target still declared .document-viewer-composer as a mask, but the composer is no longer rendered until Search document is pressed, and assertMaskSelectors fails loudly on a mask matching zero nodes — which classify-visual-baseline-outcome.mjs scores as a NON-drift failure, turning the advisory job hard red on every main push. Mask reduced to the sticky header, with the reasoning recorded in the target comment. Reviewed the rest of the diff: stale-response protection holds (closeDocumentSearch clears sourceSearch, whose effect cleanup aborts the in-flight controller before the reset run), focus restoration and Escape are covered by the Chromium journeys.", - "checks": "npm run verify:pr-local: check:runtime, check:installed-lock-parity, format:changed, lint, typecheck all passed; npm run test 692/693 files, 7592 passed, 4 skipped, 1 failed — tests/guard-push.test.ts 'inFlightCiGuard formats actionable blocked message', byte-identical to origin/main and failing only because gh is absent in this container so inFlightCiGuard fails open before the injected runFetcher is used; CI Unit coverage passed on this head. Browser proof delegated to CI Production UI: local Playwright pins chromium 1234, image ships 1194 (#255)." + "scope": "PR #2199 on-demand document search \u2014 Codex P2 review-comment resolution", + "outcome": "Fixed: the document-viewer visual-baseline target still declared .document-viewer-composer as a mask, but the composer is no longer rendered until Search document is pressed, and assertMaskSelectors fails loudly on a mask matching zero nodes \u2014 which classify-visual-baseline-outcome.mjs scores as a NON-drift failure, turning the advisory job hard red on every main push. Mask reduced to the sticky header, with the reasoning recorded in the target comment. Reviewed the rest of the diff: stale-response protection holds (closeDocumentSearch clears sourceSearch, whose effect cleanup aborts the in-flight controller before the reset run), focus restoration and Escape are covered by the Chromium journeys.", + "checks": "npm run verify:pr-local: check:runtime, check:installed-lock-parity, format:changed, lint, typecheck all passed; npm run test 692/693 files, 7592 passed, 4 skipped, 1 failed \u2014 tests/guard-push.test.ts 'inFlightCiGuard formats actionable blocked message', byte-identical to origin/main and failing only because gh is absent in this container so inFlightCiGuard fails open before the injected runFetcher is used; CI Unit coverage passed on this head. Browser proof delegated to CI Production UI: local Playwright pins chromium 1234, image ships 1194 (#255)." }, { "date": "2026-08-20", "ref": "PR #2201", "head": "44d3cbb41aae5f1b7707d529347ee12dcc0cc44e", - "scope": "PR #2201 drift alignment window record — Codex P1 review-comment resolution", + "scope": "PR #2201 drift alignment window record \u2014 Codex P1 review-comment resolution", "outcome": "Fixed: the status board's active 'Next dispatches' line, the D4 owner-decision entry, the 2026-08-19 'Resolved' paragraph and the pre-window forensics section still instructed coordinators that D4 is OFF and each migration needs its own db push, contradicting the same PR's finding that D4 is unresolved. All four now say to treat a merge as a production deployment until the dashboard toggle is re-verified. Docs only; no code, migration or fixture touched.", - "checks": "npm run verify:pr-local (docs scope): check:runtime, check:installed-lock-parity, format:changed, sitemap:check, docs:check-index/inventory/scripts/links, check:branch-review-ledger, check:outstanding-issues, check:ledger-write-discipline — all completed, none failed" + "checks": "npm run verify:pr-local (docs scope): check:runtime, check:installed-lock-parity, format:changed, sitemap:check, docs:check-index/inventory/scripts/links, check:branch-review-ledger, check:outstanding-issues, check:ledger-write-discipline \u2014 all completed, none failed" }, { "date": "2026-08-19", @@ -5706,7 +5705,7 @@ "ref": "2129", "head": "eb9cb7481674c436464b0a81b560c3c79cc93501", "scope": "RAG eval scorer: readability metric split (fragmentation vs v19-derived length bound), eval_config_version v1->v2, HANDOVER S3 row", - "outcome": "Approved — evaluation scorer only; no retrieval/ranking/selection/prompt change; RAG impact declared as no behaviour change; pr-policy evaluatePullRequestPolicy ok:true with 7/7 governance items", + "outcome": "Approved \u2014 evaluation scorer only; no retrieval/ranking/selection/prompt change; RAG impact declared as no behaviour change; pr-policy evaluatePullRequestPolicy ok:true with 7/7 governance items", "checks": "verify:pr-local heavy scope failed:(none) not-reached:(none) incl lint+typecheck+full unit suite+build; eval:rag:offline 26 suites/623 tests; check:rag:fixtures 36 golden/26 suites; eval:rag:adversarial:offline 24 cases/8 categories/6 canaries + 25 tests, 3 KNOWN_DIVERGENCES still pinned; vitest tests/rag-eval-cases.test.ts 32 passed (27+5 new, mutation-checked)" }, { @@ -5722,7 +5721,7 @@ "ref": "claude/bundle-budget-production-baseline", "head": "f2cb4ec2ce11bb29444c9aca3c0572c603d48e5e", "scope": "bundle-budget.json production baseline refresh + measurement evidence doc + outstanding-issues request", - "outcome": "Approved — investigated before refreshing: main's +8.03% is diffuse feature growth across 52 of 101 routes with no regression signature and an unchanged lockfile; production baseline moved to the measured 1518033 bytes, route/mockups budgets and tolerances left untouched", + "outcome": "Approved \u2014 investigated before refreshing: main's +8.03% is diffuse feature growth across 52 of 101 routes with no regression signature and an unchanged lockfile; production baseline moved to the measured 1518033 bytes, route/mockups budgets and tolerances left untouched", "checks": "two full builds (main 9d832452d and baseline ca788d41) with .next removed each time; baseline reproduced to within 32 bytes of the recorded value; check:bundle-budget passes at the new baseline with all five route budgets and mockups within tolerance; tests/bundle-budget.test.ts 33 passed; outstanding-issues + ledger-write-discipline + docs link guards passed; format clean. Full unit suite, lint and typecheck not run: the diff is one JSON baseline value plus documentation and an inbox request, with no source change and no plausible compile or behaviour path" }, { @@ -5769,7 +5768,7 @@ "date": "2026-08-18", "ref": "claude/clinical-kb-prod-migration-db4aab", "head": "213226eb43f0b9b4dd096b12da3247458212493e", - "scope": "docs/audit/live-drift-forensics-2026-08.md §3.7 — production window pre-flight found the five 20260818 migrations already applied by the Supabase GitHub integration; db push not run; read-only verification recorded", + "scope": "docs/audit/live-drift-forensics-2026-08.md \u00a73.7 \u2014 production window pre-flight found the five 20260818 migrations already applied by the Supabase GitHub integration; db push not run; read-only verification recorded", "outcome": "docs-only; no production writes; findings recorded for coordinator (integration auto-applies merged migrations)", "checks": "verify:pr-local docs route (11 checks, failed: none); supabase migration list; four read-only db queries; live-drift run 32131517648 read" }, @@ -5818,7 +5817,7 @@ "ref": "claude/db-phase3-staging-proof-bodies", "head": "b5d228ad5ada7bbb82624ab0573894974f3aa232", "scope": "db remediation Phase 3 follow-up, final: 20260818113000 applied to staging, 111000/112000 history text refreshed, staging drift = 1 residual (trgm idx); #316 final update (PR #2111)", - "outcome": "Reviewed and handed off; staging proof complete — zero function mismatches, zero never-created objects, zero table mismatches, single residual document_chunks_content_trgm_idx (Phase 4.4); production window list unchanged", + "outcome": "Reviewed and handed off; staging proof complete \u2014 zero function mismatches, zero never-created objects, zero table mismatches, single residual document_chunks_content_trgm_idx (Phase 4.4); production window list unchanged", "checks": "staging def_hash for the three functions equal manifest/live; four history rows md5 = repo; check:outstanding-issues passed; docs:check-links passed; earlier gates on this branch unchanged" }, { @@ -5865,7 +5864,7 @@ "date": "2026-08-18", "ref": "claude/db-remediation-phase-1-2-19e4de", "head": "8329d0f02ff1394a65cea6946b786030549563c1", - "scope": "docs-only: Phase 1.2 RPC divergence dossier (docs/audit/live-drift-forensics-2026-08.md §1.2) + one #316 inbox update; PR #2087", + "scope": "docs-only: Phase 1.2 RPC divergence dossier (docs/audit/live-drift-forensics-2026-08.md \u00a71.2) + one #316 inbox update; PR #2087", "outcome": "self-review complete: all ten match_* def_hash mismatches classified attribute-only (SET work_mem; 4 mirror-stale, 6 live-ahead), zero repo-ahead, zero UNCLASSIFIED; read-only connector session, no RPC/migration/RAG code changed", "checks": "verify:pr-local (docs scope) failed:(none); docs:check-links 1826 resolve; check:outstanding-issues 348 rows guard passed; ledger-write-discipline passed; format committed" }, @@ -5882,7 +5881,7 @@ "ref": "claude/db-remediation-phase4-indexes-a1661a", "head": "5d3dca4dd7a0593a35e6d639144092dee6609256", "scope": "Phase 4 index restoration: 20 concurrent index builds + 2 concurrent drops on production, 3 fail-fast guard migrations, search_schema_health required_indexes 22->30, schema.sql mirror, regenerated drift manifest, staging parity, forensics evidence", - "outcome": "PASS — 20/20 indexes rebuilt indisvalid+indisready with canonical definitions, 2 orphans dropped per the repo chain, live-drift 32171070287 shows missing_live 20->0 and unexpected_live 2->0, staging drift green (was 19). Two escalations recorded not absorbed: PITR is not enabled on production, and no migration_history allowlist entry was earned (empty intersection with the 15 no-statements versions)", + "outcome": "PASS \u2014 20/20 indexes rebuilt indisvalid+indisready with canonical definitions, 2 orphans dropped per the repo chain, live-drift 32171070287 shows missing_live 20->0 and unexpected_live 2->0, staging drift green (was 19). Two escalations recorded not absorbed: PITR is not enabled on production, and no migration_history allowlist entry was earned (empty intersection with the 15 no-statements versions)", "checks": "check:migration-role; vitest supabase-schema + search-health-index-coverage + migration-history-guards + drift-detection + migration-history-placeholders + hosted-migration-role-guard (6 files, 109 tests); drift:manifest; check:rag:fixtures (36 golden cases); check:medication-interactions; check:medication-lexicon-report; verify:pr-local all stages pass except two load-induced timeouts (codex-cloud-setup, document-viewer-page-virtualization) that pass in isolation and are unrelated to this diff" }, { @@ -5923,7 +5922,7 @@ "head": "189df34d69c01fe08f17df5e49dc0cf2ca37d9c6", "scope": "Run PR sweep: CI fix + threads + drift", "outcome": "Before: all required checks already green (PR required success), 0 unresolved review threads, 3 bot-only PR comments (Codex usage limit, Supabase no-op, CodeRabbit rate limit) needing no action. Branch was behind main (mergeable_state: behind). Action: synced via GitHub update-branch API (clean merge, no conflicts) -> new head 189df34d69c01fe08f17df5e49dc0cf2ca37d9c6. After: fresh CI running on synced head, no code changes made, no threads to resolve.", - "checks": "No local gates run — PR already had npm run lint/typecheck/test/verify:ui results in its own description and no code was touched by this sweep; only a GitHub-side branch sync was performed. No provider-backed checks run." + "checks": "No local gates run \u2014 PR already had npm run lint/typecheck/test/verify:ui results in its own description and no code was touched by this sweep; only a GitHub-side branch sync was performed. No provider-backed checks run." }, { "date": "2026-08-18", @@ -5953,8 +5952,8 @@ "date": "2026-08-18", "ref": "claude/eval-canary-protocol-docs-01bb49", "head": "3e9905d0ac9d88f22dc88d41639399ae69237cf0", - "scope": "docs/rag-behaviour/safeguards.md, docs/rag-improvement/README.md — eval-canary pair protocol trigger mechanics and bisection lessons (ledger #TYJ0XP)", - "outcome": "approved — docs-only, no code/behaviour change", + "scope": "docs/rag-behaviour/safeguards.md, docs/rag-improvement/README.md \u2014 eval-canary pair protocol trigger mechanics and bisection lessons (ledger #TYJ0XP)", + "outcome": "approved \u2014 docs-only, no code/behaviour change", "checks": "verify:pr-local (docs-scoped: format:changed, sitemap:check, docs:check-index, docs:check-inventory, docs:check-scripts, docs:check-links, check:branch-review-ledger, check:outstanding-issues, check:ledger-write-discipline) all passed" }, { @@ -6001,7 +6000,7 @@ "date": "2026-08-18", "ref": "claude/header-redesign-mockups-3ms5kn", "head": "8083a20d6a3496ed154b927157bd621735886795", - "scope": "Dictionary Browse header round two — letter dropdown + Abbreviations in Filters (design scratch)", + "scope": "Dictionary Browse header round two \u2014 letter dropdown + Abbreviations in Filters (design scratch)", "outcome": "approved", "checks": "verify:pr-local all 18 steps completed / none failed, check:bundle-budget within tolerance, Chromium dark+light screenshot review" }, @@ -6027,7 +6026,7 @@ "head": "33ec22afd7b23dfc89fdf836fc80cc4a97c7a065", "scope": "remove caveat footer from every mode home", "outcome": "self-review clean; all mode-home caveat footers removed, dead reserve/props/helper deleted", - "checks": "verify:pr-local pass on merged head (673 files / 7281 tests, build, lint, typecheck, offline RAG evals); verify:ui not run — playwright chromium 1234 vs installed 1194 (#255)" + "checks": "verify:pr-local pass on merged head (673 files / 7281 tests, build, lint, typecheck, offline RAG evals); verify:ui not run \u2014 playwright chromium 1234 vs installed 1194 (#255)" }, { "date": "2026-08-18", @@ -6035,22 +6034,22 @@ "head": "40b92d2d6f41d0f9fadc8c4840737ffae1f34c5d", "scope": "mode home footers + dictionary command surface", "outcome": "self-review clean; footers removed on user instruction, dictionary example ticket added", - "checks": "verify:pr-local pass (673 files / 7276 tests); verify:ui not run — playwright chromium 1234 vs installed 1194 (#255), delegated to CI" + "checks": "verify:pr-local pass (673 files / 7276 tests); verify:ui not run \u2014 playwright chromium 1234 vs installed 1194 (#255), delegated to CI" }, { "date": "2026-08-18", "ref": "claude/home-pages-cleanup-qeh5fr (PR #2139)", "head": "49875287ead7a15069224174d68f57b44c220e3d", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Branch already current with origin/main (base sha a9552eb4 == main tip; PR includes its own 'Merge branch main' commit) — no drift/conflict, so the #2112 shared-mode-home/composer overlap did not materialize and no merge or resolution was needed. 0 unresolved review threads (only bot usage-limit/skip comments present, non-actionable). All completed required CI checks green as of last observation (Static PR checks, Build, Production UI critical, Safety and config checks, Change scope, Unit coverage all success; zero failures across 25 check runs); Production UI (1)/(2)/(3) and Lighthouse budget were still in_progress after ~25 min observation window with no failure signal — left running, no code changes needed or made. No commits pushed this sweep.", + "outcome": "Branch already current with origin/main (base sha a9552eb4 == main tip; PR includes its own 'Merge branch main' commit) \u2014 no drift/conflict, so the #2112 shared-mode-home/composer overlap did not materialize and no merge or resolution was needed. 0 unresolved review threads (only bot usage-limit/skip comments present, non-actionable). All completed required CI checks green as of last observation (Static PR checks, Build, Production UI critical, Safety and config checks, Change scope, Unit coverage all success; zero failures across 25 check runs); Production UI (1)/(2)/(3) and Lighthouse budget were still in_progress after ~25 min observation window with no failure signal \u2014 left running, no code changes needed or made. No commits pushed this sweep.", "checks": "GitHub check-runs API polled for HEAD 4987528 (twice, ~5 min apart): no failing required job observed. No local gates run (nothing to fix/verify). No provider-backed checks run." }, { "date": "2026-08-18", "ref": "claude/issues-capture-h5a-residual-ulid-lookup", "head": "5c9b69a7e6bd2a3f2a1f5abac1a19a71a1cd153b", - "scope": "two immutable outstanding-issues inbox requests (P3 issue: H5a residual after G1; P3 rec: ledger writer id-scheme test gap) — no product code", - "outcome": "approved — inbox-request files only; canonical ledger untouched, applied later by issues:reconcile", + "scope": "two immutable outstanding-issues inbox requests (P3 issue: H5a residual after G1; P3 rec: ledger writer id-scheme test gap) \u2014 no product code", + "outcome": "approved \u2014 inbox-request files only; canonical ledger untouched, applied later by issues:reconcile", "checks": "verify:pr-local light docs scope, all 11 selected stages green (format:changed, docs link/index/inventory/scripts, branch-review-ledger, outstanding-issues, ledger-write-discipline); build/test correctly skipped as non-build-affecting; request JSON content verified incl. escaping" }, { @@ -6058,7 +6057,7 @@ "ref": "claude/issues-reconcile-2026-08-18-evening", "head": "79b4d8df0c37a580935904bdeed04e14aa23b0d8", "scope": "issues ledger reconciliation (88 queued inbox requests: database-remediation set + PR #2105 done resolutions)", - "outcome": "clean — reconciler applied all 88 queued requests with 10 cancellation decisions, refused none; no request adjudicated, edited or deleted by hand; diff is 1 canonical file + 88 renames", + "outcome": "clean \u2014 reconciler applied all 88 queued requests with 10 cancellation decisions, refused none; no request adjudicated, edited or deleted by hand; diff is 1 canonical file + 88 renames", "checks": "verify:pr-local (11/11 gates, 0 failed, 0 unreached); check:outstanding-issues (365 rows, 48 open, 0 pending / 339 applied); check:ledger-write-discipline (ce702ba68c12..HEAD); docs:check-links (1901 refs); format (whole tree, unchanged)" }, { @@ -6066,7 +6065,7 @@ "ref": "claude/issues-reconcile-2026-08-18-evening", "head": "ed19e1435049e284088c0e8d042465004390c4de", "scope": "prlanded", - "outcome": "clean — PR #2120 merged as squash ed19e143; two-dot content diff against branch tip 0771039f is empty, all 90 files landed including the review record, no orphaned late commit from the auto-merge race", + "outcome": "clean \u2014 PR #2120 merged as squash ed19e143; two-dot content diff against branch tip 0771039f is empty, all 90 files landed including the review record, no orphaned late commit from the auto-merge race", "checks": "git diff --stat ed19e143 0771039f (empty); ledger record 6b6d74c4 present on main; check:outstanding-issues on main 4575cf57 (365 rows, 48 open, 0 pending / 339 applied)" }, { @@ -6074,7 +6073,7 @@ "ref": "claude/issues-reconcile-2026-08-19", "head": "b393cdd530e81d6bfbdc15c495d870b57c73f01b", "scope": "Serialized reconcile of 21 queued outstanding-issues inbox requests (PR #2168)", - "outcome": "approved — documentation-only; canonical diff equals the recorded reconciliation transaction", + "outcome": "approved \u2014 documentation-only; canonical diff equals the recorded reconciliation transaction", "checks": "check:outstanding-issues passed (392 rows, 57 open); check:ledger-write-discipline passed b400b138f8c1..HEAD; format:changed clean; inbox 0 pending / 391 applied" }, { @@ -6090,7 +6089,7 @@ "ref": "claude/ledger-issues-reconcile-945d0a", "head": "dd47bbe7e402e203e3d094127d1955ea0b650d4f", "scope": "docs/outstanding-issues-inbox ledger queueing", - "outcome": "PR #2130: queued 7 immutable ledger requests (done #DP6M3G, update #231 re-grade P1->P2, done #BTVMVK/#ND10QT as duplicates, 3 new P3 recs). No canonical ledger edit — reconciliation deferred to a dedicated follow-up PR because check:ledger-write-discipline cannot pass a same-PR add+reconcile.", + "outcome": "PR #2130: queued 7 immutable ledger requests (done #DP6M3G, update #231 re-grade P1->P2, done #BTVMVK/#ND10QT as duplicates, 3 new P3 recs). No canonical ledger edit \u2014 reconciliation deferred to a dedicated follow-up PR because check:ledger-write-discipline cannot pass a same-PR add+reconcile.", "checks": "check:outstanding-issues passed (16 pending, 339 applied); check:ledger-write-discipline passed for 53438ae4392a..HEAD; prettier --check passed" }, { @@ -6115,7 +6114,7 @@ "head": "1cffafbc172fc22625aa3cba62d5d685b7720f25", "scope": "Run PR sweep: CI fix + threads + drift", "outcome": "Before: PR mergeability/PR policy transiently failed (self-healed on retry, no real conflict); Production UI (3) failed 3 Chromium specs (ui-specifiers.spec.ts mobile composer, 2x ui-tools.spec.ts stale /differentials and /services route assertions) caused by this PR's own consolidated-mode-home routing change, not main drift. Fixed: updated the 3 stale test assertions to match the new /differentials/search, /?mode=services, and /specifiers/search routes already established elsewhere in this PR's own diff. After: fixes pushed, fresh CI re-running. Still blocked on a blank Clinical Governance Preflight in the PR body (human-owned, not auto-fillable) and a real Lighthouse TBT regression pattern matching known main-wide drift from a prior merge.", - "checks": "npx tsc --noEmit (clean), npx eslint tests/ui-tools.spec.ts tests/ui-specifiers.spec.ts (clean), npx prettier --write (no changes needed); Playwright not run locally (browser revision mismatch, chromium-1194 vs CI's 1234) — delegated to CI Production UI. No provider-backed checks run." + "checks": "npx tsc --noEmit (clean), npx eslint tests/ui-tools.spec.ts tests/ui-specifiers.spec.ts (clean), npx prettier --write (no changes needed); Playwright not run locally (browser revision mismatch, chromium-1194 vs CI's 1234) \u2014 delegated to CI Production UI. No provider-backed checks run." }, { "date": "2026-08-18", @@ -6154,14 +6153,14 @@ "ref": "claude/post-reconcile-review-2026-08-18", "head": "cd5fe0f4026c43af78ab0f80f78d661e88faedc0", "scope": "retire stale visual-register instructions in issues/ledger skills + AGENTS.md; queue reconcile-serialization follow-up", - "outcome": "clean — three instruction surfaces no longer point at the ISSUES-LIST.html artifact #338 retired; check:skills regression introduced and fixed within the diff (220-word canonical budget)", + "outcome": "clean \u2014 three instruction surfaces no longer point at the ISSUES-LIST.html artifact #338 retired; check:skills regression introduced and fixed within the diff (220-word canonical budget)", "checks": "verify:pr-local (22/22 gates, 0 failed, 0 unreached); test:ci-workflows 325 passed; check:skills exit 0 (was 1 mid-change, baseline re-measured); format (whole tree)" }, { "date": "2026-08-18", "ref": "claude/rag-d4-reconcile-inbox", "head": "d1d75055396cff3ea15c6ef6c45d9363440b4175", - "scope": "issues:reconcile (17 requests) + HANDOVER G1/S1d/S1c/S2 rows + COORDINATION §7 (docs-only)", + "scope": "issues:reconcile (17 requests) + HANDOVER G1/S1d/S1c/S2 rows + COORDINATION \u00a77 (docs-only)", "outcome": "single fresh-base reconcile; 0 pending afterwards; G1/S1c/governance rows closed", "checks": "check:outstanding-issues 0 pending/234 applied; check:ledger-write-discipline passed 981d85de0301..HEAD; verify:pr-local docs scope" }, @@ -6186,7 +6185,7 @@ "ref": "claude/refresh-therapy-visual-baseline", "head": "3d74403292d3b340a01de24008d23ea91c71a755", "scope": "Refresh all six Linux visual baselines from hosted-CI artifact visual-baseline-32189416778 (main @ 9b1e7248) plus provenance and regenerated adoption manifest", - "outcome": "Approved — all six actual renders opened and reviewed before adopting; no source changed; provenance reviewerType:human is overstated for an automated pass and is flagged in the PR for owner confirmation", + "outcome": "Approved \u2014 all six actual renders opened and reviewed before adopting; no source changed; provenance reviewerType:human is overstated for an automated pass and is flagged in the PR for owner confirmation", "checks": "adopt-visual-baselines --write (6/6 replaced, capture kind refresh); check:design-system-adoption (54 components, 82 roots); vitest tests/adopt-visual-baselines.test.ts 4 passed; prettier --check provenance.json clean. No broader gate: PNG/JSON-only diff with no changed source failure path" }, { @@ -6226,8 +6225,8 @@ "ref": "claude/schema-work-mem-codify-6200f1", "head": "3e73b8bd43a689b9c6f8c83b9cbfddede0bb231b", "scope": "supabase migrations, schema.sql (PR #2106 Phase 3 codification review)", - "outcome": "Reviewed via supabase-schema-guardian: signatures, ordering, idempotency, schema.sql/migration consistency, RAG-impact claim, and guard-migration contract all verified correct against the diff. Fixed one concern (forensics runbook offered mark-applied-by-CLI as equal to db push for three migrations shipping no validation guard — narrowed to require db push and forbid migration repair) and added SET LOCAL lock_timeout/statement_timeout to the two migrations taking ACCESS EXCLUSIVE locks on hot tables (documents, ingestion_jobs, document_chunks), matching the 20260804110240 pattern. No schema.sql or function-body change from this review; no live Supabase access.", - "checks": "check:migration-role passed; vitest tests/migration-history-guards+hosted-migration-role-guard+supabase-schema+drift-detection+search-health-index-coverage+guard-push.test.ts 141/141 passed; prettier --check on the edited doc passed; npm run format whole-tree no-op; drift:manifest Docker replay not run (Docker daemon unavailable in this sandbox) — CI Migration replay + Unit coverage + Static PR checks + PR required all green on the prior head and these edits are additive SQL/prose only" + "outcome": "Reviewed via supabase-schema-guardian: signatures, ordering, idempotency, schema.sql/migration consistency, RAG-impact claim, and guard-migration contract all verified correct against the diff. Fixed one concern (forensics runbook offered mark-applied-by-CLI as equal to db push for three migrations shipping no validation guard \u2014 narrowed to require db push and forbid migration repair) and added SET LOCAL lock_timeout/statement_timeout to the two migrations taking ACCESS EXCLUSIVE locks on hot tables (documents, ingestion_jobs, document_chunks), matching the 20260804110240 pattern. No schema.sql or function-body change from this review; no live Supabase access.", + "checks": "check:migration-role passed; vitest tests/migration-history-guards+hosted-migration-role-guard+supabase-schema+drift-detection+search-health-index-coverage+guard-push.test.ts 141/141 passed; prettier --check on the edited doc passed; npm run format whole-tree no-op; drift:manifest Docker replay not run (Docker daemon unavailable in this sandbox) \u2014 CI Migration replay + Unit coverage + Static PR checks + PR required all green on the prior head and these edits are additive SQL/prose only" }, { "date": "2026-08-18", @@ -6242,7 +6241,7 @@ "ref": "claude/search-recovery-rail", "head": "7510216c672f293d26b8fdfe04a9ed3fd286b7f6", "scope": "SearchResultsEmptyState rail restyle + desktop tap floor restore (PR #2147)", - "outcome": "approved — presentation-only; no copy, testid, heading-level, live-region or handler change; band untouched", + "outcome": "approved \u2014 presentation-only; no copy, testid, heading-level, live-region or handler change; band untouched", "checks": "typecheck 0 errors; eslint+prettier+format:changed clean; 10 DOM files/168 tests passed; chromium ui-accessibility 16 passed; full verify:ui not completed (lock contention + host exit)" }, { @@ -6250,7 +6249,7 @@ "ref": "claude/services-navigation-removal-7bnknn", "head": "ba279bdd0b2fdc5d4dfa2c88dd30d57ee94be330", "scope": "src/components/services/services-navigator-page.tsx (referral progress stepper phone centering)", - "outcome": "PR #2103 opened — verify:pr-local complete (7091 tests, build, lint, typecheck, RAG fixtures, medication checks all passed)", + "outcome": "PR #2103 opened \u2014 verify:pr-local complete (7091 tests, build, lint, typecheck, RAG fixtures, medication checks all passed)", "checks": "verify:pr-local" }, { @@ -6266,7 +6265,7 @@ "ref": "claude/settings-development-section (PR #2109)", "head": "5bda0941ea2b257af23f569a25e7659bcebcdf40", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Before: Static PR checks failing (design-system-contract ratchet — legacyShadowAliases at settings-dialog.tsx increased 3 -> 4 via var(--shadow-soft) in the new Development section), 0 unresolved review threads, branch 1 commit behind main (clean merge-tree). After: synced origin/main into the branch via update_pull_request_branch (no conflicts, base now 5ae2bb6e), fixed the shadow-alias regression by switching to shadow-[var(--e2),var(--shadow-inset)] (same pattern as account-setup-dialog.tsx), pushed b1f9dac6..5bda0941. No review threads existed to action.", + "outcome": "Before: Static PR checks failing (design-system-contract ratchet \u2014 legacyShadowAliases at settings-dialog.tsx increased 3 -> 4 via var(--shadow-soft) in the new Development section), 0 unresolved review threads, branch 1 commit behind main (clean merge-tree). After: synced origin/main into the branch via update_pull_request_branch (no conflicts, base now 5ae2bb6e), fixed the shadow-alias regression by switching to shadow-[var(--e2),var(--shadow-inset)] (same pattern as account-setup-dialog.tsx), pushed b1f9dac6..5bda0941. No review threads existed to action.", "checks": "npm run check:design-system-contract -> 'Design-system contract passed'; node scripts/run-vitest.mjs run tests/settings-dialog-actions.dom.test.tsx tests/client-secret-surface.test.ts -> 'Test Files 2 passed (2) / Tests 13 passed (13)'; npx tsc -p tsconfig.typecheck.json --noEmit -> exit 0 no diagnostics; npx eslint settings-dialog.tsx -> exit 0; npx prettier --check settings-dialog.tsx -> 'All matched files use Prettier code style!'; no provider-backed checks run" }, { @@ -6274,31 +6273,31 @@ "ref": "claude/settings-development-section (PR #2141)", "head": "2e7325681c2fdb0909baba6709ca64bfe5f61692", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "No unresolved review threads (0 threads; only bot noise: Codex/CodeRabbit usage-limit notices, Supabase branching skip). Required CI (pr-required: changes/static-pr/safety/coverage/build/ui-critical/db-reset-verify) has never run on this head because mergeable_state is dirty and GitHub cannot build the merge ref (only pull_request_target PR-mergeability/PR-policy/GitGuardian ran). git merge-tree origin/main shows real content conflicts in src/components/clinical-dashboard/settings-dialog.tsx and tests/settings-dialog-actions.dom.test.tsx: this PR's first commit (34af56a6, feat(settings): add a gated Development section...) duplicates already-merged main commit bf85de98 (PR #2109, same title/feature, landed 2026-08-18 20:36 UTC, ~20 min after this PR opened) with only a cosmetic shadow-token diff. This is a semantically ambiguous product-history conflict (near-duplicate commit vs a since-merged PR), not a mechanical one (no lockfile/generated/adjacent-hunk fix applies) — per run-pr guardrails, skipped drift resolution rather than merge --abort/wholesale ours-theirs. No commits pushed, no branch state changed. Left for human: decide whether to drop/rebase the duplicate first commit (keeping only the second commit 2e732568 adding src/app/mockups/development/page.tsx) or close #2141 as superseded by #2109 — related to PR #2135 (Development mockup page) handled in parallel by another agent.", - "checks": "git merge-tree --write-tree origin/main origin/claude/settings-development-section (conflict detected, non-mutating); mcp__github__pull_request_read get/get_status/get_check_runs/get_review_comments/get_comments; npm run ledger:lookup (NOT REVIEWED at this head, confirmed pre-action). No provider-backed gates run. No local build/lint/test run — no code fix was attempted since the blocking issue is an unresolved product-history conflict, not a reproducible CI failure." + "outcome": "No unresolved review threads (0 threads; only bot noise: Codex/CodeRabbit usage-limit notices, Supabase branching skip). Required CI (pr-required: changes/static-pr/safety/coverage/build/ui-critical/db-reset-verify) has never run on this head because mergeable_state is dirty and GitHub cannot build the merge ref (only pull_request_target PR-mergeability/PR-policy/GitGuardian ran). git merge-tree origin/main shows real content conflicts in src/components/clinical-dashboard/settings-dialog.tsx and tests/settings-dialog-actions.dom.test.tsx: this PR's first commit (34af56a6, feat(settings): add a gated Development section...) duplicates already-merged main commit bf85de98 (PR #2109, same title/feature, landed 2026-08-18 20:36 UTC, ~20 min after this PR opened) with only a cosmetic shadow-token diff. This is a semantically ambiguous product-history conflict (near-duplicate commit vs a since-merged PR), not a mechanical one (no lockfile/generated/adjacent-hunk fix applies) \u2014 per run-pr guardrails, skipped drift resolution rather than merge --abort/wholesale ours-theirs. No commits pushed, no branch state changed. Left for human: decide whether to drop/rebase the duplicate first commit (keeping only the second commit 2e732568 adding src/app/mockups/development/page.tsx) or close #2141 as superseded by #2109 \u2014 related to PR #2135 (Development mockup page) handled in parallel by another agent.", + "checks": "git merge-tree --write-tree origin/main origin/claude/settings-development-section (conflict detected, non-mutating); mcp__github__pull_request_read get/get_status/get_check_runs/get_review_comments/get_comments; npm run ledger:lookup (NOT REVIEWED at this head, confirmed pre-action). No provider-backed gates run. No local build/lint/test run \u2014 no code fix was attempted since the blocking issue is an unresolved product-history conflict, not a reproducible CI failure." }, { "date": "2026-08-18", "ref": "claude/therapy-compass-convergence-2iufoh (PR #2131)", "head": "847ff291b55a69cff1029648754d316a79ca1bef", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "No drift (0 behind main, base sha matches origin/main exactly) and no CI fixes needed: all required checks green (PR required, Static PR checks, PR policy, PR mergeability, GitGuardian, Semgrep, Gitleaks all success; heavy jobs correctly skipped for doc-only scope). 1 unresolved review thread (CodeRabbit P3 nit: format / placeholders as code in the immutable record file) — replied declining the direct edit because the record filename is sha256(row) per reviewRecordPath() and check-branch-review-ledger.mjs asserts filename==hash(content), so hand-editing would desync the content-addressing invariant; left open for a human --supersede decision, not resolved.", - "checks": "mcp__github__pull_request_read get/get_status/get_check_runs/get_files/get_comments/get_review_comments (live); git fetch + git rev-list --left-right --count origin/main...origin/claude/therapy-compass-convergence-2iufoh (0 behind); no local gates run — no code change made, no CI fix required; no provider-backed checks run" + "outcome": "No drift (0 behind main, base sha matches origin/main exactly) and no CI fixes needed: all required checks green (PR required, Static PR checks, PR policy, PR mergeability, GitGuardian, Semgrep, Gitleaks all success; heavy jobs correctly skipped for doc-only scope). 1 unresolved review thread (CodeRabbit P3 nit: format / placeholders as code in the immutable record file) \u2014 replied declining the direct edit because the record filename is sha256(row) per reviewRecordPath() and check-branch-review-ledger.mjs asserts filename==hash(content), so hand-editing would desync the content-addressing invariant; left open for a human --supersede decision, not resolved.", + "checks": "mcp__github__pull_request_read get/get_status/get_check_runs/get_files/get_comments/get_review_comments (live); git fetch + git rev-list --left-right --count origin/main...origin/claude/therapy-compass-convergence-2iufoh (0 behind); no local gates run \u2014 no code change made, no CI fix required; no provider-backed checks run" }, { "date": "2026-08-18", "ref": "claude/therapy-mode-consistency-a466b0", "head": "092633eb7479b21796790a33b0ff7a3a7d4cf05c", "scope": "prlanded", - "outcome": "Landed correctly. PR #2122 squash-merged as 092633eb; verified by content, not ancestry: two-dot 'git diff --stat 092633eb 7733eb8c' is empty, so nothing was orphaned by the auto-merge race. The pre-merge sync of main into the branch was also proven clean — its tree hash equalled git merge-tree's automatic result exactly, so no hand resolution could have silently reverted content (the failure mode #324 describes). Branch reports 13 ahead of main, which is the squash artifact, not unlanded work. Remote head deleted by GitHub on merge; four inbox requests ride on main awaiting issues:reconcile.", - "checks": "git diff --stat empty; merge-tree hash equality on the pre-merge sync; post-merge verify:cheap green — Test Files 673 passed (673), Tests 7275 passed | 4 skipped (7279), Design-system contract passed (784 production files), hosted migration-role guard passed" + "outcome": "Landed correctly. PR #2122 squash-merged as 092633eb; verified by content, not ancestry: two-dot 'git diff --stat 092633eb 7733eb8c' is empty, so nothing was orphaned by the auto-merge race. The pre-merge sync of main into the branch was also proven clean \u2014 its tree hash equalled git merge-tree's automatic result exactly, so no hand resolution could have silently reverted content (the failure mode #324 describes). Branch reports 13 ahead of main, which is the squash artifact, not unlanded work. Remote head deleted by GitHub on merge; four inbox requests ride on main awaiting issues:reconcile.", + "checks": "git diff --stat empty; merge-tree hash equality on the pre-merge sync; post-merge verify:cheap green \u2014 Test Files 673 passed (673), Tests 7275 passed | 4 skipped (7279), Design-system contract passed (784 production files), hosted migration-role guard passed" }, { "date": "2026-08-18", "ref": "claude/therapy-mode-consistency-a466b0", "head": "244accbde60c5b39f9a91c7f2096053a2f2c5a65", "scope": "Therapy Compass shared-component convergence B3/C/D: control recipes to shared Button, 16 card surfaces to card-recipes cardSurface/heroCard, six page headers to shared PageHeader, plus two strengthened responsive-contract assertions", - "outcome": "Approved for review as PR #2122 — 19 button call sites converted with per-screen one-filled-command checks, all 16 card surfaces converged (compare table scroll frame deliberately excluded as a frame not a card), six of nine h1 converted (detail hero, patient-handout title and placeholder hero left; PageHeader renders a header element that print CSS hides unconditionally). therapyBtn retained: still the affordance for ~20 non-Button raw call sites. Ratchets fell, none rose.", + "outcome": "Approved for review as PR #2122 \u2014 19 button call sites converted with per-screen one-filled-command checks, all 16 card surfaces converged (compare table scroll frame deliberately excluded as a frame not a card), six of nine h1 converted (detail hero, patient-handout title and placeholder hero left; PageHeader renders a header element that print CSS hides unconditionally). therapyBtn retained: still the affordance for ~20 non-Button raw call sites. Ratchets fell, none rose.", "checks": "eslint clean; tsc --noEmit clean; verify:pr-local Test Files 673 passed (673), Tests 7274 passed | 4 skipped (7278); build re-run standalone exit 0 after BUILD_REFUSED_DEV_SERVER; check:bundle-budget all routes within tolerance; verify:ui 447 passed (20.4m) on Playwright-matched Chromium 1234; check:design-system-contract passed" }, { @@ -6306,7 +6305,7 @@ "ref": "claude/therapy-modes-visibility-bb37d2", "head": "9b4b3056b1f4ef7355e8947d6b210dee63de182e", "scope": "Therapy production visibility: remove devOnly gate, route-layout not-found gate and production review filter; add catalogue review notice + needsReviewCount; retire PLAYWRIGHT_OFFLINE_MODE bypass; update pinning contracts", - "outcome": "Approved — reachability now disclosed rather than gated; per-record reviewStatus badges retained on every surface; single-commit revert restores all three gates", + "outcome": "Approved \u2014 reachability now disclosed rather than gated; per-record reviewStatus badges retained on every surface; single-commit revert restores all three gates", "checks": "verify:pr-local (docs/ledger/lint/typecheck passed; test failed only on unrelated load-flaky tests/codex-cloud-setup.test.ts, which passes in isolation at HEAD and with the change); build from wiped .next compiled successfully with all 9 therapy routes; check:rag:fixtures, check:medication-interactions, check:medication-lexicon-report passed; focused therapy+route-reachability contracts 77 passed; eslint+tsc clean; dev-server route 200s. verify:ui not run - coordinator heavy lock held by another worktree" }, { @@ -6322,7 +6321,7 @@ "ref": "codex/caring-contact-linked-mockup", "head": "fde840e6cdddc823245f1c9f239a51aa1951f93c", "scope": "Caring Contact linked prototype: 13 mockup routes, 17 mockup components, docs/caring-contacts, 6 test files, playwright/package script registration, mockups bundle-budget baseline", - "outcome": "Approved for draft PR — mockup-only scope, no production route/API/library change; merged up to main and re-verified", + "outcome": "Approved for draft PR \u2014 mockup-only scope, no production route/API/library change; merged up to main and re-verified", "checks": "verify:pr-local (lint, typecheck, docs/ledger guards passed); vitest 7033 passed / 4 failed, all four cleared as pre-existing or full-suite contention (session-start-hook fails identically on untouched origin/main; other three pass in isolation); next build compiled; bundle-budget production within tolerance, mockups baseline refreshed 296.0->370.2 KiB; check:rag:fixtures 36 cases; medication interaction + lexicon checks passed; post-sync lint + typecheck exit 0" }, { @@ -6330,7 +6329,7 @@ "ref": "codex/chat-dictionary-ultimate-dictionary-ultimate", "head": "3a8271bd7a9aa13b2a323cd29e84f294de211690", "scope": "Dictionary mode: 8 production routes, 96-entry governed catalogue, shared search/filter lib, launcher/ModeNav/universal-search/tools-catalogue integration, design-system adoption manifests", - "outcome": "Approved for draft PR with one declared red gate — production bundle budget +10.5% (main alone is +7.8% of a 2026-08-13 baseline; this branch adds 33.9 KiB across 11 dictionary-exclusive chunks). Baseline deliberately not refreshed; decision left to review", + "outcome": "Approved for draft PR with one declared red gate \u2014 production bundle budget +10.5% (main alone is +7.8% of a 2026-08-13 baseline; this branch adds 33.9 KiB across 11 dictionary-exclusive chunks). Baseline deliberately not refreshed; decision left to review", "checks": "verify:pr-local (lint, typecheck, docs/ledger guards passed); vitest 6990 passed / 2 failed, both cleared (private-access-routes passes in isolation 145/145; session-start-hook fails identically on untouched origin/main); next build compiled; check:client-bundle-secrets passed; check:bundle-budget FAIL on production bucket (documented in PR body), routes and mockups within tolerance; check:rag:fixtures 36 cases; medication interaction + lexicon checks passed; post-sync lint + typecheck exit 0" }, { @@ -6346,8 +6345,8 @@ "ref": "codex/ward-management-design (PR #2140)", "head": "d7f5b76e29aa2ca489c3f3401f19bd18508e462f", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "No fix applied — branch history is unrelated to main (git merge-base/merge-tree fails: 'refusing to merge unrelated histories', root commits differ entirely). GitHub cannot build refs/pull/2140/merge, so pull_request (ci.yml/pr-required) never ran; only pull_request_target jobs ran (PR mergeability: failure — real merge conflict; PR policy: failure — Clinical Governance Preflight unchecked, 7/7 boxes empty in template). 0 unresolved review threads (only bot rate-limit/ignored notices). Left for human: branch needs re-basing/re-creation onto main or history investigation — out of scope for mechanical sweep; PR body also needs governance section completed by author, which this session may not edit.", - "checks": "git fetch/merge-base/merge-tree (local, offline); mcp__github__pull_request_read get/get_status/get_check_runs/get_review_comments/get_comments; mcp__github__actions_list + get_job_logs on both failing workflow runs. No provider-backed checks (build/test/eval) run — no code fix was possible or attempted." + "outcome": "No fix applied \u2014 branch history is unrelated to main (git merge-base/merge-tree fails: 'refusing to merge unrelated histories', root commits differ entirely). GitHub cannot build refs/pull/2140/merge, so pull_request (ci.yml/pr-required) never ran; only pull_request_target jobs ran (PR mergeability: failure \u2014 real merge conflict; PR policy: failure \u2014 Clinical Governance Preflight unchecked, 7/7 boxes empty in template). 0 unresolved review threads (only bot rate-limit/ignored notices). Left for human: branch needs re-basing/re-creation onto main or history investigation \u2014 out of scope for mechanical sweep; PR body also needs governance section completed by author, which this session may not edit.", + "checks": "git fetch/merge-base/merge-tree (local, offline); mcp__github__pull_request_read get/get_status/get_check_runs/get_review_comments/get_comments; mcp__github__actions_list + get_job_logs on both failing workflow runs. No provider-backed checks (build/test/eval) run \u2014 no code fix was possible or attempted." }, { "date": "2026-08-18", @@ -6370,7 +6369,7 @@ "ref": "dependabot/github_actions/github-actions-6d70da7aad (PR #2011)", "head": "bb5e4d1158639d678c75c8fd85f5e3fd608e2936", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Ledger throttle showed NOT REVIEWED at cda7ff21b. Found the substantive fix (claude-code-action pin v1.0.187->v1.0.193 allowlisted in scripts/github-action-pins.mjs) was already present at that head from a prior sweep commit 907ca970; checks were already green (Static PR checks/PR required/PR policy all success). Branch was 25 commits behind main; local merge tripped the pre-push ledger-write-discipline guard on the far-behind old remote tip (guardBaseForRange uses the branch's prior remote SHA for a fast-forward push, not mainMergeBase), so synced via authenticated GitHub update-branch API (human identity BigSimmo) instead of a local push, landing cleanly at bb5e4d115. Zero unresolved review threads (get_review_comments returned 0); the one PR comment is a stale 2026-08-17 ci-triage bot note superseded by the later fix commit, no reply needed. No conflicts, no code changes beyond the dependency-bump PR's own prior content. CI re-triggered on the new head and left running (not babysat) — Static PR checks/Semgrep/GitGuardian in_progress at handoff, PR mergeability and PR policy already green.", + "outcome": "Ledger throttle showed NOT REVIEWED at cda7ff21b. Found the substantive fix (claude-code-action pin v1.0.187->v1.0.193 allowlisted in scripts/github-action-pins.mjs) was already present at that head from a prior sweep commit 907ca970; checks were already green (Static PR checks/PR required/PR policy all success). Branch was 25 commits behind main; local merge tripped the pre-push ledger-write-discipline guard on the far-behind old remote tip (guardBaseForRange uses the branch's prior remote SHA for a fast-forward push, not mainMergeBase), so synced via authenticated GitHub update-branch API (human identity BigSimmo) instead of a local push, landing cleanly at bb5e4d115. Zero unresolved review threads (get_review_comments returned 0); the one PR comment is a stale 2026-08-17 ci-triage bot note superseded by the later fix commit, no reply needed. No conflicts, no code changes beyond the dependency-bump PR's own prior content. CI re-triggered on the new head and left running (not babysat) \u2014 Static PR checks/Semgrep/GitGuardian in_progress at handoff, PR mergeability and PR policy already green.", "checks": "npm run check:github-actions (pass), npm run check:ci-scope (pass), npm run check:pr-policy (pass); npm run check:ledger-write-discipline (pass, base=origin/main); local git merge-tree confirmed clean merge; no provider-backed checks run" }, { @@ -6450,7 +6449,7 @@ "ref": "gemini/therapy-compass-and-tooling-hardening (PR #2159)", "head": "f135f22cde36acbb3c9ab7d018565545708bb81c", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Before: real (git merge-tree confirmed) merge conflicts against origin/main in docs/launch-operator-runbook.md (stale search-health-index text vs the fix already merged via #2155) and docs/rag-evaluation.md (add/add — main independently gained the base doc while this branch extended it with a RAG Improvement Programme Board section; main's content was an exact prefix of this branch's version). Resolved: kept main's already-fixed runbook line, kept this branch's superset rag-evaluation.md content (main's text preserved verbatim as a prefix, extension section retained). Both playwright.config.ts and design-system docs auto-merged clean. After: merge commit pushed; typecheck clean; tests/design-system-adoption.test.ts 51/51 passed.", + "outcome": "Before: real (git merge-tree confirmed) merge conflicts against origin/main in docs/launch-operator-runbook.md (stale search-health-index text vs the fix already merged via #2155) and docs/rag-evaluation.md (add/add \u2014 main independently gained the base doc while this branch extended it with a RAG Improvement Programme Board section; main's content was an exact prefix of this branch's version). Resolved: kept main's already-fixed runbook line, kept this branch's superset rag-evaluation.md content (main's text preserved verbatim as a prefix, extension section retained). Both playwright.config.ts and design-system docs auto-merged clean. After: merge commit pushed; typecheck clean; tests/design-system-adoption.test.ts 51/51 passed.", "checks": "npx tsc --noEmit (clean), npx vitest run tests/design-system-adoption.test.ts (51 passed), diff verification that main's rag-evaluation.md content survived as an exact prefix. No provider-backed checks run." }, { @@ -6513,7 +6512,7 @@ "date": "2026-08-17", "ref": "claude/correct-056-staging-gap", "head": "6188086e6056c23aa0f7fe1655345c47e0068784", - "scope": "docs/outstanding-issues-inbox — #056 staging migration gap correction", + "scope": "docs/outstanding-issues-inbox \u2014 #056 staging migration gap correction", "outcome": "Remeasured read-only: staging ikoiolksxqxfxgiyqpnu holds 166 migrations (latest 20260719055623) against 192 repo files with 16 after that version, so the gap is 26 not 24 and the post-cutoff count is 16 not 14. Delta is new work landing on main, not a new defect, but the chain grows while the row stays open. Row now instructs re-measuring at window start rather than trusting its own figures.", "checks": "verify:pr-local (11 completed, 0 failed)" }, @@ -6522,7 +6521,7 @@ "ref": "claude/database-coordination-chat-9c0730", "head": "cef640f25aeee9b1fd8fc6c95a351ff1a6c348d3", "scope": "docs/database-remediation-coordination.md board re-baseline (#316), PR #2044", - "outcome": "coordinator self-review: docs-only, anchor corrected #312→#316, board rebuilt from main record", + "outcome": "coordinator self-review: docs-only, anchor corrected #312\u2192#316, board rebuilt from main record", "checks": "prettier --check pass; docs:check-links 1799 refs resolve" }, { @@ -6563,7 +6562,7 @@ "head": "77a631e960b55ef1c563ad85f6d4fc5551e1c98c", "scope": "theme-transition timer race in use-theme.ts causing Vitest unhandled-error failures", "outcome": "Fixed: guarded the 200ms theme-transitioning callback against a torn-down document and tracked/cleared the timer handle so rapid switches cannot end a later transition early", - "checks": "verify:pr-local exit 0 (649 files/6968 tests, no Errors line); red-green proved — new spec reproduces ReferenceError: document is not defined against the unfixed file (2 failed), passes 3/3 with the fix" + "checks": "verify:pr-local exit 0 (649 files/6968 tests, no Errors line); red-green proved \u2014 new spec reproduces ReferenceError: document is not defined against the unfixed file (2 failed), passes 3/3 with the fix" }, { "date": "2026-08-17", @@ -6586,15 +6585,15 @@ "ref": "claude/g1-rag-document-context-qn9ubx", "head": "f59b358d5ddba2480c585196b262afe1f4181632", "scope": "packet G1 document_context provenance tag + ledger issueRowFingerprint display-id fix + two queued G1 closures (supersedes the f5f146a record: two further commits landed on this branch)", - "outcome": "approved — G1 is a provenance tag only, deriveConfidence and synthetic_similarity_count unchanged and pinned; ledger fix restores issues:done for ULID-backed rows with null-safety preserved; no retrieval behaviour change, no canary per owner decision 2026-08-17 Option B", + "outcome": "approved \u2014 G1 is a provenance tag only, deriveConfidence and synthetic_similarity_count unchanged and pinned; ledger fix restores issues:done for ULID-backed rows with null-safety preserved; no retrieval behaviour change, no canary per owner decision 2026-08-17 Option B", "checks": "verify:pr-local all 18 stages green at this head; full unit 642 files / 6879 passed 4 skipped; eval:rag:offline 36 golden 25 suites 603/603; 4 G1 pins + 3 ledger pins mutation-checked" }, { "date": "2026-08-17", "ref": "claude/g1-rag-document-context-qn9ubx", "head": "f5f146a497a4ed04fc1db99b7b8f90a00a1cea30", - "scope": "packet G1 — document_context similarity_origin provenance tag (types.ts, answer-stream-contract.ts, rag-row-contracts.ts, rag.ts telemetry export) + 4 discriminating pins + H5a/HANDOVER docs", - "outcome": "approved — provenance tag only; deriveConfidence and synthetic_similarity_count unchanged and pinned; no retrieval behaviour change, no canary per owner decision 2026-08-17 Option B", + "scope": "packet G1 \u2014 document_context similarity_origin provenance tag (types.ts, answer-stream-contract.ts, rag-row-contracts.ts, rag.ts telemetry export) + 4 discriminating pins + H5a/HANDOVER docs", + "outcome": "approved \u2014 provenance tag only; deriveConfidence and synthetic_similarity_count unchanged and pinned; no retrieval behaviour change, no canary per owner decision 2026-08-17 Option B", "checks": "vitest 5 touched suites 58/58; full unit 642 files / 6879 passed 4 skipped; eval:rag:offline 36 golden 25 suites 603/603; check:rag:fixtures; verify:pr-local all 18 stages green (lint, typecheck, test, build, eval:rag:offline); 4 pins mutation-checked" }, { @@ -6602,7 +6601,7 @@ "ref": "claude/ledger-212-tranche-4-worker-q3y6i4", "head": "0e6e58ca4ac59768658ae4ad5b37a1266a09109b", "scope": "worker/row-contracts.ts, worker/main.ts, tests/worker-row-contract.test.ts", - "outcome": "approved — no defects found; concurrency/lease fencing, schema-constraint-backed contract pins, and safe-logging discipline all verified", + "outcome": "approved \u2014 no defects found; concurrency/lease fencing, schema-constraint-backed contract pins, and safe-logging discipline all verified", "checks": "npx vitest run tests/worker-row-contract.test.ts (28 passed); npx tsc -p tsconfig.json --noEmit (0 errors)" }, { @@ -6627,7 +6626,7 @@ "head": "edc17cc5f059868d31bf7c523be68d8b6449ecae", "scope": "Run PR sweep: babysit", "outcome": "No action needed. New PR discovered mid-sweep (opened by the owner during this sweep). CI green (PR required success), mergeable_state clean, not behind main, no review threads.", - "checks": "No local checks run — nothing to fix, CI already green." + "checks": "No local checks run \u2014 nothing to fix, CI already green." }, { "date": "2026-08-17", @@ -6674,7 +6673,7 @@ "ref": "claude/packet-s6-docling-lab-d6foa6", "head": "798725d04c85070f90c7496c5c7808713dd2d2a5", "scope": "eval/docling isolated Docling lab benchmark harness + Gate B decision-record template (packet S6/B3, PR #2057)", - "outcome": "PR #2057 open — harness only, no benchmark verdict; hard boundaries respected (worker/extractors/database untouched)", + "outcome": "PR #2057 open \u2014 harness only, no benchmark verdict; hard boundaries respected (worker/extractors/database untouched)", "checks": "verify:pr-local heavy plan failed:(none); check:docling-lab passed (36 fixtures/10 hostile/6 canaries); docling-lab-contract test 20/20; check:github-actions passed; legacy engine smoke 46 docs 10/10 hostile contained canary-clean" }, { @@ -6715,7 +6714,7 @@ "head": "6f1624386306abbf52b327a7abb8922b3a7778eb", "scope": "Run PR sweep: babysit", "outcome": "No action needed. CI was mid-run at first snapshot (Unit coverage in progress); left to settle rather than mutating. Re-checked: all required checks (PR required, Static PR checks, Unit coverage, Safety and config checks, PR policy) now green. Not behind main. No review threads.", - "checks": "No local checks run — nothing to fix, CI already green." + "checks": "No local checks run \u2014 nothing to fix, CI already green." }, { "date": "2026-08-17", @@ -6729,7 +6728,7 @@ "date": "2026-08-17", "ref": "claude/rag-d3-s5-followups", "head": "60e61bb9b89e2a62cefa7e89e8f6497c09e8a900", - "scope": "docs/rag-improvement S5 follow-ups: HANDOVER S5/S2 rows, COORDINATION §7, 4 inbox requests (docs-only)", + "scope": "docs/rag-improvement S5 follow-ups: HANDOVER S5/S2 rows, COORDINATION \u00a77, 4 inbox requests (docs-only)", "outcome": "docs-only; S5 landed; follow-ups queued", "checks": "verify:pr-local docs scope" }, @@ -6769,7 +6768,7 @@ "date": "2026-08-17", "ref": "claude/regrade-322-warfarin", "head": "5259f388992a1ed5f9d3ab757ccf40b21705326d", - "scope": "docs/outstanding-issues-inbox — #322 re-grade to P1 on traced evidence", + "scope": "docs/outstanding-issues-inbox \u2014 #322 re-grade to P1 on traced evidence", "outcome": "Traced data/medication-interaction-index.json and src/lib/medication-interactions.ts. The row's 'ZERO in common' claim is wrong - rows 0 and 2 are shared. Real defect is complementary incompleteness: warfarin-vka holds the CRITICAL CYP2C9 inducers row (carbamazepine, St John's Wort) and warfarin-anticoagulant holds the HIGH NSAID/Aspirin/SSRI row (12 counterparties, 6 SSRIs); neither holds the other's. Resolution is per-slug via INDEX.bySlug with no union (medication-interactions.ts:207,241), so which record is opened determines the warnings shown, and both display as Warfarin. Re-graded P2 to P1. Structural finding only; clinical correctness and the merge/delete/relabel decision left to the clinician.", "checks": "verify:pr-local (11 completed, 0 failed)" }, @@ -6794,7 +6793,7 @@ "ref": "claude/s1-rag-mitigation-231-86c182", "head": "6ddd45e5fd0725638c55684ca85833ddf78560c4", "scope": "RAG answer-verification faithfulness fixes (#231 S1): markdown-emphasis atom folding + claim-support wrap reflow, tests, HANDOVER S1 row", - "outcome": "PR #2022 open — rung 1 mitigation; residuals recorded (unbudgeted strong retry timeout, directive-normativity, topic dilution)", + "outcome": "PR #2022 open \u2014 rung 1 mitigation; residuals recorded (unbudgeted strong retry timeout, directive-normativity, topic dilution)", "checks": "eval:rag:offline 583/583; check:production-readiness READY; verify:pr-local heavy scope green except 2 pre-existing host-env unit failures reproduced at merge-base d02767184; 8 pre-fix + 5 post-fix owner-approved live probes" }, { @@ -6938,7 +6937,7 @@ "ref": "dependabot/docker/docker-images-263a700181 (PR #2013)", "head": "eb1874db74b9be0a2657e3913ab41003f402deb0", "scope": "Run PR sweep: CI diagnosis", - "outcome": "Not fixed — genuine incompatibility, not a bug: bumping the Dockerfile base image to node 26-bookworm-slim ships Node v26.7.0, but the repo's engine-strict floor pins Node >=24.15.0 <25 (AGENTS.md), so npm ci fails EBADENGINE in the container build. Needs an owner decision (reject the bump, or a deliberate repo-wide Node 26 migration), not a sweep-scoped code change. Left untouched; no review threads.", + "outcome": "Not fixed \u2014 genuine incompatibility, not a bug: bumping the Dockerfile base image to node 26-bookworm-slim ships Node v26.7.0, but the repo's engine-strict floor pins Node >=24.15.0 <25 (AGENTS.md), so npm ci fails EBADENGINE in the container build. Needs an owner decision (reject the bump, or a deliberate repo-wide Node 26 migration), not a sweep-scoped code change. Left untouched; no review threads.", "checks": "Diagnosed from CI job logs only (Container images / build-and-verify); no local reproduction attempted (Docker build), no provider-backed checks run." }, { @@ -6963,7 +6962,7 @@ "head": "1fb8035b9fdf6617705dd386f33158f20a3c334a", "scope": "Run PR sweep: drift sync", "outcome": "CI already green. Was behind main by 6 commits; synced via authenticated update-branch. No code fix needed, no review threads.", - "checks": "No local checks run — dependency-bump PR, CI already validated before sync; no provider-backed checks run." + "checks": "No local checks run \u2014 dependency-bump PR, CI already validated before sync; no provider-backed checks run." }, { "date": "2026-08-17", @@ -6987,14 +6986,14 @@ "head": "7df44e5c19c904247e0d0d1de40d338223820a95", "scope": "Run PR sweep: drift sync", "outcome": "CI already green (Static PR checks/Unit coverage/Build/Container images all success). Was behind main by 6 commits; synced via authenticated update-branch. No code fix needed, no review threads.", - "checks": "No local checks run — dependency-bump PR, CI already validated before sync; no provider-backed checks run." + "checks": "No local checks run \u2014 dependency-bump PR, CI already validated before sync; no provider-backed checks run." }, { "date": "2026-08-17", "ref": "gemini/clinical-data-lexicon-integrity (PR #2029)", "head": "1f903da31d9befb0cadebd7704447284d3c95bba", "scope": "Run PR sweep: threads + drift", - "outcome": "Partially fixed. Fixed 1 CodeRabbit review thread: tests/therapy-compass-pathways.test.ts modality-absence predicate incorrectly used '&& therapy.modality != null', letting a modality:null record slip past the field-removal assertion — changed to key-presence-only per the reviewer's own suggested diff. Was behind main by 3 commits; synced. NOT fixed, needs owner attention: (1) PR policy check fails — this diff regenerates data/medication-interaction-index.json (clinical-risk per classifyPullRequestFiles) but the PR body has no '## Clinical Governance Preflight' section; cannot fix by editing the PR body per Run PR guardrails. (2) This PR's TCAs dothiepin->dosulepin fix duplicates PR #2015 (claude/p1-318-lexicon-slug-and-guards), which already landed the same fix plus mutation-tested guards and full clinical governance documentation — flagging for owner triage rather than guessing which should win.", + "outcome": "Partially fixed. Fixed 1 CodeRabbit review thread: tests/therapy-compass-pathways.test.ts modality-absence predicate incorrectly used '&& therapy.modality != null', letting a modality:null record slip past the field-removal assertion \u2014 changed to key-presence-only per the reviewer's own suggested diff. Was behind main by 3 commits; synced. NOT fixed, needs owner attention: (1) PR policy check fails \u2014 this diff regenerates data/medication-interaction-index.json (clinical-risk per classifyPullRequestFiles) but the PR body has no '## Clinical Governance Preflight' section; cannot fix by editing the PR body per Run PR guardrails. (2) This PR's TCAs dothiepin->dosulepin fix duplicates PR #2015 (claude/p1-318-lexicon-slug-and-guards), which already landed the same fix plus mutation-tested guards and full clinical governance documentation \u2014 flagging for owner triage rather than guessing which should win.", "checks": "docs:check-links passed after sync. Test fix not locally re-run (no Node 24/vitest install in this sandbox); verified by hand-tracing against the reviewer's own executed verification script. No provider-backed checks run." }, { @@ -7010,7 +7009,7 @@ "ref": "gemini/design-tokens-source-contracts (PR #2031)", "head": "faa22eb3262d3951e398bbda6aa08108c8c574bc", "scope": "Run PR sweep: CI diagnosis", - "outcome": "Not fixed — diagnosed a real, measured Lighthouse regression that needs design/browser review, not a blind sweep fix: 'Lighthouse budget' job failed with mobile-root CLS 0.236 vs baseline 0.013 (+0.223, tolerance +/-0.02), confirmed on 2/3 samples, no other route regressed. The only functional diff in this PR is the mode-nav icon size migration (h-[1.0625rem] w-[1.0625rem] i.e. 17px -> size-icon-md i.e. --spacing-icon-md = 16px, in mode-nav.tsx and nav-slot-ink.tsx); everything else is test-helper refactors. That is the only plausible cause but a 1px icon-size change producing an 11x-over-tolerance CLS spike needs actual browser-rendered root-causing (hydration timing, a paint reflow this sandbox's headless-less environment cannot observe) before touching a protected icon-scale token, not a guess. No review threads. Was behind main by 2 commits at snapshot; left unsynced since there is nothing to push yet.", + "outcome": "Not fixed \u2014 diagnosed a real, measured Lighthouse regression that needs design/browser review, not a blind sweep fix: 'Lighthouse budget' job failed with mobile-root CLS 0.236 vs baseline 0.013 (+0.223, tolerance +/-0.02), confirmed on 2/3 samples, no other route regressed. The only functional diff in this PR is the mode-nav icon size migration (h-[1.0625rem] w-[1.0625rem] i.e. 17px -> size-icon-md i.e. --spacing-icon-md = 16px, in mode-nav.tsx and nav-slot-ink.tsx); everything else is test-helper refactors. That is the only plausible cause but a 1px icon-size change producing an 11x-over-tolerance CLS spike needs actual browser-rendered root-causing (hydration timing, a paint reflow this sandbox's headless-less environment cannot observe) before touching a protected icon-scale token, not a guess. No review threads. Was behind main by 2 commits at snapshot; left unsynced since there is nothing to push yet.", "checks": "Diagnosed from the CI job log for the Lighthouse budget job only; no local Chromium/Lighthouse available in this sandbox to reproduce. No provider-backed checks run." }, { @@ -7018,8 +7017,8 @@ "ref": "gemini/test-infra-tooling-hardening (PR #2030)", "head": "7bcd354401fb2cd4f5b3f328c3f61765db03cace", "scope": "Run PR sweep: threads + drift", - "outcome": "Fixed 5 of 6 CodeRabbit review threads (3 Major, 2 Minor): (1) findBranchTouchedRowIds() in check-ledger-stamp-retention.mjs only iterated commit-side rows and compared 3 of 7 fields, so a deleted ledger row was never marked touched — now iterates the union of base/commit IDs and compares raw+section. (2) checkLedgerStampRetention() silently reported ok:true/0-touched on an unresolvable merge-base instead of failing closed — now returns an explicit error, and the CLI path prints it before touching lostCount/lost. (3) readExpectedBrowserRevisions() in check-playwright-browser-revision.mjs silently omitted a browser family missing a revision instead of failing — now fails closed for chromium/firefox/webkit, with a new regression test. (4) tests/search-route-round-trip-budget.test.ts's non-vacuity guard asserted counter.total()>0 (also counts rate-limit/metadata/telemetry RPCs) instead of the two actual retrieval RPC names. (5) Added the missing check-ledger-stamp-retention.mjs entry to docs/scripts-index.md. Declined 1 finding (--filter option) as a false positive — no docstring, --help text, doc, or test anywhere advertises a --filter option for this script; replied asking the reviewer/owner to point at the source if one exists, left that thread open. CI was mid-run at first snapshot (Container images + 2 Production UI jobs in progress); pushed once assembled rather than mutating mid-run. Not behind main.", - "checks": "node scripts/check-ledger-stamp-retention.mjs --self-test passed; live run + deliberately-bad --base ref confirmed fail-closed behavior. node scripts/check-docs-links.mjs and update-docs-inventory.mjs --check passed. Vitest additions (2 new tests) not locally run (no Node 24/vitest install in this sandbox) — left for CI to verify. No provider-backed checks run." + "outcome": "Fixed 5 of 6 CodeRabbit review threads (3 Major, 2 Minor): (1) findBranchTouchedRowIds() in check-ledger-stamp-retention.mjs only iterated commit-side rows and compared 3 of 7 fields, so a deleted ledger row was never marked touched \u2014 now iterates the union of base/commit IDs and compares raw+section. (2) checkLedgerStampRetention() silently reported ok:true/0-touched on an unresolvable merge-base instead of failing closed \u2014 now returns an explicit error, and the CLI path prints it before touching lostCount/lost. (3) readExpectedBrowserRevisions() in check-playwright-browser-revision.mjs silently omitted a browser family missing a revision instead of failing \u2014 now fails closed for chromium/firefox/webkit, with a new regression test. (4) tests/search-route-round-trip-budget.test.ts's non-vacuity guard asserted counter.total()>0 (also counts rate-limit/metadata/telemetry RPCs) instead of the two actual retrieval RPC names. (5) Added the missing check-ledger-stamp-retention.mjs entry to docs/scripts-index.md. Declined 1 finding (--filter option) as a false positive \u2014 no docstring, --help text, doc, or test anywhere advertises a --filter option for this script; replied asking the reviewer/owner to point at the source if one exists, left that thread open. CI was mid-run at first snapshot (Container images + 2 Production UI jobs in progress); pushed once assembled rather than mutating mid-run. Not behind main.", + "checks": "node scripts/check-ledger-stamp-retention.mjs --self-test passed; live run + deliberately-bad --base ref confirmed fail-closed behavior. node scripts/check-docs-links.mjs and update-docs-inventory.mjs --check passed. Vitest additions (2 new tests) not locally run (no Node 24/vitest install in this sandbox) \u2014 left for CI to verify. No provider-backed checks run." }, { "date": "2026-08-17", @@ -7305,7 +7304,7 @@ "date": "2026-08-15", "ref": "claude/capture-ongoing-drop-question", "head": "367ef8e1414a3ebf81102884fa48298f16068093", - "scope": "docs/outstanding-issues-inbox — capture the unreconciled drift count", + "scope": "docs/outstanding-issues-inbox \u2014 capture the unreconciled drift count", "outcome": "Queued one P1 add request: check:drift reported missing_live 21 (2026-08-09) then 20 (2026-08-14) despite two indexes being restored between, so the expected figure was 19; the gap is consistent with an ongoing drop mechanism. Recorded as inference not fact. Carries a stop rule against beginning the restoration window until resolved. Filed as add rather than a #316 update to avoid colliding with the #316 update already queued in PR #1970.", "checks": "verify:pr-local (11 completed, 0 failed)" }, @@ -7314,7 +7313,7 @@ "ref": "claude/capture-ongoing-drop-question", "head": "8aead5c4fa3ed588f63860b3dc96f54ba415da44", "scope": "required base sync through main 17402395", - "outcome": "Approved — required main update merged; prior drift-inference review remains applicable with no PR-path conflict", + "outcome": "Approved \u2014 required main update merged; prior drift-inference review remains applicable with no PR-path conflict", "checks": "git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed" }, { @@ -7330,7 +7329,7 @@ "ref": "claude/db-remediation-phase-0-wfaiyl", "head": "1a8f7ae02c2bd7aa22e51edfb3b4a7b249ede578", "scope": "required base sync through main 17402395", - "outcome": "Approved — required main update merged; prior ledger guard remediation review remains applicable with no PR-path conflict", + "outcome": "Approved \u2014 required main update merged; prior ledger guard remediation review remains applicable with no PR-path conflict", "checks": "git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed" }, { @@ -7363,7 +7362,7 @@ "head": "6de09c409645cd854438c819250aa668b661568e", "scope": "DS gate 2: interactiveTapFloorDeclarations ratchet closing the h-10 case, plus GATES.md figure corrections (#265)", "outcome": "Gate 2 closed for new use; gate 8 stopped deliberately with the reason recorded; gate 7 untouched", - "checks": "verify:pr-local all 17 selected gates passed — unit suite 607 files / 6585 passed, 4 skipped; check:design-system-contract mutation-verified (interactiveTapFloorDeclarations increased from 41 to 42 plus the per-path line); check:gate-manifest OK at 35 gates / 32 static; no Chromium available (chromium-1194 vs pinned 1234, #255/#312) so no browser gate was claimed" + "checks": "verify:pr-local all 17 selected gates passed \u2014 unit suite 607 files / 6585 passed, 4 skipped; check:design-system-contract mutation-verified (interactiveTapFloorDeclarations increased from 41 to 42 plus the per-path line); check:gate-manifest OK at 35 gates / 32 static; no Chromium available (chromium-1194 vs pinned 1234, #255/#312) so no browser gate was claimed" }, { "date": "2026-08-15", @@ -7379,7 +7378,7 @@ "head": "41a1bd73749564954d7bf11143fd6541402f7691", "scope": "Tighten seven design-system ratchets to measured values after the #1982-#1986 merges", "outcome": "17 units of stale headroom removed; no metric relaxed", - "checks": "check:design-system-contract passed at the tightened values (sub-floor min-heights 40, edge conflicts 19, legacy shadow aliases 114); mutation-verified — min-h-9 on the shortlist Clear button now fails 'increased from 40 to 41' plus the per-path line, which the old pin of 43 allowed silently; check:gate-manifest OK; verify:pr-local 17 gates, unit suite 611 files / 6647 passed" + "checks": "check:design-system-contract passed at the tightened values (sub-floor min-heights 40, edge conflicts 19, legacy shadow aliases 114); mutation-verified \u2014 min-h-9 on the shortlist Clear button now fails 'increased from 40 to 41' plus the per-path line, which the old pin of 43 allowed silently; check:gate-manifest OK; verify:pr-local 17 gates, unit suite 611 files / 6647 passed" }, { "date": "2026-08-15", @@ -7387,7 +7386,7 @@ "head": "02672320db5a0b5b57b589e8d19d19c8c66483d4", "scope": "Favourites search-led workspace: retire marketing H1 and library nav, live in-place filter, dashboard band (#164)", "outcome": "Shipped; no P0-P2 findings", - "checks": "verify:pr-local all 10 selected gates passed — unit suite 607 files / 6584 passed, 4 skipped; check:design-system-contract passed with edgeOwnershipConflicts 25 to 24 from the deleted nav module; UI delegated to CI Production UI — chromium-1194 vs pinned 1234 (#255/#312)" + "checks": "verify:pr-local all 10 selected gates passed \u2014 unit suite 607 files / 6584 passed, 4 skipped; check:design-system-contract passed with edgeOwnershipConflicts 25 to 24 from the deleted nav module; UI delegated to CI Production UI \u2014 chromium-1194 vs pinned 1234 (#255/#312)" }, { "date": "2026-08-15", @@ -7418,7 +7417,7 @@ "ref": "claude/ledger-review-triage-yi63ao", "head": "02d2e7fc839cf370b512f66b255d5f9e9b42f377", "scope": "required base sync through main 17402395", - "outcome": "Approved — required main update merged; previous ledger issue-closure verification remains applicable with no PR-path conflict", + "outcome": "Approved \u2014 required main update merged; previous ledger issue-closure verification remains applicable with no PR-path conflict", "checks": "git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed" }, { @@ -7458,7 +7457,7 @@ "ref": "claude/rag-zod-hardening-tranche2", "head": "1a59ce0b128fbdabb9a24c3ea95c1123299693f3", "scope": "RAG row-contract CI follow-up: optional-signal assertion narrowing", - "outcome": "Fixed P1 — explicit local mismatch catches preserve both logged optional-signal degradation and TypeScript row narrowing", + "outcome": "Fixed P1 \u2014 explicit local mismatch catches preserve both logged optional-signal degradation and TypeScript row narrowing", "checks": "CI typecheck failure reproduced from exact-head log; git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed; local Vitest unavailable because node_modules/vitest is absent" }, { @@ -7466,7 +7465,7 @@ "ref": "claude/rag-zod-hardening-tranche2", "head": "20304ddc703fdc6913e1b62ad532b552ff919dac", "scope": "RAG row-contract tranche 2: optional signal shape-mismatch degradation; merged main", - "outcome": "Approved with P1 fix — malformed optional embedding-field/index-unit rows are logged and degrade to no signal candidates, preserving chunk retrieval; no ranking, ordering, or clinical-output contract changed", + "outcome": "Approved with P1 fix \u2014 malformed optional embedding-field/index-unit rows are logged and degrade to no signal candidates, preserving chunk retrieval; no ranking, ordering, or clinical-output contract changed", "checks": "manual adversarial control-flow review; git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed; targeted Vitest blocked: node_modules/vitest absent" }, { @@ -7474,7 +7473,7 @@ "ref": "claude/rag-zod-hardening-tranche2", "head": "671b0b99f7fdd33e83e5fa55a29470690c9243f2", "scope": "RAG row-contract tranche 2 P2: unconstrained JSON provenance acceptance", - "outcome": "Fixed P2 — index-unit source_span and metadata accept all JSON allowed by the database; non-object provenance is safely omitted from record-only downstream consumers", + "outcome": "Fixed P2 \u2014 index-unit source_span and metadata accept all JSON allowed by the database; non-object provenance is safely omitted from record-only downstream consumers", "checks": "manual adversarial review; focused scalar/array contract regression added; git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed; targeted Vitest blocked: node_modules/vitest absent" }, { @@ -7514,7 +7513,7 @@ "ref": "claude/rag-zod-hardening-tranche2", "head": "f4bc9033d5482922de60681d764eb5e6c6ebb73f", "scope": "rag-candidate-sources.ts signal-row Zod contracts (ledger #212 tranche 2) + 2 ledger captures", - "outcome": "Approved — 3 unchecked RPC-result casts replaced with validated assertions; similarity_origin item deliberately excluded as a clinical-output behaviour change; no ranking/ordering/scoring logic touched", + "outcome": "Approved \u2014 3 unchecked RPC-result casts replaced with validated assertions; similarity_origin item deliberately excluded as a clinical-output behaviour change; no ranking/ordering/scoring logic touched", "checks": "verify:pr-local all 18 steps green, zero failures; contract + rag-imputation-contract pins 21 passed; typecheck exit 0" }, { @@ -7545,8 +7544,8 @@ "date": "2026-08-15", "ref": "claude/services-search-redesign-163", "head": "d007d4a11a0d7b52283fe0088583259ef27c0264", - "scope": "Services bookmark readiness — correcting the 216a72e4 record", - "outcome": "PRIOR RECORD WAS FALSE. Record 216a72e4 claimed 'Fix service bookmark readiness and mutation race' at head 720e7027a9f08e518eb6344e74dfde35d78d5981. That object does not exist in this repository (git cat-file fails; not an ancestor of the branch) and src/components/services/ was byte-identical between 285e12d3c939 and the then-remote tip 87e7fcc2 — no fix had landed. The named defect was real and is fixed here instead", + "scope": "Services bookmark readiness \u2014 correcting the 216a72e4 record", + "outcome": "PRIOR RECORD WAS FALSE. Record 216a72e4 claimed 'Fix service bookmark readiness and mutation race' at head 720e7027a9f08e518eb6344e74dfde35d78d5981. That object does not exist in this repository (git cat-file fails; not an ancestor of the branch) and src/components/services/ was byte-identical between 285e12d3c939 and the then-remote tip 87e7fcc2 \u2014 no fix had landed. The named defect was real and is fixed here instead", "checks": "git cat-file -t on the claimed head: object does not exist; git diff 285e12d..87e7fcc2 -- src/components/services/: empty; new DOM regression test mutation-verified (reverting the gate fails it); focused vitest 12/12; typecheck clean" }, { @@ -7554,8 +7553,8 @@ "ref": "claude/services-search-redesign-163", "head": "f9391318605f4a2cf743cc7a6b3448b61a8296d4", "scope": "Services search results: progressive referral rail, compact rows, favourites bookmark (#163)", - "outcome": "Shipped; row re-measured as half-stale before building — no P0-P2 findings", - "checks": "verify:pr-local all 10 selected gates passed (runtime, lock parity, format:changed, lint, typecheck, test, build, rag fixtures, medication interactions, lexicon report); focused vitest 22/22 across services scope-empty-state, services regressions audit, band adoption, route reachability; check:design-system-contract passed at 25 edge conflicts unchanged; UI delegated to CI Production UI — chromium-1194 vs pinned 1234 (#255/#312)" + "outcome": "Shipped; row re-measured as half-stale before building \u2014 no P0-P2 findings", + "checks": "verify:pr-local all 10 selected gates passed (runtime, lock parity, format:changed, lint, typecheck, test, build, rag fixtures, medication interactions, lexicon report); focused vitest 22/22 across services scope-empty-state, services regressions audit, band adoption, route reachability; check:design-system-contract passed at 25 edge conflicts unchanged; UI delegated to CI Production UI \u2014 chromium-1194 vs pinned 1234 (#255/#312)" }, { "date": "2026-08-15", @@ -7571,7 +7570,7 @@ "head": "22aa7c627e4d3ce220c741d4246d998956249fd2", "scope": "Guarded source-slice test windows: shared helper plus three migrations (#1985)", "outcome": "Shipped; closes a silent-pass class in the contract tests, remainder queued", - "checks": "verify:pr-local all 9 selected gates passed — unit suite 6608 passed / 4 skipped; helper's own test pins the raw idiom returning out-of-window content; migrated files re-run green (17/17, 23/23)" + "checks": "verify:pr-local all 9 selected gates passed \u2014 unit suite 6608 passed / 4 skipped; helper's own test pins the raw idiom returning out-of-window content; migrated files re-run green (17/17, 23/23)" }, { "date": "2026-08-15", @@ -7618,7 +7617,7 @@ "ref": "codex/calculators-mode", "head": "9dc3891ee8bc30a35fdb203607cdd984d3a24cc3", "scope": "calculator command-surface P1/P2 follow-up: suggestion submit and footer ownership docs", - "outcome": "Fixed P1/P2 — selected calculator suggestions pass their exact text into navigation; chrome ownership docs no longer describe calculators as page-owned footers", + "outcome": "Fixed P1/P2 \u2014 selected calculator suggestions pass their exact text into navigation; chrome ownership docs no longer describe calculators as page-owned footers", "checks": "manual control-flow review; focused DOM regression added; git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed; focused Vitest blocked: node_modules/vitest absent" }, { @@ -7626,7 +7625,7 @@ "ref": "codex/calculators-mode", "head": "bbf2207102a0b40b5ba048e8e9a04f37add9bf2c", "scope": "required base sync through main 3824095", - "outcome": "Approved — required main update merged after calculator command follow-ups; no PR-path conflict", + "outcome": "Approved \u2014 required main update merged after calculator command follow-ups; no PR-path conflict", "checks": "git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed" }, { @@ -7634,7 +7633,7 @@ "ref": "codex/calculators-mode", "head": "d8fde21e65ce010b72bc56f1e57334cdfac764c5", "scope": "required base sync through main 17402395", - "outcome": "Approved — required main update merged; prior calculator-mode review remains applicable with no PR-path conflict", + "outcome": "Approved \u2014 required main update merged; prior calculator-mode review remains applicable with no PR-path conflict", "checks": "git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed" }, { @@ -7658,7 +7657,7 @@ "ref": "codex/differential-results-ui-20260814", "head": "8bba4d60586c102a8d42e208c7bd73fb0b52046b", "scope": "Differentials results evidence-state, clinical-cue, and ranking presentation", - "outcome": "Fixed three validated P2 findings: evidence-gated best-match success styling, clinical-cue-only labels, and A–Z display rank.", + "outcome": "Fixed three validated P2 findings: evidence-gated best-match success styling, clinical-cue-only labels, and A\u2013Z display rank.", "checks": "git diff --check; direct Node source-contract assertions; targeted Vitest attempted but unavailable because this isolated worktree has no node_modules/vitest" }, { @@ -7674,7 +7673,7 @@ "ref": "codex/differential-results-ui-20260814", "head": "cc68da45cf37c5fbb6e588106e9d3bf8ab8004c3", "scope": "required base sync through main 17402395", - "outcome": "Approved — required main update merged; prior focused UI review remains applicable with no PR-path conflict", + "outcome": "Approved \u2014 required main update merged; prior focused UI review remains applicable with no PR-path conflict", "checks": "git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed" }, { @@ -7778,7 +7777,7 @@ "ref": "codex/fix-documents-without-live-images", "head": "a42f45955ad8595ccd17ac4fea2ea0d6fd2c2f3f", "scope": "required base sync through main 17402395", - "outcome": "Approved — required main update merged; prior document-cover repair review remains applicable with no PR-path conflict", + "outcome": "Approved \u2014 required main update merged; prior document-cover repair review remains applicable with no PR-path conflict", "checks": "git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed" }, { @@ -7818,7 +7817,7 @@ "ref": "codex/medication-info-header-20260814", "head": "9c1bfe7154eb36e890b4d4e8d61d83da7ba6c926", "scope": "required base sync through main 17402395", - "outcome": "Approved — required main update merged; prior focused medication-header review remains applicable with no PR-path conflict", + "outcome": "Approved \u2014 required main update merged; prior focused medication-header review remains applicable with no PR-path conflict", "checks": "git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed" }, { @@ -7898,7 +7897,7 @@ "ref": "codex/pwa-install-polish-20260815", "head": "c6d8c2829ddd2fc52441a3696aed56fbd0262917", "scope": "required base sync through main 17402395", - "outcome": "Approved — required main update merged; prior PWA lifecycle review and style-inventory repair remain applicable with no PR-path conflict", + "outcome": "Approved \u2014 required main update merged; prior PWA lifecycle review and style-inventory repair remain applicable with no PR-path conflict", "checks": "git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed" }, { @@ -8009,7 +8008,7 @@ "date": "2026-08-14", "ref": "claude/archive-inflight-verified", "head": "2b44e8085ac0e356d43a3180527da2d92cb4af66", - "scope": "docs/outstanding-issues-inbox — retire stale IN FLIGHT annotations", + "scope": "docs/outstanding-issues-inbox \u2014 retire stale IN FLIGHT annotations", "outcome": "Verified 11 IN FLIGHT rows against code on main. Archived 8 as delivered (#178 #209 #221 #233 #234 #235 #237 #238) with file:line evidence, 1 as intentional-by-design (#245). Kept #150 open (account state, not code-verifiable) and #162 open (PR #1839 genuinely still open). Queued as immutable inbox requests.", "checks": "verify:pr-local (11 completed, 0 failed)" }, @@ -8017,7 +8016,7 @@ "date": "2026-08-14", "ref": "claude/capture-drift-phase1-evidence", "head": "00f5612ccf982441cf98ec6ca1c51d68ba2add6a", - "scope": "docs/audit/live-drift-forensics-2026-08.md + inbox — Phase 1.2/1.3 evidence capture", + "scope": "docs/audit/live-drift-forensics-2026-08.md + inbox \u2014 Phase 1.2/1.3 evidence capture", "outcome": "Filled 1.2 (was Pending): 93 functions compared, 0 missing/0 extra/16 mismatches, 6 proven normalization noise, 10 real and UNCLASSIFIED, confirming #316's figure of 10. Extended 1.3: 210 repo vs 192 live indexes, 20 still absent after the incident repair, zero invalid indexes, all five creating migrations recorded executed DDL. Root cause left unestablished. #316/#248 queued as inbox requests. Read-only throughout; no writes to the database.", "checks": "verify:pr-local (11 completed, 0 failed)" }, @@ -8025,7 +8024,7 @@ "date": "2026-08-14", "ref": "claude/correct-rejected-closures", "head": "e4372b5b4e1e382ec28b79e326a0ae1f2a9901ba", - "scope": "docs/outstanding-issues-inbox — corrections for rejected closures and stale #231", + "scope": "docs/outstanding-issues-inbox \u2014 corrections for rejected closures and stale #231", "outcome": "Queued 4 update requests. #235/#237/#238 record the rejected closure, its reason, and a Stop rule naming the evidence class that must not be reused; all three drop the stale IN FLIGHT prefix (PRs #1841/#1842 merged). #231 records that scripts/probe-generation-quality.ts now exists (a3bc4da) and PR #1861 was adjudicated superseded for phase 1, so the row no longer asks for an instrument that exists.", "checks": "verify:pr-local (11 completed, 0 failed; first run correctly failed check:ledger-write-discipline on uncommitted edits)" }, @@ -8058,7 +8057,7 @@ "ref": "claude/disabled-button-accessibility-piclvr (PR #1928)", "head": "1988c762dfa763a38ec1b95cc9855b0db47f2054", "scope": "PR #1928 heavy review: outstanding-issues inbox count accuracy (docs only)", - "outcome": "P2 fixed — durable summary corrected from four controls to four groups covering nine controls; no other actionable defects; no unresolved review threads", + "outcome": "P2 fixed \u2014 durable summary corrected from four controls to four groups covering nine controls; no other actionable defects; no unresolved review threads", "checks": "manual adversarial source pass; JSON parse + schema/count assertions; exact-head PR required CI green before fix; no provider-backed gates run" }, { @@ -8066,7 +8065,7 @@ "ref": "claude/fetch-stream-catch-cleanup", "head": "53ed54137fde3cb5ee7f8e177d85ba0f177593c6", "scope": "empty catch disposition (src/lib/theme.ts, src/app/layout.tsx) + new tests/empty-catch-disposition.test.ts contract guard + issues:done request for #213", - "outcome": "Approved — 3 bare catches dispositioned with inline comments; no behaviour change. Finding: all 3 were inline-script storage/cookie reads, not fetch/stream swallowing as #213 described; the genuine fetch/stream catches were already dispositioned. New raw-source-text contract test guards the population (0 bare, 21 total).", + "outcome": "Approved \u2014 3 bare catches dispositioned with inline comments; no behaviour change. Finding: all 3 were inline-script storage/cookie reads, not fetch/stream swallowing as #213 described; the genuine fetch/stream catches were already dispositioned. New raw-source-text contract test guards the population (0 bare, 21 total).", "checks": "verify:pr-local (all gates pass except pre-existing check:medication-lexicon-report, inputs byte-identical to origin/main); npm run test 602 files / 6511 passed / 4 skipped; new contract test 2 passed" }, { @@ -8074,8 +8073,8 @@ "ref": "claude/fetch-stream-catch-cleanup", "head": "f05c2d58fc70465a52cbb23306179b5420c3a95c", "scope": "empty catch disposition + contract guard + regenerated docs/medication-interaction-lexicon-review.md", - "outcome": "Approved — supersedes the 53ed541 record after adding the lexicon-report regeneration. 3 bare catches dispositioned inline (no behaviour change); finding recorded that all 3 were inline-script storage/cookie reads, not the fetch/stream swallowing #213 described. Lexicon report drift was pre-existing on main and a pure re-wrap (whitespace-normalised files are byte-identical); classifyPullRequestFiles reports clinicalRisk false with or without it.", - "checks": "verify:pr-local on final head: failed (none) — all 18 gates pass including check:medication-lexicon-report; npm run test 602 files / 6511 passed / 4 skipped" + "outcome": "Approved \u2014 supersedes the 53ed541 record after adding the lexicon-report regeneration. 3 bare catches dispositioned inline (no behaviour change); finding recorded that all 3 were inline-script storage/cookie reads, not the fetch/stream swallowing #213 described. Lexicon report drift was pre-existing on main and a pure re-wrap (whitespace-normalised files are byte-identical); classifyPullRequestFiles reports clinicalRisk false with or without it.", + "checks": "verify:pr-local on final head: failed (none) \u2014 all 18 gates pass including check:medication-lexicon-report; npm run test 602 files / 6511 passed / 4 skipped" }, { "date": "2026-08-14", @@ -8098,8 +8097,8 @@ "ref": "claude/ledger-merge-loss-finding", "head": "7a8d57da01b3221c61c87d2f14ace392ab33fb67", "scope": "ledger merge-loss finding", - "outcome": "PR #1937 — one immutable inbox request (P2 issue) recording that a queued outstanding-issues request was created on a branch and never reached main through that branch's squash. Verified before writing: the request's own remedies had already shipped on main independently (hook guards CLAUDE_ENV_FILE; check:runtime names the hook), so the request was NOT re-queued verbatim — a re-queue would have opened an already-resolved row. The row filed instead is about the undetected loss itself. Docs-only; no source changes.", - "checks": "npm run verify:pr-local — failed: (none), 11 checks completed; ledger inbox check passed: 76 pending request(s), 19 applied" + "outcome": "PR #1937 \u2014 one immutable inbox request (P2 issue) recording that a queued outstanding-issues request was created on a branch and never reached main through that branch's squash. Verified before writing: the request's own remedies had already shipped on main independently (hook guards CLAUDE_ENV_FILE; check:runtime names the hook), so the request was NOT re-queued verbatim \u2014 a re-queue would have opened an already-resolved row. The row filed instead is about the undetected loss itself. Docs-only; no source changes.", + "checks": "npm run verify:pr-local \u2014 failed: (none), 11 checks completed; ledger inbox check passed: 76 pending request(s), 19 applied" }, { "date": "2026-08-14", @@ -8130,16 +8129,16 @@ "ref": "claude/ledger-process-tooling-50uqfc", "head": "93365d6e4e496c233e629d85a572f3feb08513cf", "scope": "outstanding-issues reconciliation of 35 queued requests (fresh base 0011a058)", - "outcome": "PR #1956 — one serial reconciliation transaction from a fresh origin/main base, restarting the branch after its previous PR (#1944) merged as squash 372cb13f. 35 requests applied: 17 done, 7 add, 6 update, 5 cancel; ledger 328 to 334 rows, 115 to 99 open. Machine-generated and machine-verified end to end; no request or canonical row was hand-edited. Includes the five requests PR #1944 left pending: closes #313, carries #211 forward with a re-measured 1,445 errors while keeping its deprioritisation and P3 priority, records #168 and #258 without closing either, and opens #335. One request deliberately not re-filed: cancel a8783c79, whose target 0e47904b was already consumed by the reconcile in PR #1936, making it invalid; nothing lost because the surviving #211 update folds its text forward. Visual HTML register NOT refreshed — its PowerShell refresh script is a Windows path unavailable in this Linux container; Markdown source is current, artifact is stale.", - "checks": "npm run verify:pr-local — 11 gates completed, 0 failed; npm run check:ledger-write-discipline printed \"Ledger write discipline passed for 0011a058fd1d..HEAD\", independently recomputing the transaction; check:outstanding-issues 334 rows (99 open, 235 archived), unique ids, next-id=337 above the highest, 0 pending requests, 129 applied; the pre-existing check:medication-lexicon-report failure seen on PR #1944 is gone, confirming PR #1941 fixed it at source. Note: run before committing, check:ledger-write-discipline correctly REFUSED to report a verdict and named every uncommitted request file — the guard PR #1944 shipped, working on the first real reconciliation after it landed." + "outcome": "PR #1956 \u2014 one serial reconciliation transaction from a fresh origin/main base, restarting the branch after its previous PR (#1944) merged as squash 372cb13f. 35 requests applied: 17 done, 7 add, 6 update, 5 cancel; ledger 328 to 334 rows, 115 to 99 open. Machine-generated and machine-verified end to end; no request or canonical row was hand-edited. Includes the five requests PR #1944 left pending: closes #313, carries #211 forward with a re-measured 1,445 errors while keeping its deprioritisation and P3 priority, records #168 and #258 without closing either, and opens #335. One request deliberately not re-filed: cancel a8783c79, whose target 0e47904b was already consumed by the reconcile in PR #1936, making it invalid; nothing lost because the surviving #211 update folds its text forward. Visual HTML register NOT refreshed \u2014 its PowerShell refresh script is a Windows path unavailable in this Linux container; Markdown source is current, artifact is stale.", + "checks": "npm run verify:pr-local \u2014 11 gates completed, 0 failed; npm run check:ledger-write-discipline printed \"Ledger write discipline passed for 0011a058fd1d..HEAD\", independently recomputing the transaction; check:outstanding-issues 334 rows (99 open, 235 archived), unique ids, next-id=337 above the highest, 0 pending requests, 129 applied; the pre-existing check:medication-lexicon-report failure seen on PR #1944 is gone, confirming PR #1941 fixed it at source. Note: run before committing, check:ledger-write-discipline correctly REFUSED to report a verdict and named every uncommitted request file \u2014 the guard PR #1944 shipped, working on the first real reconciliation after it landed." }, { "date": "2026-08-14", "ref": "claude/ledger-process-tooling-50uqfc", "head": "d36914a79fa4304273429aab0d7f271010f3bb96", "scope": "ledger process tooling bundle (#313 dirty-tree gate, 829597d4 merge-loss detector, #211/#168/#258 plans)", - "outcome": "PR #1944 — five separate commits, each independently revertible. Two code items: check-ledger-write-discipline.mjs now refuses a verdict while a governed ledger path is dirty (gated on default HEAD so guard-push.mjs explicit --head and clean CI are unaffected); new scripts/audit-merge-loss.mjs advisory blob-comparison sweep, exits 0 and asks for human confirmation, not wired into CI or verify:cheap by design. Three docs-only plans. Found and fixed during build: the shared git() helper trim() was corrupting porcelain status parsing, and JSDoc types were needed to stop TS inferring never[] for the classifier landings parameter. Noted: classifyPullRequestFiles reports operationalRisk true solely from the package.json script entry.", - "checks": "npm run verify:pr-local — 18 gates completed, 1 failed: check:medication-lexicon-report, reproduced identically in a clean detached worktree at origin/main d47aa6d so pre-existing and not caused here; tests/ledger-write-discipline.test.ts 9 passed; tests/merge-loss-audit.test.ts 14 passed; both script self-tests passed; audit:merge-loss --since 6 independently rediscovered the acf78bf casualties #1803/#1800/#1804/#1796/#1811" + "outcome": "PR #1944 \u2014 five separate commits, each independently revertible. Two code items: check-ledger-write-discipline.mjs now refuses a verdict while a governed ledger path is dirty (gated on default HEAD so guard-push.mjs explicit --head and clean CI are unaffected); new scripts/audit-merge-loss.mjs advisory blob-comparison sweep, exits 0 and asks for human confirmation, not wired into CI or verify:cheap by design. Three docs-only plans. Found and fixed during build: the shared git() helper trim() was corrupting porcelain status parsing, and JSDoc types were needed to stop TS inferring never[] for the classifier landings parameter. Noted: classifyPullRequestFiles reports operationalRisk true solely from the package.json script entry.", + "checks": "npm run verify:pr-local \u2014 18 gates completed, 1 failed: check:medication-lexicon-report, reproduced identically in a clean detached worktree at origin/main d47aa6d so pre-existing and not caused here; tests/ledger-write-discipline.test.ts 9 passed; tests/merge-loss-audit.test.ts 14 passed; both script self-tests passed; audit:merge-loss --since 6 independently rediscovered the acf78bf casualties #1803/#1800/#1804/#1796/#1811" }, { "date": "2026-08-14", @@ -8153,7 +8152,7 @@ "date": "2026-08-14", "ref": "claude/ledger-reconcile-batch-1", "head": "00c09a30f91427b3154b64812b73294847265778", - "scope": "docs/outstanding-issues.md + inbox — serial reconciliation of 75 queued requests", + "scope": "docs/outstanding-issues.md + inbox \u2014 serial reconciliation of 75 queued requests", "outcome": "Applied 63 active mutations (14 add, 23 done, 26 update) plus 6 cancellation decisions. Ledger 115 open/199 archived -> 106/222; inbox 0 pending/94 applied. Verified zero live same-target collisions before applying, since planRequestBatch dedupes on request UUID not canonical row id.", "checks": "issues:reconcile --dry-run; verify:pr-local (11 completed, 0 failed); check:ledger-write-discipline" }, @@ -8161,7 +8160,7 @@ "date": "2026-08-14", "ref": "claude/ledger-reconcile-batch-2", "head": "af68b3271922656ef97312dae513a3f6906aec76", - "scope": "docs/outstanding-issues.md + inbox — second serial reconciliation of 35 queued requests", + "scope": "docs/outstanding-issues.md + inbox \u2014 second serial reconciliation of 35 queued requests", "outcome": "Applied 25 active mutations (13 done, 6 add, 6 update) plus 5 cancellation decisions. Ledger 106 open/222 archived -> 99/235; inbox 0 pending/129 applied. Three closures queued in PR #1940 (#235 #237 #238) were cancelled by review and stay open: each asked for visual or browser proof and had been closed on executable evidence. Zero live same-target collisions verified before applying.", "checks": "issues:reconcile --dry-run; verify:pr-local (11 completed, 0 failed); check:ledger-write-discipline" }, @@ -8169,8 +8168,8 @@ "date": "2026-08-14", "ref": "claude/ledger-reconcile-batch-3", "head": "be94fbbb31843f4593783b9ca388ee0526b74e84", - "scope": "docs/outstanding-issues.md + inbox — reconcile the four rejected-closure corrections", - "outcome": "Applied 4 update requests from PR #1957, no cancellations, zero live collisions. #235/#237/#238 now carry the rejected closure, its reason and a Stop rule naming the evidence class; #231 records the probe script and the #1861 adjudication. Row counts unchanged at 99 open/235 archived by design — detail rewrites, not archives. Inbox 0 pending/133 applied.", + "scope": "docs/outstanding-issues.md + inbox \u2014 reconcile the four rejected-closure corrections", + "outcome": "Applied 4 update requests from PR #1957, no cancellations, zero live collisions. #235/#237/#238 now carry the rejected closure, its reason and a Stop rule naming the evidence class; #231 records the probe script and the #1861 adjudication. Row counts unchanged at 99 open/235 archived by design \u2014 detail rewrites, not archives. Inbox 0 pending/133 applied.", "checks": "issues:reconcile --dry-run; verify:pr-local (11 completed, 0 failed); check:ledger-write-discipline" }, { @@ -8210,7 +8209,7 @@ "ref": "claude/rag-zod-hardening-tranche1", "head": "0fded0878b6f8e35ef50b8c97a63af6e78e1f716", "scope": "rag.ts retrieval RPC row Zod shape contract (ledger #212 tranche 1)", - "outcome": "Approved — 4 unchecked as SearchResult[] casts on retrieval RPC rows replaced with assertRetrievalRows; no ranking/ordering/scoring logic touched", + "outcome": "Approved \u2014 4 unchecked as SearchResult[] casts on retrieval RPC rows replaced with assertRetrievalRows; no ranking/ordering/scoring logic touched", "checks": "verify:pr-local (all steps green except pre-existing check:medication-lexicon-report staleness on main); test 602 files/6517 passed; typecheck exit 0; eval:rag:offline 36 golden cases 23 suites, 579 passed" }, { @@ -8345,8 +8344,8 @@ "date": "2026-08-14", "ref": "PR #1965 (claude/playwright-browser-revision-check)", "head": "24e8fd040949564e2c07fccfe6d243e386815b6e", - "scope": "scripts/check-playwright-browser-revision.mjs, tests/check-playwright-browser-revision.test.ts — ledger #312 fix", - "outcome": "authored — verified real Chromium binary presence check on disk; reproduced original false-OK bug live against this session's /opt/pw-browsers container (chromium-1194 present, pinned revision 1234 missing)", + "scope": "scripts/check-playwright-browser-revision.mjs, tests/check-playwright-browser-revision.test.ts \u2014 ledger #312 fix", + "outcome": "authored \u2014 verified real Chromium binary presence check on disk; reproduced original false-OK bug live against this session's /opt/pw-browsers container (chromium-1194 present, pinned revision 1234 missing)", "checks": "verify:pr-local (runtime, lock-parity, format, lint, typecheck, test 602 files/6518 passed/4 skipped, rag:fixtures, medication-interactions PASS; medication-lexicon-report pre-existing unrelated FAIL); focused vitest check-playwright-browser-revision.test.ts 10/10, playwright-browser-preflight.test.ts 12/12" }, { @@ -8466,7 +8465,7 @@ "ref": "PR-1959", "head": "428fa8772198817e17ef6330c63f7f5e47e090b0", "scope": "PR #1959 base-preserving reconciliation review", - "outcome": "Required base sync resolved the sole ledger conflict with main: all four inbox requests were already applied upstream; preserved main’s newer #231 evidence and retained the existing immutable historical record.", + "outcome": "Required base sync resolved the sole ledger conflict with main: all four inbox requests were already applied upstream; preserved main\u2019s newer #231 evidence and retained the existing immutable historical record.", "checks": "docs link check passed: 1776 repo path references resolve; Ledger inbox check passed: 12 pending request(s), 138 applied; branch-review-ledger self-test passed; Branch review ledger guard passed: 880 live table records + 1206 archived + 92 immutable; verify:pr-local unavailable: tsx/cli absent from isolated worktree (Node v24.14.0)." }, { @@ -8474,7 +8473,7 @@ "ref": "PR-1961", "head": "ed6ad9a0f81b079568534db78283fec93b956c67", "scope": "PR #1961 base-preserving reconciliation sync", - "outcome": "Required base sync retained the current canonical ledger: all 35 reconciliation records and the #310 correction were already present upstream; preserved only the branch’s new pending Prettier-version-trap request.", + "outcome": "Required base sync retained the current canonical ledger: all 35 reconciliation records and the #310 correction were already present upstream; preserved only the branch\u2019s new pending Prettier-version-trap request.", "checks": "docs link check passed: 1775 repo path references resolve; Ledger inbox check passed: 23 pending request(s), 138 applied; branch-review-ledger self-test passed; Branch review ledger guard passed: 880 live table records + 1206 archived + 99 immutable; verify:pr-local unavailable: tsx/cli absent from isolated worktree (Node v24.14.0)." }, { @@ -8490,7 +8489,7 @@ "ref": "PR-1964", "head": "1dfc0c9b984152f6518060712ab050311f3f77c9", "scope": "vitest.config.mts, docs/maturity-backlog-workorders.md (ledger #192 / maturity X6 coverage floors)", - "outcome": "APPROVED — coverage-threshold re-ratchet, no RAG/clinical behaviour change; verify:pr-local green except pre-existing unrelated check:medication-lexicon-report staleness", + "outcome": "APPROVED \u2014 coverage-threshold re-ratchet, no RAG/clinical behaviour change; verify:pr-local green except pre-existing unrelated check:medication-lexicon-report staleness", "checks": "test:coverage,verify:pr-local" }, { @@ -8513,7 +8512,7 @@ "date": "2026-08-13", "ref": "claude/design-issues-triage-wnr7k9", "head": "615893b24fa2be21e245ef1e47ae2fa1e2e12981", - "scope": "docs/outstanding-issues-inbox — #210 correction", + "scope": "docs/outstanding-issues-inbox \u2014 #210 correction", "outcome": "Corrected #210: typecheck half already fixed by tsconfig.typecheck.json; the prescribed tsconfig.json include edit is reverted by Next (type-paths.js:34-36 + writeConfigurationDefaults.js:305-315). Remaining Playwright-isolated-tsconfig half recorded as not proven end-to-end. Queued as immutable inbox request.", "checks": "verify:pr-local (all 11 completed, 0 failed)" }, @@ -8522,7 +8521,7 @@ "ref": "claude/disabled-button-accessibility-piclvr", "head": "c73bba958e26e706c4957c886c9974ffcf330943", "scope": "outstanding-issues inbox request capturing the four placeholder controls #291 left native (docs only)", - "outcome": "authored — PR #1928 opened", + "outcome": "authored \u2014 PR #1928 opened", "checks": "verify:pr-local 11/11 completed, none failed; check:outstanding-issues; check:ledger-write-discipline (re-run post-commit); prettier --check clean" }, { @@ -8578,7 +8577,7 @@ "ref": "claude/ledger-tasks-fable-xhl7xb", "head": "6f1cd23a34dca2fa3ae9d676d4dace46fd779d3a", "scope": "ledger intake: merge-loss capture (4 inbox requests)", - "outcome": "clean — additive JSON intake only, no canonical ledger edit", + "outcome": "clean \u2014 additive JSON intake only, no canonical ledger edit", "checks": "verify:pr-local (all 11 gates, none failed); dry-apply of 23 pending requests against origin/main" }, { @@ -8970,7 +8969,7 @@ "ref": "claude/design-issues-triage-wnr7k9", "head": "586012639565e4d3306b44361ebc5a3bdb3024ad", "scope": "Land PR #1838 ledger sweep; close #147 mobile CLS by measurement", - "outcome": "Merge resolved as union (main renumbered #302/#303 to #306/#307 — not lost, correcting an earlier claim); #306/#307 archived as already-delivered. #147 archived on two identical offline Lighthouse runs: mobile CLS 0.035/0.000/0.013/0.081/0.000, all under 0.1, cause fixed by PR #1616 not this session. #118 updated (browser drift 141-vs-151, wider than recorded); new #308 for desktop /documents/search CLS 0.119", + "outcome": "Merge resolved as union (main renumbered #302/#303 to #306/#307 \u2014 not lost, correcting an earlier claim); #306/#307 archived as already-delivered. #147 archived on two identical offline Lighthouse runs: mobile CLS 0.035/0.000/0.013/0.081/0.000, all under 0.1, cause fixed by PR #1616 not this session. #118 updated (browser drift 141-vs-151, wider than recorded); new #308 for desktop /documents/search CLS 0.119", "checks": "verify:pr-local 10/10 green; check:outstanding-issues 121 open/185 archived; verify:lighthouse x2 (gate ungraded on browser drift, measurements valid)" }, { @@ -9202,7 +9201,7 @@ "ref": "PR #1888 (claude/filter-contract-factsheets-pr-d)", "head": "95515078031b4bd29d90f05986dc5eb3a36ce660", "scope": "factsheets category counts, filter-contract correction, desktop-rail exception decision", - "outcome": "Filter contract PR D — corrected the earlier false claim that factsheets' category presets discard the query and need eviction (searchHref preserves q); kept the desktop rail as real Link elements rather than converging to SegmentedControl because /factsheets/search is a genuine server-rendered searchParams route, recorded as a documented exception in filter-contract.md; added per-query category counts to both breakpoints from one shared options array. verify:pr-local full green pre- and post-merge; bundle budget within tolerance; UI proved with pinned-Chromium Playwright (11/11) and the updated ui-smoke.spec.ts factsheets test against a real build. /issues #170 updated to correct its own stale factsheets claim.", + "outcome": "Filter contract PR D \u2014 corrected the earlier false claim that factsheets' category presets discard the query and need eviction (searchHref preserves q); kept the desktop rail as real Link elements rather than converging to SegmentedControl because /factsheets/search is a genuine server-rendered searchParams route, recorded as a documented exception in filter-contract.md; added per-query category counts to both breakpoints from one shared options array. verify:pr-local full green pre- and post-merge; bundle budget within tolerance; UI proved with pinned-Chromium Playwright (11/11) and the updated ui-smoke.spec.ts factsheets test against a real build. /issues #170 updated to correct its own stale factsheets claim.", "checks": "verify:pr-local (green), check:bundle-budget (within tolerance), lint, typecheck, full vitest (564/564 post-merge), targeted Playwright (1/1) + manual browser script (11/11)" }, { @@ -9290,8 +9289,8 @@ "ref": "claude/codex-m4c-retire-shadow-nliak3", "head": "448a0d084c4cd2cda6153dd7f03dcb67c43a8df0", "scope": "DS Track A2 (#261): retire --shadow-focus; composer focus onto sanctioned outline; contract guard; baseline ratchet; design-system docs + ledger", - "outcome": "Approved — PR #1807. Token deleted in both themes; .chat-composer-shell-delta:focus-within uses outline 2px var(--focus) at offset 2px and no longer overrides box-shadow. Reach premise corrected: 0 of 37 production routes render the class (only /mockups/calculators-search). legacyShadowAliases 127->125, globals.css pin 3->1.", - "checks": "check:design-system-contract PASS; design-token-contract.test.ts PASS + mutation-verified both ways; verify:pr-local PASS except pre-existing tests/pr-handoff-stop.test.ts failure baselined on untouched base e8b61d8; build PASS; check:rag:fixtures PASS (36 cases); Chromium look both themes on the mockup route (inspection only, rev 1194 vs pinned 1234 #255); verify:ui/verify:phone-chrome NOT run — delegated to CI" + "outcome": "Approved \u2014 PR #1807. Token deleted in both themes; .chat-composer-shell-delta:focus-within uses outline 2px var(--focus) at offset 2px and no longer overrides box-shadow. Reach premise corrected: 0 of 37 production routes render the class (only /mockups/calculators-search). legacyShadowAliases 127->125, globals.css pin 3->1.", + "checks": "check:design-system-contract PASS; design-token-contract.test.ts PASS + mutation-verified both ways; verify:pr-local PASS except pre-existing tests/pr-handoff-stop.test.ts failure baselined on untouched base e8b61d8; build PASS; check:rag:fixtures PASS (36 cases); Chromium look both themes on the mockup route (inspection only, rev 1194 vs pinned 1234 #255); verify:ui/verify:phone-chrome NOT run \u2014 delegated to CI" }, { "date": "2026-08-11", @@ -9394,7 +9393,7 @@ "ref": "codex/visual-baseline-advisory-pr", "head": "6bc57714c36bc6d027561bb8f5f8b00bb92524b2", "scope": "PR #1791 babysit unblock", - "outcome": "fixed Production UI formulation Clear→Draft flake settle; classified visual drift vs non-drift failures", + "outcome": "fixed Production UI formulation Clear\u2192Draft flake settle; classified visual drift vs non-drift failures", "checks": "test:ci-workflows 263; classify-visual-baseline-outcome+ci-cache-safety 40" }, { @@ -9458,7 +9457,7 @@ "ref": "cursor/smarter-meds-search-9c1b (PR #1785)", "head": "88dbdd80ede81ec6062ffebae79244703d495a99", "scope": "PR #1785 unblock/fix", - "outcome": "before: BEHIND/MERGEABLE behind-but-clean (merge-tree clean, behind 2/ahead 9); tip 88dbdd80 required CI green; → after: late merged origin/main once (#1793/#1794); merge-tree clean; behind 0; no required-CI code fixes; no provider-backed checks", + "outcome": "before: BEHIND/MERGEABLE behind-but-clean (merge-tree clean, behind 2/ahead 9); tip 88dbdd80 required CI green; \u2192 after: late merged origin/main once (#1793/#1794); merge-tree clean; behind 0; no required-CI code fixes; no provider-backed checks", "checks": "git merge-tree clean; npm run format; prior tip CI green; no provider-backed checks run" }, { @@ -9466,7 +9465,7 @@ "ref": "cursor/smarter-meds-search-9c1b (PR #1785)", "head": "a4f57500f6b16a4616e1f84c126c2f787a40766b", "scope": "PR #1785 unblock/fix", - "outcome": "before: DIRTY/CONFLICTING behind-but-clean (merge-tree clean, behind 3/ahead 8); prior tip a4f57500 CI green; 0 unresolved threads → after: merged origin/main once (sync-only); merge-tree clean; behind 0; no CI/thread code fixes; focused meds tests 201 passed", + "outcome": "before: DIRTY/CONFLICTING behind-but-clean (merge-tree clean, behind 3/ahead 8); prior tip a4f57500 CI green; 0 unresolved threads \u2192 after: merged origin/main once (sync-only); merge-tree clean; behind 0; no CI/thread code fixes; focused meds tests 201 passed", "checks": "git merge-tree clean; npm run format; npm run test:focused meds/route/universal-search 201 passed; no provider-backed checks run" }, { @@ -9474,7 +9473,7 @@ "ref": "PR #1788", "head": "aaeb54630fde2c05efe9a90eda13fbb92cc933c0", "scope": "Run PR sweep", - "outcome": "Static PR maintainability: extracted useAnswerThreadBootstrap (ClinicalDashboard 4144→4106); merged origin/main (#1794/#1795)", + "outcome": "Static PR maintainability: extracted useAnswerThreadBootstrap (ClinicalDashboard 4144\u21924106); merged origin/main (#1794/#1795)", "checks": "check:maintainability-budgets pass; vitest bootstrap+storage 17; tsc clean; CI pending after push" }, { @@ -9546,7 +9545,7 @@ "ref": "claude/disabled-button-accessibility-piclvr", "head": "722abdb780c715c0a89df268ed48f6c741ffd569", "scope": "disabled-placeholder buttons -> aria-disabled + inert handler (25 sites, 13 components); controlDisabled/therapy recipe aria-disabled styling; require-button-wiring redundantDisabledPair gate; wiring-conventions contract rewrite (settles #291)", - "outcome": "authored — PR #1778 opened", + "outcome": "authored \u2014 PR #1778 opened", "checks": "lint (uncached, exit 0); typecheck; test 5878 passed/1 pre-existing root-env failure in pr-handoff-stop; build; check:rag:fixtures 36 golden cases; prettier --check clean; verify:ui not run (no browser in container)" }, { @@ -9626,7 +9625,7 @@ "ref": "claude/m2-ds-gates-blocking", "head": "d204c6f7c84a5e7de3f28061121fda68e7d28670", "scope": "M2 design-system gates: #264 + gate 4 of #265", - "outcome": "ready-to-merge; supersedes the 8ed66a05 row — the tap-floor defect renumbered #289 to #291 after main claimed #289/#290, and main was merged in", + "outcome": "ready-to-merge; supersedes the 8ed66a05 row \u2014 the tap-floor defect renumbered #289 to #291 after main claimed #289/#290, and main was merged in", "checks": "post-merge ds-contract PASS (colour-only 4, numerals 2, inversions 0) against main's new #1765/#1766 component code; outstanding-issues guard PASS 289 rows next-id=292; ledger guard PASS 774 rows; format clean" }, { @@ -9634,7 +9633,7 @@ "ref": "claude/m2-ds-gates-blocking", "head": "e8447b042088998d34af750df72a946b1f074b97", "scope": "M2 design-system gates: #264 + gate 4 of #265", - "outcome": "ready-to-merge; supersedes the d204c6f7 row — seven review findings fixed, copilot-swe-agent commits merged keeping the safer numeral classifier, tap-floor defect renumbered #291 to #293 after main claimed #291/#292", + "outcome": "ready-to-merge; supersedes the d204c6f7 row \u2014 seven review findings fixed, copilot-swe-agent commits merged keeping the safer numeral classifier, tap-floor defect renumbered #291 to #293 after main claimed #291/#292", "checks": "ds-contract PASS (colour-only 4, numerals 2, inversions 0); 11 reviewer cases probe-verified; mutation-verified incl. opacity and arbitrary-filter forms; lint 0; tsc 0 errors; format clean; outstanding-issues guard PASS 291 rows next-id=294 no ids deleted; ledger guard PASS 775 rows" }, { @@ -9643,7 +9642,7 @@ "head": "7bac3bd762b381cb25c9b2a15ef3bb7223d15b16", "scope": "PR #1780 review-and-fix", "outcome": "fixed P2 ratchet bypasses (arbitrary-property classes, CSS-consumer exemption anti-rot, modern CSS zero units); Bugbot clean; merge-tree clean; required CI was green on prior tip", - "checks": "vitest design-system-contract-utils 32/32; check:design-system-contract; mutation CSS-exemption fail→restore; verify:cheap PASS (549 files / 5933 tests); verify:pr-local stages PASS (test flake in design-system-adoption timed out once then 51/51 + full test 549/549 + check:rag:fixtures PASS); no provider gates" + "checks": "vitest design-system-contract-utils 32/32; check:design-system-contract; mutation CSS-exemption fail\u2192restore; verify:cheap PASS (549 files / 5933 tests); verify:pr-local stages PASS (test flake in design-system-adoption timed out once then 51/51 + full test 549/549 + check:rag:fixtures PASS); no provider gates" }, { "date": "2026-08-09", @@ -9651,7 +9650,7 @@ "head": "95221ef4235abd9544158b07b8b8569f00c9ec78", "scope": "PR #1780 review-and-fix", "outcome": "fixed P2 ratchet bypasses (arbitrary-property classes, CSS-consumer exemption anti-rot, modern CSS zero units); Bugbot clean; merge-tree clean; required CI was green on prior tip", - "checks": "vitest design-system-contract-utils 32/32; check:design-system-contract; mutation CSS-exemption fail→restore; verify:cheap PASS (549 files / 5933 tests); verify:pr-local stages PASS (test flake in design-system-adoption timed out once then 51/51 + full test 549/549 + check:rag:fixtures PASS); no provider gates" + "checks": "vitest design-system-contract-utils 32/32; check:design-system-contract; mutation CSS-exemption fail\u2192restore; verify:cheap PASS (549 files / 5933 tests); verify:pr-local stages PASS (test flake in design-system-adoption timed out once then 51/51 + full test 549/549 + check:rag:fixtures PASS); no provider gates" }, { "date": "2026-08-09", @@ -9786,7 +9785,7 @@ "ref": "cursor/therapy-card-densify-e975", "head": "3db839a6bb1f5b45fc55bb732d21b30551a506b0", "scope": "therapy search ResultCard densify (gap, tags, favourite, actions, match cells)", - "outcome": "pass — denser cards; band gap fixed; single-row prioritized tags; heart top-right; 3-col actions; summarised cells", + "outcome": "pass \u2014 denser cards; band gap fixed; single-row prioritized tags; heart top-right; 3-col actions; summarised cells", "checks": "unit 35/35; verify:pr-local pass; ensure visual phone+desktop pass" }, { @@ -9882,7 +9881,7 @@ "ref": "claude/document-viewer-optimization-tu8tnj (PR #1741)", "head": "8d01991217f56d40666e31e13547202c2a8df8f2", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Production UI PDF position fail + DIRTY → merged main; removed redundant relative on document-frame-controls; CI re-running", + "outcome": "Production UI PDF position fail + DIRTY \u2192 merged main; removed redundant relative on document-frame-controls; CI re-running", "checks": "test:focused document-frame 16 passed; playwright smoke PDF-first mobile 1 passed; no provider-backed checks" }, { @@ -9890,7 +9889,7 @@ "ref": "claude/document-viewer-optimization-tu8tnj (PR #1754)", "head": "41b4bccf7d7229920c33344bec0d46e0f2e48b97", "scope": "heavy review-and-fix", - "outcome": "CONFLICT merge-tree on docs/outstanding-issues.md resolved: kept main #285 (Node/jsdom floor) + renumbered authorizationHeader trap to #286, next-id=287; merged origin/main; 1 unresolved review thread (comments 403 — skipped); no product code change", + "outcome": "CONFLICT merge-tree on docs/outstanding-issues.md resolved: kept main #285 (Node/jsdom floor) + renumbered authorizationHeader trap to #286, next-id=287; merged origin/main; 1 unresolved review thread (comments 403 \u2014 skipped); no product code change", "checks": "check:outstanding-issues PASS (284 rows, next-id=287); prettier --check docs/outstanding-issues.md PASS; ledger:dedupe none; no provider-backed checks" }, { @@ -9914,7 +9913,7 @@ "ref": "claude/ds-baseline-workflow (PR #1743)", "head": "753898f4982be38c3b3d11495caf3d30236b16a3", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "3 Codex threads (2 P1+1 P2) → partial refresh + refresh provenance + mask settle; threads disposition via later head", + "outcome": "3 Codex threads (2 P1+1 P2) \u2192 partial refresh + refresh provenance + mask settle; threads disposition via later head", "checks": "vitest adopt-visual-baselines 3 + design-system-adoption 51; no provider-backed checks" }, { @@ -9938,7 +9937,7 @@ "ref": "claude/ds-doc-corrections", "head": "534405600dca67317b4d60266cda03ec95f028e7", "scope": "M1 stranded doc corrections (docs/outstanding-issues.md #262/#266, docs/design-system/COMPONENTS.md TextField row + section 4)", - "outcome": "authored and handed off as PR #1719; every inherited figure re-measured against origin/main rather than copied forward, and the stranded version's 'eight shadow tokens, focus 2' claim was found wrong — LEGACY_SHADOW_ALIAS matches seven tokens and has never included focus", + "outcome": "authored and handed off as PR #1719; every inherited figure re-measured against origin/main rather than copied forward, and the stranded version's 'eight shadow tokens, focus 2' claim was found wrong \u2014 LEGACY_SHADOW_ALIAS matches seven tokens and has never included focus", "checks": "check:outstanding-issues pass (274 rows, unique ids, no ids deleted from base); prettier --check . pass whole-tree; legacyShadowAliases re-measured 228 via the contract's own analyzers; docs-only diff so no unit/lint/typecheck/browser gate applies" }, { @@ -9953,7 +9952,7 @@ "date": "2026-08-08", "ref": "claude/ds-tap-and-linkaction", "head": "6916c80526603514d91bd29d224959dd420af59c", - "scope": "M5 LinkAction tone refusal plus re-measured corrections to outstanding-issues #270, #118 and #269 — final reviewed head, adds the tone?: never fix, its type-contract test and both regenerated manifests", + "scope": "M5 LinkAction tone refusal plus re-measured corrections to outstanding-issues #270, #118 and #269 \u2014 final reviewed head, adds the tone?: never fix, its type-contract test and both regenerated manifests", "outcome": "PR #1720, superseding the 824c1b74a record. Codex found the Omit form still accepted tone through a spread; verified with a focused tsc probe before changing anything (Omit accepted the spread with no diagnostic, tone?: never rejected it with TS2345), because excess-property checking only fires on object literals. Fixed with tone?: never plus a type-level contract test that stops compiling if the prop widens back. CodeRabbit's future-dated finding fixed in ff307cc5b. CodeRabbit's ledger-scope finding does not apply: that row records a different ref and head and was accurate as written, but a superseding row for the final #1719 head was appended anyway since its scope grew after the review pass", "checks": "tsc -p tsconfig.typecheck.json --noEmit exit 0 zero diagnostics; lint exit 0; check:design-system-contract exit 0 (676 production files, legacy shadow aliases 228 confirming the #262 re-measure, adoption 53 components 55 roots, design-sync 53 components and 7 guidelines); check-icon-scale.mjs --strict exit 0; vitest threads pool 3 files 164 tests passed; check:outstanding-issues pass; check:branch-review-ledger pass; prettier --check . pass whole-tree; main merged in with merge-tree proven clean first and an id-set proof over both merge parents showing 274 ids each side, none lost, none invented" }, @@ -9970,7 +9969,7 @@ "ref": "claude/mode-routing-search-pages-jabe17", "head": "3a0bdd62466080ad713873cdd690ae600635a979", "scope": "mode routing: one shared home page at /, mode pill retargets the composer, /documents + /medications mode homes", - "outcome": "handoff — PR #1744 opened; 2 pre-existing failures verified at base bc33d41", + "outcome": "handoff \u2014 PR #1744 opened; 2 pre-existing failures verified at base bc33d41", "checks": "test:e2e:pr 406 passed/2 failed (both fail at base); vitest 5608 passed/1 failed (pre-existing); lint clean; tsc clean; sitemap:check, docs:check-index, docs:check-inventory, check:design-system-contract, check:outstanding-issues pass; verify:pr-local and verify:ui blocked by pre-existing installed-lock-parity (playwright 1.62.0 vs locked 1.62.1)" }, { @@ -9994,7 +9993,7 @@ "ref": "claude/mode-routing-search-pages-jabe17 (PR #1744)", "head": "e7a6b44cf4488228129fb2f7285904f9e040dcaa", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Static maintainability 4205>4140 + DIRTY → merged main; extracted payloads+home-mode-seed to 4124 lines; CI re-running", + "outcome": "Static maintainability 4205>4140 + DIRTY \u2192 merged main; extracted payloads+home-mode-seed to 4124 lines; CI re-running", "checks": "check:maintainability-budgets pass; typecheck; vitest clinical-dashboard-merge+search-route-ownership 25; no provider-backed checks" }, { @@ -10026,7 +10025,7 @@ "ref": "claude/planning-build-intelligence-9ot0nm (PR #1730)", "head": "fa616b11e8072ac3a94dd25e02c9c096983770f5", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "DIRTY → CLEAN at current head (auto-merge/sync); local merge push blocked by armed auto-merge sentinel", + "outcome": "DIRTY \u2192 CLEAN at current head (auto-merge/sync); local merge push blocked by armed auto-merge sentinel", "checks": "no local gates; no provider-backed checks" }, { @@ -10042,7 +10041,7 @@ "ref": "codex/lighthouse-hardening (PR #1746)", "head": "038058ea63837e7c4a90e84b7f8f860aacc51e13", "scope": "heavy review-and-fix", - "outcome": "CONFLICT merge-tree on lighthouse-budget.json resolved: kept main baseline measurements + this PR Lighthouse hardening (scripts/workflows/ci-change-scope); visual-baseline policy matches main; 3 unresolved threads (comments 403 — skipped)", + "outcome": "CONFLICT merge-tree on lighthouse-budget.json resolved: kept main baseline measurements + this PR Lighthouse hardening (scripts/workflows/ci-change-scope); visual-baseline policy matches main; 3 unresolved threads (comments 403 \u2014 skipped)", "checks": "ci-change-scope --self-test PASS; vitest check-lighthouse-budget+ci-cache-safety 84/84 PASS; no provider-backed checks" }, { @@ -10050,7 +10049,7 @@ "ref": "codex/lighthouse-hardening (PR #1746)", "head": "d4af6a6356de3327906936a237405e4e7ccba0cb", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "DIRTY + 3 Codex P2 + Static contract fail → main sync; process-group kill; suite deadline; normalized samples; contract test updated; threads unreplied (API 403)", + "outcome": "DIRTY + 3 Codex P2 + Static contract fail \u2192 main sync; process-group kill; suite deadline; normalized samples; contract test updated; threads unreplied (API 403)", "checks": "vitest live-web-vitals-inputs+check-lighthouse-budget 61; ci-cache-safety 32; no provider-backed checks" }, { @@ -10058,7 +10057,7 @@ "ref": "cursor/compact-services-result-text-9b7d (PR #1731)", "head": "bdaad2cc471e5b599205b2f1f265b2d8e1fdb43c", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "2 Codex P2 → skip placeholders in compactBestUseTitle; gate subtitle compaction to services mode; threads unreplied (API 403)", + "outcome": "2 Codex P2 \u2192 skip placeholders in compactBestUseTitle; gate subtitle compaction to services mode; threads unreplied (API 403)", "checks": "vitest services-catalog+document-search-record-fault 20 passed; no provider-backed checks" }, { @@ -10114,7 +10113,7 @@ "ref": "cursor/confirm-checklist-polish-195c (PR #1734)", "head": "e1385d67ce42023f1293a652efa9799f3eb9eb2d", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "DIRTY reported → already contained main; no code change this sweep", + "outcome": "DIRTY reported \u2192 already contained main; no code change this sweep", "checks": "no gates; no provider-backed checks" }, { @@ -10154,7 +10153,7 @@ "ref": "cursor/factsheets-compact-mockups-ad4c (PR #1728)", "head": "541f68bd1bcd29daa05805d8fce22034b21d5076", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "BEHIND + 2 Codex P2 threads → synced main; full comfortable list + ComfortableCards density; threads unreplied (API 403)", + "outcome": "BEHIND + 2 Codex P2 threads \u2192 synced main; full comfortable list + ComfortableCards density; threads unreplied (API 403)", "checks": "vitest factsheets-compact-view-mockups.dom 3 passed; tsc; no provider-backed checks" }, { @@ -10266,7 +10265,7 @@ "ref": "cursor/forms-results-bar-documents-style-13dc", "head": "fd148ca931ab9c023619deed98bae5af787e4253", "scope": "sync", - "outcome": "PR #1751 unblock: CONFLICTING→MERGEABLE; 11 behind main; merge-tree clean; merge commit fd148ca9 pushed; all static+unit+build+critical CI green; Production UI (1/2/3) pending", + "outcome": "PR #1751 unblock: CONFLICTING\u2192MERGEABLE; 11 behind main; merge-tree clean; merge commit fd148ca9 pushed; all static+unit+build+critical CI green; Production UI (1/2/3) pending", "checks": "merge-tree:clean,static-pr:pass,unit-coverage:pass,build:pass,production-ui-critical:pass,safety:pass,pr-policy:pass,production-ui-1/2/3:pending" }, { @@ -10290,7 +10289,7 @@ "ref": "cursor/phone-mode-dense-production-05c0 (PR #1648)", "head": "276a5cd02cfb8fb93d969e9e4db167576e054a42", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "DIRTY/master-search-header conflict → merged origin/main; phone dense + desktop tall rows preserved; CI re-running", + "outcome": "DIRTY/master-search-header conflict \u2192 merged origin/main; phone dense + desktop tall rows preserved; CI re-running", "checks": "vitest header-scroll-hide+mode-nav 55 passed; lint master-search-header; no provider-backed checks" }, { @@ -10322,7 +10321,7 @@ "ref": "cursor/run-pr-sweep-ledger-d56c (PR #1698)", "head": "ccf7284cbbe2315e5dc6a1bf126403a8a2205fa7", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: DIRTY/CONFLICTING, PR mergeability fail, behind 33, 0 threads, fake single-parent merge tip → after: real merge origin/main (conflicts resolved: docs/outstanding-issues.md + lighthouse-budget.json took main), merge-tree clean, unique diff ledger-only, 0 threads", + "outcome": "before: DIRTY/CONFLICTING, PR mergeability fail, behind 33, 0 threads, fake single-parent merge tip \u2192 after: real merge origin/main (conflicts resolved: docs/outstanding-issues.md + lighthouse-budget.json took main), merge-tree clean, unique diff ledger-only, 0 threads", "checks": "check:outstanding-issues pass; check:branch-review-ledger pass; ledger:dedupe none; merge-tree clean; format; no provider-backed checks run" }, { @@ -10346,7 +10345,7 @@ "ref": "cursor/safety-plan-phone-safe-area-624a (PR #1711)", "head": "0aa81baf1260991f92dd8646bd9cd52b4077a39b", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "DIRTY/ledger-only → merged origin/main via ledger driver; CI re-running", + "outcome": "DIRTY/ledger-only \u2192 merged origin/main via ledger driver; CI re-running", "checks": "ledger merge driver; no provider-backed checks" }, { @@ -10394,7 +10393,7 @@ "ref": "cursor/services-content-cleanup-1c73 (PR #1733)", "head": "af90c9017fd6c1c65fab0f40f96e155bd4f64f41", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "DIRTY/ledger sync + 2 Copilot threads → placeholder ranking + multi-clause criteria; threads unreplied (API 403)", + "outcome": "DIRTY/ledger sync + 2 Copilot threads \u2192 placeholder ranking + multi-clause criteria; threads unreplied (API 403)", "checks": "vitest services-catalog 16 passed; no provider-backed checks" }, { @@ -10410,7 +10409,7 @@ "ref": "cursor/site-testing-speed-08c1 (PR #1686)", "head": "632958dd63e320b3c1ae911ca0b025aaab78a478", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "DIRTY (ledger+outstanding-issues+scripts-index) → merged origin/main with careful unions; CI re-running", + "outcome": "DIRTY (ledger+outstanding-issues+scripts-index) \u2192 merged origin/main with careful unions; CI re-running", "checks": "check:outstanding-issues pass; ledger:dedupe; vitest playwright-revision+ci-cache-safety 33 passed; no provider-backed checks" }, { @@ -10442,7 +10441,7 @@ "ref": "dependabot/npm_and_yarn/js-yaml-4.3.1 (PR #1668)", "head": "e95160210e7801c1f4e863648ed6b48c8fbee71f", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "BEHIND → merged origin/main; Safety audit failed on transitive nanoid→bumped lock to 3.3.18; CI re-running", + "outcome": "BEHIND \u2192 merged origin/main; Safety audit failed on transitive nanoid\u2192bumped lock to 3.3.18; CI re-running", "checks": "npm audit --omit=dev --audit-level=high clean; no provider-backed checks" }, { @@ -10522,7 +10521,7 @@ "ref": "claude/handover-review-nlhuln", "head": "de8b74e2fb94d1ec9b1982c15a2dea43421c3eee", "scope": "outstanding-issues ledger capture after the mode-nav rollout (PR #1685) (supersedes 2026-08-07)", - "outcome": "Confirmed #256's two remaining suspected section sets are dead (/forms/ and /differentials/presentations/ draw no section nav; form-decision-context-mobile is a testId not an id; ruled out sectionId indirection in both files). Added #271 (delete-or-keep the consumer-less action kind) and #272 (addon-slot single-owner rule held by two lists agreeing by coincidence) — renumbered from this PR's original #261/#262 because main claimed #261-#270 via PR #1678 design-system tracks in the interim. #207/#226/#231 reviewed and deliberately left untouched as existing P1 rows.", + "outcome": "Confirmed #256's two remaining suspected section sets are dead (/forms/ and /differentials/presentations/ draw no section nav; form-decision-context-mobile is a testId not an id; ruled out sectionId indirection in both files). Added #271 (delete-or-keep the consumer-less action kind) and #272 (addon-slot single-owner rule held by two lists agreeing by coincidence) \u2014 renumbered from this PR's original #261/#262 because main claimed #261-#270 via PR #1678 design-system tracks in the interim. #207/#226/#231 reviewed and deliberately left untouched as existing P1 rows.", "checks": "check:outstanding-issues passed (270 rows, 129 open, 141 archived, unique ids, next-id=273 above the highest, no ids deleted from base d32dd549a3dd); prettier --check clean on the changed file; rows written via scripts/outstanding-issues.mjs, never hand-edited; no code gates run - docs-only diff" }, { @@ -10530,7 +10529,7 @@ "ref": "claude/handover-review-nlhuln (PR #1685)", "head": "e200e589938c8dac2d3f76ef42ed1639b3fde18e", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: behind 1, checks green, 0 threads → after: merged origin/main (conflicts: none); PR required SUCCESS; 0 threads", + "outcome": "before: behind 1, checks green, 0 threads \u2192 after: merged origin/main (conflicts: none); PR required SUCCESS; 0 threads", "checks": "merge-tree clean; git merge origin/main + push; no provider-backed checks run" }, { @@ -10546,7 +10545,7 @@ "ref": "claude/issues-256-section-nav-clean (PR #1697)", "head": "2b99db1f00c42fd7c11c4bf8acbad904ef5003e1", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: DIRTY/PR mergeability fail, behind 3, merge-tree CLEAN, 0 threads → after: merged origin/main (conflicts: none), CI re-running; 0 threads", + "outcome": "before: DIRTY/PR mergeability fail, behind 3, merge-tree CLEAN, 0 threads \u2192 after: merged origin/main (conflicts: none), CI re-running; 0 threads", "checks": "merge-tree clean; git merge origin/main + push; no provider-backed checks run" }, { @@ -10586,7 +10585,7 @@ "ref": "claude/search-bar-mobile-layout-buu0io (PR #1689)", "head": "a152ffd89c962e3589509c0c3740dc429264063a", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: behind 1, required CI green (advisory lighthouse fail ignored), 1 CodeRabbit lighthouse baseline thread (human disagreement in progress) → after: waited for CI settle, disabled automerge, merged origin/main, pushed, re-enabled automerge; thread left open for human", + "outcome": "before: behind 1, required CI green (advisory lighthouse fail ignored), 1 CodeRabbit lighthouse baseline thread (human disagreement in progress) \u2192 after: waited for CI settle, disabled automerge, merged origin/main, pushed, re-enabled automerge; thread left open for human", "checks": "settled CI then merge+push; no provider-backed checks run; advisory lighthouse not chased" }, { @@ -10642,7 +10641,7 @@ "ref": "cursor/clinician-workflow-mockups-2b63 (PR #1662)", "head": "42ccad8ecc2889612e8f25ba79bb26a19e0a8baa", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: behind 17, checks green, 0 threads → after: merged origin/main (conflicts: none), CI re-running; 0 threads", + "outcome": "before: behind 17, checks green, 0 threads \u2192 after: merged origin/main (conflicts: none), CI re-running; 0 threads", "checks": "merge-tree clean; git merge origin/main + push; no provider-backed checks run" }, { @@ -10714,7 +10713,7 @@ "ref": "cursor/phone-mode-dense-production-05c0 (PR #1648)", "head": "4e0cca2ccbc19ed676765b029642da0afea6215a", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: behind 17, checks green, 0 threads → after: merged origin/main (conflicts: none), CI re-running; 0 threads", + "outcome": "before: behind 17, checks green, 0 threads \u2192 after: merged origin/main (conflicts: none), CI re-running; 0 threads", "checks": "merge-tree clean; git merge origin/main + push; no provider-backed checks run" }, { @@ -10730,7 +10729,7 @@ "ref": "cursor/pr-1676-unblock-ledger-ef51 (PR #1677)", "head": "89e25e97d442ebbbc7d33e87edec37ef42090486", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: DIRTY/PR mergeability fail, behind 1, merge-tree CLEAN, 0 threads → after: merged origin/main (conflicts: none), CI re-running; 0 threads", + "outcome": "before: DIRTY/PR mergeability fail, behind 1, merge-tree CLEAN, 0 threads \u2192 after: merged origin/main (conflicts: none), CI re-running; 0 threads", "checks": "merge-tree clean; git merge origin/main + push; no provider-backed checks run" }, { @@ -10754,7 +10753,7 @@ "ref": "cursor/privacy-live-signal-variants-bc81 (PR #1676)", "head": "7dd4ea9b1ce17777f2d0ac6bd95bb916cd69758f", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: DIRTY/PR mergeability fail, behind 2, merge-tree CLEAN, 0 threads → after: merged origin/main (conflicts: none), CI re-running; 0 threads", + "outcome": "before: DIRTY/PR mergeability fail, behind 2, merge-tree CLEAN, 0 threads \u2192 after: merged origin/main (conflicts: none), CI re-running; 0 threads", "checks": "merge-tree clean; git merge origin/main + push; no provider-backed checks run" }, { @@ -10778,7 +10777,7 @@ "ref": "cursor/remove-specifiers-back-arrow-f1c4", "head": "095791235d58a6309b21b139911a1aad9fe9086b", "scope": "specifiers-search-results-breadcrumb", - "outcome": "removed lone ← Specifiers crumb from search results; deep pages unchanged", + "outcome": "removed lone \u2190 Specifiers crumb from search results; deep pages unchanged", "checks": "format,typecheck,lint,ensure+phone-spot-check" }, { @@ -10802,7 +10801,7 @@ "ref": "cursor/settings-features-mockups-97ac (PR #1657)", "head": "d64288ce0f2f111b1838ded31a23d0020b38da8b", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: behind 17, checks green, 0 threads → after: merged origin/main (conflicts: none), CI re-running; 0 threads", + "outcome": "before: behind 17, checks green, 0 threads \u2192 after: merged origin/main (conflicts: none), CI re-running; 0 threads", "checks": "merge-tree clean; git merge origin/main + push; no provider-backed checks run" }, { @@ -10810,7 +10809,7 @@ "ref": "cursor/ship-first-redesign-mockups-2398 (PR #1654)", "head": "9d9eb0be47073a7f051a5885359b82f2ff978a85", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: behind 17, checks green, 0 threads → after: merged origin/main (conflicts: none), CI re-running; 0 threads", + "outcome": "before: behind 17, checks green, 0 threads \u2192 after: merged origin/main (conflicts: none), CI re-running; 0 threads", "checks": "merge-tree clean; git merge origin/main + push; no provider-backed checks run" }, { @@ -10834,8 +10833,8 @@ "ref": "cursor/site-testing-speed-08c1 (PR #1686)", "head": "71b57ea5ce0c46c16c42c07e66933836ae609b6a", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: DIRTY + Static PR fail (docs inventory stale) + PR required fail, merge-tree CLEAN → after: merged origin/main, docs:update inventory, pushed; CI re-running; 0 threads", - "checks": "docs:check-inventory fail→docs:update; format via Prettier; no provider-backed checks run" + "outcome": "before: DIRTY + Static PR fail (docs inventory stale) + PR required fail, merge-tree CLEAN \u2192 after: merged origin/main, docs:update inventory, pushed; CI re-running; 0 threads", + "checks": "docs:check-inventory fail\u2192docs:update; format via Prettier; no provider-backed checks run" }, { "date": "2026-08-07", @@ -10866,7 +10865,7 @@ "ref": "cursor/tools-search-mockups-72e1 (PR #1653)", "head": "a7fbc26a917b347d90c6bab1e6c1b2ede6422263", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: behind 17, checks green, 0 threads → after: merged origin/main (conflicts: none), CI re-running; 0 threads", + "outcome": "before: behind 17, checks green, 0 threads \u2192 after: merged origin/main (conflicts: none), CI re-running; 0 threads", "checks": "merge-tree clean; git merge origin/main + push; no provider-backed checks run" }, { @@ -10890,15 +10889,15 @@ "ref": "cursor/viewer-phase2a-frame-controls-1db8 (PR #1687)", "head": "5c10730be1641a386ee8c8476778933588a822fc", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: up to date with main, Static PR fail (format:changed pdf-canvas-viewer), 1 outdated CodeRabbit thread (ref sync) already fixed on head → after: prettier format fix pushed; thread left open (no review-write API as cursor[bot]); CI re-running", - "checks": "format:changed fail→prettier --write pdf-canvas-viewer.tsx; format:changed PASS locally; no provider-backed checks run" + "outcome": "before: up to date with main, Static PR fail (format:changed pdf-canvas-viewer), 1 outdated CodeRabbit thread (ref sync) already fixed on head \u2192 after: prettier format fix pushed; thread left open (no review-write API as cursor[bot]); CI re-running", + "checks": "format:changed fail\u2192prettier --write pdf-canvas-viewer.tsx; format:changed PASS locally; no provider-backed checks run" }, { "date": "2026-08-07", "ref": "cursor/viewer-phase2c-rail-filmstrip-1db8 (PR #1707)", "head": "af52b592bd22794f5cf96cbca0fb27f2d6bbb3e3", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Not behind main, no merge needed (mergeable_state 'blocked' was just the failing required check). Fixed the real Unit coverage CI failure: tests/document-image-filmstrip.dom.test.tsx still asserted the stale aria-current='true' after the component was already fixed to emit 'page' for an earlier a11y review finding -- exactly matched an unresolved CodeRabbit finding, applied its suggested fix. Also fixed an unresolved LOW-severity Sentry finding (image metadata line could start with a leading ' · ' separator when image_type is falsy) by collecting parts into an array and filter+join instead of individually prefixing. All 4 review threads now resolved (2 new fixes + 2 already-fixed-on-branch copilot threads).", + "outcome": "Not behind main, no merge needed (mergeable_state 'blocked' was just the failing required check). Fixed the real Unit coverage CI failure: tests/document-image-filmstrip.dom.test.tsx still asserted the stale aria-current='true' after the component was already fixed to emit 'page' for an earlier a11y review finding -- exactly matched an unresolved CodeRabbit finding, applied its suggested fix. Also fixed an unresolved LOW-severity Sentry finding (image metadata line could start with a leading ' \u00b7 ' separator when image_type is falsy) by collecting parts into an array and filter+join instead of individually prefixing. All 4 review threads now resolved (2 new fixes + 2 already-fixed-on-branch copilot threads).", "checks": "eslint on both fixed files (clean); local vitest blocked by environment-wide missing tailwind-merge dependency -- relying on CI" }, { @@ -10914,7 +10913,7 @@ "ref": "dependabot/npm_and_yarn/js-yaml-4.3.1 (PR #1668)", "head": "a7dde7e6101ed69fb43f004981be9500ba773105", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: behind 17, checks green, 0 threads → after: merged origin/main (conflicts: none), CI re-running; 0 threads", + "outcome": "before: behind 17, checks green, 0 threads \u2192 after: merged origin/main (conflicts: none), CI re-running; 0 threads", "checks": "merge-tree clean; git merge origin/main + push; no provider-backed checks run" }, { @@ -10938,7 +10937,7 @@ "ref": "claude/ds-truth-fixes", "head": "7a9c41a971aa9111f050cd39d4429ada1b3f4409", "scope": "PR #1655 heavy review-and-fix", - "outcome": "fixed DownloadLink tone DOM leak + stale ToggleSwitch/Links §9 docs; merge-tree clean; verify:cheap+verify:pr-local green; CI re-queued after push", + "outcome": "fixed DownloadLink tone DOM leak + stale ToggleSwitch/Links \u00a79 docs; merge-tree clean; verify:cheap+verify:pr-local green; CI re-queued after push", "checks": "bugbot+deep-review; vitest ui-primitives+ui-v2 60p; verify:cheap 5448p; verify:pr-local format+lint+typecheck+test+build+rag-fixtures; no provider gates" }, { @@ -10946,7 +10945,7 @@ "ref": "claude/implement-97vpz7", "head": "00ab7bfd34684bc854d15a3f28987674098a7130", "scope": "PR #1646 soft-tail answer-cache skip + soft-tail test hardening", - "outcome": "fixed — answer-path soft-tail skip via rag-query-guard helpers; soft-tail fixture pins; duplicate memo test removed; in-corpus assert narrowed; budget 4362", + "outcome": "fixed \u2014 answer-path soft-tail skip via rag-query-guard helpers; soft-tail fixture pins; duplicate memo test removed; in-corpus assert narrowed; budget 4362", "checks": "test:rag-query-guard+unsupported-cache+classifier-memo 22/22,check:maintainability-budgets 4362/4362" }, { @@ -10978,7 +10977,7 @@ "ref": "claude/pr-handoff-stop-hook (PR #1649)", "head": "3403126bc6cd86145d6921a3fe4d081181e8a113", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: 5 unresolved threads (Devin create-from-output + 4 CodeRabbit), mergeable/BLOCKED, Actions major outage leaving CI pending; after: hardened jq-less input/output separation + session fail-open + prefix unlock + tests (9 passed) in 3403126bc6cd86145d6921a3fe4d081181e8a113, threads replied+resolved, branch current with main, CI re-triggered (Actions outage — not babysat)", + "outcome": "before: 5 unresolved threads (Devin create-from-output + 4 CodeRabbit), mergeable/BLOCKED, Actions major outage leaving CI pending; after: hardened jq-less input/output separation + session fail-open + prefix unlock + tests (9 passed) in 3403126bc6cd86145d6921a3fe4d081181e8a113, threads replied+resolved, branch current with main, CI re-triggered (Actions outage \u2014 not babysat)", "checks": "npx vitest run tests/pr-handoff-stop.test.ts (9 passed); bash -n hook OK; no provider-backed checks run" }, { @@ -10986,7 +10985,7 @@ "ref": "claude/pr-handoff-stop-hook (PR #1649)", "head": "36c1bccd89f976bcae3dabf8f5787198db5df078", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: 5 unresolved threads (Devin create-from-output + 4 CodeRabbit), mergeable/BLOCKED, Actions major outage leaving CI pending; after: hardened jq-less input/output separation + session fail-open + prefix unlock + tests (9 passed) in 36c1bccd89f976bcae3dabf8f5787198db5df078, threads replied+resolved, branch current with main, CI re-triggered (Actions outage — not babysat)", + "outcome": "before: 5 unresolved threads (Devin create-from-output + 4 CodeRabbit), mergeable/BLOCKED, Actions major outage leaving CI pending; after: hardened jq-less input/output separation + session fail-open + prefix unlock + tests (9 passed) in 36c1bccd89f976bcae3dabf8f5787198db5df078, threads replied+resolved, branch current with main, CI re-triggered (Actions outage \u2014 not babysat)", "checks": "npx vitest run tests/pr-handoff-stop.test.ts (9 passed); bash -n hook OK; no provider-backed checks run" }, { @@ -10994,7 +10993,7 @@ "ref": "claude/pr-handoff-stop-hook (PR #1649)", "head": "f67e5c9103c3e1483ad8e034fe7a6757c2362d74", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: 5 unresolved threads (Devin create-from-output + 4 CodeRabbit), mergeable/BLOCKED, Actions major outage leaving CI pending; after: hardened jq-less input/output separation + session fail-open + prefix unlock + tests (9 passed) in f67e5c9103c3e1483ad8e034fe7a6757c2362d74, threads replied+resolved, branch current with main, CI re-triggered (Actions outage — not babysat)", + "outcome": "before: 5 unresolved threads (Devin create-from-output + 4 CodeRabbit), mergeable/BLOCKED, Actions major outage leaving CI pending; after: hardened jq-less input/output separation + session fail-open + prefix unlock + tests (9 passed) in f67e5c9103c3e1483ad8e034fe7a6757c2362d74, threads replied+resolved, branch current with main, CI re-triggered (Actions outage \u2014 not babysat)", "checks": "npx vitest run tests/pr-handoff-stop.test.ts (9 passed); bash -n hook OK; no provider-backed checks run" }, { @@ -11002,7 +11001,7 @@ "ref": "claude/pr-handoff-stop-hook (PR #1649)", "head": "fff524d73ebfafeef7bdc50752a6d14f253ebc2e", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: 5 unresolved threads (Devin create-from-output + 4 CodeRabbit), mergeable/BLOCKED, Actions major outage leaving CI pending; after: hardened jq-less input/output separation + session fail-open + prefix unlock + tests (9 passed) in fff524d73ebfafeef7bdc50752a6d14f253ebc2e, threads replied+resolved, branch current with main, CI re-triggered (Actions outage — not babysat)", + "outcome": "before: 5 unresolved threads (Devin create-from-output + 4 CodeRabbit), mergeable/BLOCKED, Actions major outage leaving CI pending; after: hardened jq-less input/output separation + session fail-open + prefix unlock + tests (9 passed) in fff524d73ebfafeef7bdc50752a6d14f253ebc2e, threads replied+resolved, branch current with main, CI re-triggered (Actions outage \u2014 not babysat)", "checks": "npx vitest run tests/pr-handoff-stop.test.ts (9 passed); bash -n hook OK; no provider-backed checks run" }, { @@ -11018,7 +11017,7 @@ "ref": "claude/settings-nav-freeze-desktop-tdzh7z (PR #1641)", "head": "d4ecd2b5fc48a8d8f37f081cac2d80beb749df01", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: mergeable/BLOCKED, 0 unresolved threads, 0 behind main; prior CI reds were infra (npm ECONNRESET on Unit coverage; e7f380f3 cancelled at Set up job). after: pushed d4ecd2b5 ResizeObserver pin-clamp distance reset; all review threads remain resolved; CI re-triggered but GitHub Actions major_outage — runs pending/queued, no product failure to fix; merge tree clean", + "outcome": "before: mergeable/BLOCKED, 0 unresolved threads, 0 behind main; prior CI reds were infra (npm ECONNRESET on Unit coverage; e7f380f3 cancelled at Set up job). after: pushed d4ecd2b5 ResizeObserver pin-clamp distance reset; all review threads remain resolved; CI re-triggered but GitHub Actions major_outage \u2014 runs pending/queued, no product failure to fix; merge tree clean", "checks": "local typecheck PASS; local lint (settings-dialog) PASS; format unchanged; no provider-backed checks run; hosted CI awaiting Actions recovery (run 31120931239)" }, { @@ -11250,7 +11249,7 @@ "ref": "cursor/ledger-fastest-wins-capture-1479", "head": "b03b51d7b22671f2734115b5fef469bd2e932ae3", "scope": "prlanded PR #1624", - "outcome": "MERGED squash b03b51d7; 118/118 open↔queue, A1 #226 at order 5, #249–#251; orphaned #250 acuity clarify → fix-forward", + "outcome": "MERGED squash b03b51d7; 118/118 open\u2194queue, A1 #226 at order 5, #249\u2013#251; orphaned #250 acuity clarify \u2192 fix-forward", "checks": "check:outstanding-issues PASS on merge head; Bugbot clean after clarify" }, { @@ -11305,7 +11304,7 @@ "date": "2026-08-04", "ref": "claude/ds-v2-empty-state-heading", "head": "5c1c1b32c8efb030a8603ac281c59108b842798d", - "scope": "PR #1612 — EmptyState headingLevel (#217), /dsm/search heading (#224), document-search empty-state adoption, ledger #230", + "scope": "PR #1612 \u2014 EmptyState headingLevel (#217), /dsm/search heading (#224), document-search empty-state adoption, ledger #230", "outcome": "self-review clean; no findings raised", "checks": "typecheck 0; lint 0; vitest 5085 passed/3 skipped; verify:ui 347 passed; prettier whole-tree clean; verify:pr-local exit 0" }, @@ -11337,7 +11336,7 @@ "date": "2026-08-04", "ref": "claude/top-search-design-mockups-w53znc", "head": "b432448e4893a42d07558aff0dc04be797971231", - "scope": "PR #1611 — results-band shelf Clear filter-only, memo deps, restored tests", + "scope": "PR #1611 \u2014 results-band shelf Clear filter-only, memo deps, restored tests", "outcome": "Fixed two Qodo findings from merged #1555; mutation-tested guard added", "checks": "tsc 0; eslint 0; vitest 4 files/59 tests; verify:pr-local blocked by lock parity (node 24.13 vs jsdom@30)" }, @@ -11363,14 +11362,14 @@ "head": "6cc0b6ffdae3b515a05a17f2a87e5f51e5347263", "scope": "PR review + fix (ingestion-autopilot service-role exposure) (supersedes 2026-08-02)", "outcome": "Supersedes the earlier row to record decisive gate results; historical review outcome otherwise unchanged.", - "checks": "PASS: npm run test:ci-workflows — 206/206 passed; PASS: focused ci-cache-safety + ingestion-autopilot-workflow — 21/21 passed; PASS: npm run check:github-actions — GitHub Actions pin check passed; PASS: prettier --check — all matched files use Prettier code style; PASS: git diff --check — clean. No provider calls." + "checks": "PASS: npm run test:ci-workflows \u2014 206/206 passed; PASS: focused ci-cache-safety + ingestion-autopilot-workflow \u2014 21/21 passed; PASS: npm run check:github-actions \u2014 GitHub Actions pin check passed; PASS: prettier --check \u2014 all matched files use Prettier code style; PASS: git diff --check \u2014 clean. No provider calls." }, { "date": "2026-08-04", "ref": "codex/fix-mode-switching-and-loading-issues", "head": "3e3b224a2ec13928d1e28173b1fc4c75d202d7d2", "scope": "PR #1607 unblock/fix", - "outcome": "clean — behind 0, merge-tree clean, 0 unresolved threads, required CI in progress (no code fix)", + "outcome": "clean \u2014 behind 0, merge-tree clean, 0 unresolved threads, required CI in progress (no code fix)", "checks": "merge-tree clean; behind_by 0; Unit/Build/Static/ProdUI in progress; no failing required" }, { @@ -11618,7 +11617,7 @@ "ref": "claude/ds-v2-architecture", "head": "157373700281f81f136275c56c9a82fb22776d99", "scope": "PR-Arch Wave4 motion/z/overlays/print", - "outcome": "local gates green; frontend-ui-reviewer API-limited — glance required before auto-merge", + "outcome": "local gates green; frontend-ui-reviewer API-limited \u2014 glance required before auto-merge", "checks": "unit 4972p; e2e:critical 15p; verify:ui 347p; verify:pr-local 0; eval:rag:offline pass" }, { @@ -11642,7 +11641,7 @@ "ref": "claude/ds-v2-architecture", "head": "93bb4b4756a7fad22f93008325f2c0f72471b0db", "scope": "PR-Arch Wave4 motion/z/overlays/print", - "outcome": "local gates green; frontend-ui-reviewer API-limited — glance required before auto-merge", + "outcome": "local gates green; frontend-ui-reviewer API-limited \u2014 glance required before auto-merge", "checks": "unit 4972p; e2e:critical 15p; verify:ui 347p; verify:pr-local 0; eval:rag:offline pass" }, { @@ -11650,7 +11649,7 @@ "ref": "claude/ds-v2-values", "head": "48012d359b84daae347201697c82f3e433c182c5", "scope": "PR #1571 review-and-fix (ds-v2-values tap/radius)", - "outcome": "fixed: Tools submit + account-setup close onto h-tap; phone composer input 44px pin; gate 2 demoted to implemented-partial; SPEC 407→426; short-runway/short-answer smoke pins retuned; verify:cheap + verify:pr-local + 2 smoke tests green; CI Production UI in progress", + "outcome": "fixed: Tools submit + account-setup close onto h-tap; phone composer input 44px pin; gate 2 demoted to implemented-partial; SPEC 407\u2192426; short-runway/short-answer smoke pins retuned; verify:cheap + verify:pr-local + 2 smoke tests green; CI Production UI in progress", "checks": "verify:cheap 471/4879; verify:pr-local build+fixtures; test:e2e 2 phone smoke passed; design-system-contract raw 2/0/0" }, { @@ -11794,7 +11793,7 @@ "ref": "claude/top-search-design-mockups-w53znc", "head": "4f4440fd6776742f5de203ee15295f372205321d", "scope": "search results bar: scope-system deletion, filter shelf, bar anatomy", - "outcome": "Handoff for PR #1555. Deleted the inert command-scope system (voided props, six modes' scope config, three matchers, four no-op call sites, the original shelf) — behaviour-preserving because every matcher early-returned true on a permanently-empty array. Rebuilt the applied-filter shelf prop-driven on live facet data, scoped to documents and therapy-compass. Landed the bar anatomy: tile spinner and funnel states, Filter to the right edge, Sort inboard. Study step 6 (remove the library button) deliberately declined — the nav route clears the query via onSearchModeChange. Ledger #182 closed.", + "outcome": "Handoff for PR #1555. Deleted the inert command-scope system (voided props, six modes' scope config, three matchers, four no-op call sites, the original shelf) \u2014 behaviour-preserving because every matcher early-returned true on a permanently-empty array. Rebuilt the applied-filter shelf prop-driven on live facet data, scoped to documents and therapy-compass. Landed the bar anatomy: tile spinner and funnel states, Filter to the right edge, Sort inboard. Study step 6 (remove the library button) deliberately declined \u2014 the nav route clears the query via onSearchModeChange. Ledger #182 closed.", "checks": "verify:pr-local exit 0 (460 files / 4796 tests, production build, client-bundle secret scan, RAG fixtures 36 cases / 23 suites); ui-tools 87 passed; ui-smoke + ui-accessibility 108 passed 1 failed (pre-existing PDF-canvas test, fails identically stashed, Chromium 1194 vs pinned 1228); mutation-tested the shelf's survives-loading guard" }, { @@ -11833,7 +11832,7 @@ "date": "2026-07-31", "ref": "1489", "head": "67d5cb91083f9b0e9d3017816cbf68abab102688", - "scope": "PR 1489 review — Therapy startup/sidebar perf, catalogue split, bundle-budget, phone-chrome", + "scope": "PR 1489 review \u2014 Therapy startup/sidebar perf, catalogue split, bundle-budget, phone-chrome", "outcome": "approved with follow-ups; merged 945148251. No P0/P1. Findings fixed on claude/pr-1489-review-786e01: inferred modality mislabelled ECT/rTMS as ACT and Psychoanalysis as CBT (pre-existing on main); hashed catalogue assets never pruned (2 stranded in-PR); classifyPullRequestFiles returned clinicalRisk:false for 205 clinical records; viewportHeightChanged guard outranked topRevealOffset; guard keyed innerHeight not visualViewport; sk-proj- keys unescaped; bundle-budget step timeout 3m too tight. Bundling note: operationalRisk+clinicalRisk in one squash, so no per-item revert.", "checks": "verify:cheap static gates pass; lint pass; typecheck exit 0; vitest 449 files/4700 pass; verify:phone-chrome contracts 116 pass + focused browser 13 pass; verify:ui 342 pass/2 fail, both pass isolated (composer hero-vs-dock hydration race, no position: assignment in use-hide-on-scroll)" }, @@ -11930,7 +11929,7 @@ "ref": "claude/issues-133-evidence", "head": "37f71f02f731175e4fed500f95529c3ef9eb568f", "scope": "PR #1506 reopen prep: sync main, renumber hazard to #155, supersede #112 residual", - "outcome": "READY — conflict cleared vs origin/main; main #154 preserved; hazard=#155 with archived #112 residual cross-link; med-accent=#156; false #155 evidence clause removed; Codex P2 addressed; Bugbot P1/P2 fixed; PR left CLOSED", + "outcome": "READY \u2014 conflict cleared vs origin/main; main #154 preserved; hazard=#155 with archived #112 residual cross-link; med-accent=#156; false #155 evidence clause removed; Codex P2 addressed; Bugbot P1/P2 fixed; PR left CLOSED", "checks": "check:outstanding-issues 154 rows/46 open next-id=157; check:branch-review-ledger 277 live; merge-tree clean da0c63d0; format no-op" }, { @@ -11946,7 +11945,7 @@ "ref": "claude/issues-writer-cli (PR #1524)", "head": "83dec1f5a36d577c87ee9a5382ef8431d197d93d", "scope": "PR #1524 review+bugbot+fix", - "outcome": "before: dirty/CONFLICTING vs main (outstanding-issues.md + scripts-index.md), missing pull_request CI, 0 review threads, NOT REVIEWED. after: merged origin/main (prefer main queues; renumbered this PR collision-free-ids note #159→#168, next-id=169); fixed wrong skill/writer cite #154→#156/#168; no other P0–P2 writer defects; 0 threads. Residual: concurrent id RMW (#156/#168) still open.", + "outcome": "before: dirty/CONFLICTING vs main (outstanding-issues.md + scripts-index.md), missing pull_request CI, 0 review threads, NOT REVIEWED. after: merged origin/main (prefer main queues; renumbered this PR collision-free-ids note #159\u2192#168, next-id=169); fixed wrong skill/writer cite #154\u2192#156/#168; no other P0\u2013P2 writer defects; 0 threads. Residual: concurrent id RMW (#156/#168) still open.", "checks": "check:outstanding-issues pass (166 rows, next-id=169); outstanding-issues.mjs --self-test pass; vitest tests/outstanding-issues-writer.test.ts 8/8; merge-tree clean vs origin/main; format clean; no provider-backed checks" }, { @@ -11994,7 +11993,7 @@ "ref": "claude/sentry-agent-monitoring-eri94v", "head": "38378ac78c0b288b6e93b638019653001f375042", "scope": "Sentry AI agent monitoring (OpenAI wrap, gen_ai scrubber allowlist, conversation id)", - "outcome": "pass — metadata-only instrumentation; privacy boundary preserved", + "outcome": "pass \u2014 metadata-only instrumentation; privacy boundary preserved", "checks": "verify:pr-local,verify:cheap,typecheck,vitest 458 files green" }, { @@ -12002,7 +12001,7 @@ "ref": "claude/sentry-agent-monitoring-eri94v", "head": "d521fe9dc4ce50e94273a77ee819332afc5bc7e1", "scope": "Ingestion-worker Sentry error reporting (worker/observability.ts, SAFE_TAGS worker keys, @sentry/node direct dep, docs + ledger #183)", - "outcome": "pass — additive capture only; privacy scrubbers reused, worker events pinned by tests", + "outcome": "pass \u2014 additive capture only; privacy scrubbers reused, worker events pinned by tests", "checks": "verify:pr-local exit 0 (460 files/4794 tests, build, eval:rag:offline),build:worker,npm ci --dry-run,check:outstanding-issues" }, { @@ -12082,7 +12081,7 @@ "ref": "codex/address-performance-issues-in-package", "head": "caced05a1bd9f0047e14ce5ab21d56f03f8ce0ec", "scope": "PR #1489 review+bugbot+fix+heavy", - "outcome": "fixed Build bundle-budget post-success hang (CI timeout→cancelled); stream measure + exitProcess failsafe + 3m step timeout; supersedes a861c968/2257c221", + "outcome": "fixed Build bundle-budget post-success hang (CI timeout\u2192cancelled); stream measure + exitProcess failsafe + 3m step timeout; supersedes a861c968/2257c221", "checks": "vitest bundle-budget 14/14; check:bundle-budget done; check:github-actions passed" }, { @@ -12322,7 +12321,7 @@ "ref": "codex/reduce-catalogue-json-bundle-weight", "head": "4d1f776ae77c26b2b323caad2eb43651f5b823bd", "scope": "PR #1468 review+bugbot+fix+heavy", - "outcome": "PASS heavy: synced main (DIRTY→clean); no PR-introduced P0/P1/P2; Production UI #146 Services settle flake dispositioned as pre-existing (not cache-caused); required CI expected after sync push", + "outcome": "PASS heavy: synced main (DIRTY\u2192clean); no PR-introduced P0/P1/P2; Production UI #146 Services settle flake dispositioned as pre-existing (not cache-caused); required CI expected after sync push", "checks": "merge-tree clean; verify:cheap 445 files/4659 passed; verify:pr-local + rag fixtures; check:github-actions prior; bugbot+diff review" }, { @@ -12930,7 +12929,7 @@ "ref": "claude/organize-local-worktree-d22bc3", "head": "2f26a53b5aeb3df451cf7b1d04f80b07edf0d6fe", "scope": "docs organisation: dated-record filing, docs index gaps, orientation maps", - "outcome": "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", + "outcome": "PR #1436 opened \u2014 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", "checks": "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" }, { @@ -12986,7 +12985,7 @@ "ref": "claude/test-coverage-analysis-2vcd8a", "head": "4f498b66a56b2a7eddde6c841a79621f23b59cc7", "scope": "PR #1398 babysit", - "outcome": "BLOCKER CLEARED: CONFLICTING due to docs/outstanding-issues.md vs main (#115 band-adoption follow-up). Kept main #115 + next-id=116; preserved PR #109 single-branch/refspec update. Prior tip had no GitHub CI suite (only PR Policy/CircleCI) — push retriggered full CI. 0 review threads; 0 Bugbot findings.", + "outcome": "BLOCKER CLEARED: CONFLICTING due to docs/outstanding-issues.md vs main (#115 band-adoption follow-up). Kept main #115 + next-id=116; preserved PR #109 single-branch/refspec update. Prior tip had no GitHub CI suite (only PR Policy/CircleCI) \u2014 push retriggered full CI. 0 review threads; 0 Bugbot findings.", "checks": "verify:cheap PASS (432 files, 4467 passed | 4 skipped); repo-hygiene 38/38; sweep:branch-ledger --no-fetch exit 0; format:changed PASS; Bugbot none; hosted CI re-triggered on tip" }, { @@ -12994,7 +12993,7 @@ "ref": "claude/test-coverage-analysis-2vcd8a", "head": "d5842e62238237ff5c47da0b32ef8d9f12819714", "scope": "PR #1398 babysit", - "outcome": "COMPLETE for tip: cleared main conflict; fixed Codex P2 (reject refs/*→origin/* nesting); prior Codex P2 (destination check) already fixed in de594186 and resolved; 0 unresolved threads; merge-tree clean. Hosted CI re-running.", + "outcome": "COMPLETE for tip: cleared main conflict; fixed Codex P2 (reject refs/*\u2192origin/* nesting); prior Codex P2 (destination check) already fixed in de594186 and resolved; 0 unresolved threads; merge-tree clean. Hosted CI re-running.", "checks": "repo-hygiene 40/40; verify:cheap earlier PASS on pre-tip; format:changed PASS; Bugbot none; Codex P2 resolved" }, { @@ -13034,7 +13033,7 @@ "ref": "claude/white-element-positioning-t607pk", "head": "db341491b0d94cf11641eb98aa8726629580a652", "scope": "phone-chrome safe-area paint fix", - "outcome": "APPROVED — no P0/P1. One P2 pre-existing residual (spacer/bar mismatch on notched tablet sm+ in PWA mode — worse before, slightly better after; no action needed). P3: contract test slice brittleness (indexOf '/>') and invariant-6 prose length. No defects introduced.", + "outcome": "APPROVED \u2014 no P0/P1. One P2 pre-existing residual (spacer/bar mismatch on notched tablet sm+ in PWA mode \u2014 worse before, slightly better after; no action needed). P3: contract test slice brittleness (indexOf '/>') and invariant-6 prose length. No defects introduced.", "checks": "vitest header-scroll-hide-contract 27/27 green; source read: master-search-header.tsx, globals.css forced-colors block, tests/header-scroll-hide-contract.test.ts, docs/search-chrome-behaviour.md" }, { @@ -13058,7 +13057,7 @@ "ref": "claude/x3-rag-coverage-gate-qx9j7d (PR #1454, squashed as 102bb1f)", "head": "102bb1f5edf09e666d1be5934ff5dfb2aa5abcf0", "scope": "X3/#086 evidence coverage gate extraction from rag.ts into rag-coverage-gate.ts", - "outcome": "clean and landed — byte-identical move verified against pre-merge main, rag.ts 5030->4780, budget ratcheted to 4780, no back-edge, public re-export preserved; squash captured 100% of branch content, nothing orphaned", + "outcome": "clean and landed \u2014 byte-identical move verified against pre-merge main, rag.ts 5030->4780, budget ratcheted to 4780, no back-edge, public re-export preserved; squash captured 100% of branch content, nothing orphaned", "checks": "workflow:rag-lab, focused vitest 81/81, check:maintainability-budgets 4780/4780, check:rag:fixtures 36 golden, eval:rag:offline 567/567, typecheck, lint, check:knip, format:check, verify:cheap 4569 passed, npm test 4569 passed, verify:pr-local build+bundle-scan, post-merge npm test on main 4574 passed" }, { @@ -13066,7 +13065,7 @@ "ref": "claude/x3-rag-coverage-gate-qx9j7d (PR #1463, squashed as dba7356f)", "head": "dba7356fc8dc926d951d6de6f019d5b8e000be21", "scope": "X3/#101 per-request hydration extraction from rag.ts into rag-hydration.ts", - "outcome": "clean and landed — byte-identical move verified against pre-merge main, rag.ts 4780->4543, budget ratcheted to 4543, no back-edge (cluster referenced zero rag.ts-local symbols), both public re-exports preserved; squash captured 100% of branch content", + "outcome": "clean and landed \u2014 byte-identical move verified against pre-merge main, rag.ts 4780->4543, budget ratcheted to 4543, no back-edge (cluster referenced zero rag.ts-local symbols), both public re-exports preserved; squash captured 100% of branch content", "checks": "typecheck, lint, check:knip, check:maintainability-budgets 4543/4543, focused vitest 83/83 incl rag-query-concurrency, eval:rag:offline 572/572 36 golden, format:check, verify:cheap, verify:pr-local build+bundle-scan, post-merge content verification on main" }, { @@ -13290,7 +13289,7 @@ "ref": "codex/computed-style-assertions", "head": "1f431caa8d80660b8f6d90f557e4b8ea5d82560c", "scope": "post-sync archive completed rendered-style contract task #094", - "outcome": "APPROVED — no findings after exact current-main sync; archive move and prior review record only.", + "outcome": "APPROVED \u2014 no findings after exact current-main sync; archive move and prior review record only.", "checks": "check:outstanding-issues PASS (151 rows; 44 open, 107 archived); branch-review-ledger PASS (254 live, 1206 archived); git diff --check PASS; merge-tree 9ab802e9ec73132e4a7231b9060bf95be090b9d2" }, { @@ -13298,7 +13297,7 @@ "ref": "codex/computed-style-assertions", "head": "229b0d396decd0ad7f7779b57631ae1f137752d7", "scope": "archive completed rendered-style contract task #094", - "outcome": "APPROVED — no findings; docs-only archive move matches landed computed-style, forced-colors, tap-size, and unlayered-class registry evidence.", + "outcome": "APPROVED \u2014 no findings; docs-only archive move matches landed computed-style, forced-colors, tap-size, and unlayered-class registry evidence.", "checks": "check:outstanding-issues PASS (148 rows; 42 open, 106 archived); git diff --check PASS; implementation commits verified ancestral to origin/main" }, { @@ -13306,7 +13305,7 @@ "ref": "codex/computed-style-assertions", "head": "a18085a15339f280fff76cad15fafcf1a80084fe", "scope": "post-#1490 sync archive rendered-style task #094", - "outcome": "APPROVED — no findings; current-main issue additions are preserved and #094 is the sole state change.", + "outcome": "APPROVED \u2014 no findings; current-main issue additions are preserved and #094 is the sole state change.", "checks": "outstanding-issues PASS (151 rows; 43 open, 108 archived); branch-review-ledger PASS (271 live, 1206 archived); diff check PASS; merge-tree ab18c4319fcca6c915d340bdea286481caa8ea43" }, { @@ -13314,7 +13313,7 @@ "ref": "codex/computed-style-assertions", "head": "a8ee3315f2c9959025b7d652c0b7ea45432ca6be", "scope": "post-#121 sync archive rendered-style task #094", - "outcome": "APPROVED — no findings; #121 main merge preserved and #094 remains the only issue-state change.", + "outcome": "APPROVED \u2014 no findings; #121 main merge preserved and #094 remains the only issue-state change.", "checks": "outstanding-issues PASS (151 rows; 43 open, 108 archived); branch-review-ledger PASS (261 live, 1206 archived); diff check PASS; merge-tree 2c567bcbb60f5d3f36eb18b6f7d7f6ee2a7a788b" }, { @@ -14570,7 +14569,7 @@ "ref": "cursor/ci-hygiene-gates-1bf5", "head": "ad9da6a6f8ba3884b389fa78e678bb88ee72d9d1", "scope": "ci-hygiene-gates", - "outcome": "implemented matrix unblock, scope narrow, cancelled≠failure, pinned gitleaks, critical-first UI, eval:rag:offline; skipped #093; verify:cheap 4471 pass", + "outcome": "implemented matrix unblock, scope narrow, cancelled\u2260failure, pinned gitleaks, critical-first UI, eval:rag:offline; skipped #093; verify:cheap 4471 pass", "checks": "verify:cheap,check:ci-scope,check:gitleaks-pinned,check:gate-manifest,eval:rag:offline" }, { @@ -14642,7 +14641,7 @@ "ref": "dba7356fc8dc926d951d6de6f019d5b8e000be21", "head": "dba7356fc8dc926d951d6de6f019d5b8e000be21", "scope": "X3 hydration unit: per-request hydration extraction from rag.ts into rag-hydration.ts (PR #1463)", - "outcome": "clean and landed — byte-identical move verified against pre-merge main, rag.ts 4780->4543, budget ratcheted to 4543, no back-edge, both public re-exports preserved. Supersedes the earlier row for this HEAD, which was keyed only to the slash-form branch token and so returned NOT REVIEWED on a landed-SHA lookup; it also mislabelled the unit as #101, which is the unrelated open canary-gated retrieval-parallelisation recommendation", + "outcome": "clean and landed \u2014 byte-identical move verified against pre-merge main, rag.ts 4780->4543, budget ratcheted to 4543, no back-edge, both public re-exports preserved. Supersedes the earlier row for this HEAD, which was keyed only to the slash-form branch token and so returned NOT REVIEWED on a landed-SHA lookup; it also mislabelled the unit as #101, which is the unrelated open canary-gated retrieval-parallelisation recommendation", "checks": "typecheck, lint, check:knip, check:maintainability-budgets 4543/4543, focused vitest 83/83, eval:rag:offline 572/572 36 golden, format:check, verify:cheap 442 files 4625 passed, verify:pr-local, post-merge content verification on main" }, { @@ -14690,7 +14689,7 @@ "ref": "origin/codex/document-reader-condensed-view", "head": "b5cdbf301d517239ffe9ed941b9ebe809aea0bfd", "scope": "branch-cleanup", - "outcome": "safe to delete — tip tree identical to merge-base tree (855aa291), so the branch nets zero content change vs main; --cherry-pick shows 13 commits, a squash-merge false positive", + "outcome": "safe to delete \u2014 tip tree identical to merge-base tree (855aa291), so the branch nets zero content change vs main; --cherry-pick shows 13 commits, a squash-merge false positive", "checks": "git diff --name-only merge-base..tip = 0 files; tree(tip)==tree(merge-base); git ls-remote confirms live HEAD" }, { @@ -14698,7 +14697,7 @@ "ref": "origin/codex/document-reader-condensed-view", "head": "b5cdbf301d517239ffe9ed941b9ebe809aea0bfd", "scope": "branch-cleanup (supersedes 2026-07-30)", - "outcome": "safe to delete — merge-base 855aa291 is an ANCESTOR of main and tree(tip)==tree(855aa291), so every byte at the tip exists in main's history; the 13 --cherry-pick commits are merges of main plus work already squash-merged, not uncancelled work", + "outcome": "safe to delete \u2014 merge-base 855aa291 is an ANCESTOR of main and tree(tip)==tree(855aa291), so every byte at the tip exists in main's history; the 13 --cherry-pick commits are merges of main plus work already squash-merged, not uncancelled work", "checks": "git merge-base --is-ancestor 855aa291 origin/main = YES; tree(tip)==tree(855aa291); feature blobs present and byte-identical on origin/main; supersedes the earlier row, which omitted the ancestor step (Codex P2, PR #1398/#1403)" }, { @@ -14714,7 +14713,7 @@ "ref": "origin/cursor/page-anchored-search-composer-30ee", "head": "7ff134ca7f614db527b8d142676640305533669d", "scope": "branch-cleanup", - "outcome": "safe to delete — tip tree identical to merge-base tree (79d1c879), so the branch nets zero content change vs main; --cherry-pick shows 6 commits, a squash-merge false positive", + "outcome": "safe to delete \u2014 tip tree identical to merge-base tree (79d1c879), so the branch nets zero content change vs main; --cherry-pick shows 6 commits, a squash-merge false positive", "checks": "git diff --name-only merge-base..tip = 0 files; tree(tip)==tree(merge-base); git ls-remote confirms live HEAD" }, { @@ -14722,7 +14721,7 @@ "ref": "origin/cursor/page-anchored-search-composer-30ee", "head": "7ff134ca7f614db527b8d142676640305533669d", "scope": "branch-cleanup (supersedes 2026-07-30)", - "outcome": "safe to delete — merge-base 79d1c879 is an ANCESTOR of main and tree(tip)==tree(79d1c879), so every byte at the tip exists in main's history; the 6 --cherry-pick commits are merges of main plus work already squash-merged, not uncancelled work", + "outcome": "safe to delete \u2014 merge-base 79d1c879 is an ANCESTOR of main and tree(tip)==tree(79d1c879), so every byte at the tip exists in main's history; the 6 --cherry-pick commits are merges of main plus work already squash-merged, not uncancelled work", "checks": "git merge-base --is-ancestor 79d1c879 origin/main = YES; tree(tip)==tree(79d1c879); feature blobs present and byte-identical on origin/main; supersedes the earlier row, which omitted the ancestor step (Codex P2, PR #1398/#1403)" }, { @@ -14730,7 +14729,7 @@ "ref": "origin/cursor/pr-1379-babysit-ledger-9365", "head": "be2de03f855cb7fdfccea4bb74d05eb4c9bf6c61", "scope": "branch-cleanup", - "outcome": "safe to delete — tip tree identical to merge-base tree (b2740480), so the branch nets zero content change vs main; --cherry-pick shows 4 commits, a squash-merge false positive", + "outcome": "safe to delete \u2014 tip tree identical to merge-base tree (b2740480), so the branch nets zero content change vs main; --cherry-pick shows 4 commits, a squash-merge false positive", "checks": "git diff --name-only merge-base..tip = 0 files; tree(tip)==tree(merge-base); git ls-remote confirms live HEAD" }, { @@ -14738,7 +14737,7 @@ "ref": "origin/cursor/pr-1379-babysit-ledger-9365", "head": "be2de03f855cb7fdfccea4bb74d05eb4c9bf6c61", "scope": "branch-cleanup (supersedes 2026-07-30)", - "outcome": "safe to delete — merge-base b2740480 is an ANCESTOR of main and tree(tip)==tree(b2740480), so every byte at the tip exists in main's history; the 4 --cherry-pick commits are merges of main plus work already squash-merged, not uncancelled work", + "outcome": "safe to delete \u2014 merge-base b2740480 is an ANCESTOR of main and tree(tip)==tree(b2740480), so every byte at the tip exists in main's history; the 4 --cherry-pick commits are merges of main plus work already squash-merged, not uncancelled work", "checks": "git merge-base --is-ancestor b2740480 origin/main = YES; tree(tip)==tree(b2740480); feature blobs present and byte-identical on origin/main; supersedes the earlier row, which omitted the ancestor step (Codex P2, PR #1398/#1403)" }, { @@ -14746,7 +14745,7 @@ "ref": "origin/execute-audit-code-remediation", "head": "3470279fba23ad442d59d34552eb576e87f24141", "scope": "branch-cleanup", - "outcome": "REJECTED and deleted remote. PR #1162 already merged; sole unique commit was a ledger CI-green row already present on main (edcd17a1…). No open PR; no unique product content.", + "outcome": "REJECTED and deleted remote. PR #1162 already merged; sole unique commit was a ledger CI-green row already present on main (edcd17a1\u2026). No open PR; no unique product content.", "checks": "fetch --prune; cherry-pick log; tip-to-tip/three-dot; grep ledger for edcd17a1; gh pr 1162 MERGED; open=0; GitHub reads explicitly authorized; no non-GitHub provider checks." }, { @@ -14801,7 +14800,7 @@ "date": "2026-07-30", "ref": "PR #1394 / `claude/top-search-design-mockups-w53znc`", "head": "0d47141fc030684299dcb265e3d853c93b9e2a91", - "scope": "CI/review closeout — merged", + "scope": "CI/review closeout \u2014 merged", "outcome": "MERGED as squash `0d47141f`. Prior tip `4a001efa` had required CI green after prettier fix `61314887` (Static PR/CircleCI red on `#096` padding) and main sync. Layout/`/tools` false-positive fixed; `#115` deferred; review threads resolved. Post-merge ledger-only follow-up.", "checks": "hosted Static/Unit/PR-required/CircleCI pass on pre-merge tip; vitest adoption 6/6; typecheck; Bugbot no open P0/P1; merge-tree clean" }, @@ -14906,7 +14905,7 @@ "ref": "PR #1400", "head": "e869cb9d7ab20939361b277d1c6fcc07bbb6ca45", "scope": "pr-1400-guard-push-band-adoption", - "outcome": "MERGED — 17 review findings across guard-push.mjs and the band-adoption gate, all fixed and thread-resolved; each fix confirmed by reverting it and watching the guard fail. Guard now checks the pushed SHA in a git worktree (config, dynamic config, policy escalation incl. removal, lockfile Prettier parity); adoption gate replaced presence-matching with per-module reachability, closing six false greens of one root cause plus type-position edges found in self-review. Merge verified: all 8 commits ancestors of main, 4 changed files byte-identical.", + "outcome": "MERGED \u2014 17 review findings across guard-push.mjs and the band-adoption gate, all fixed and thread-resolved; each fix confirmed by reverting it and watching the guard fail. Guard now checks the pushed SHA in a git worktree (config, dynamic config, policy escalation incl. removal, lockfile Prettier parity); adoption gate replaced presence-matching with per-module reachability, closing six false greens of one root cause plus type-position edges found in self-review. Merge verified: all 8 commits ancestors of main, 4 changed files byte-identical.", "checks": "verify:cheap 432 files / 4470 passed 4 skipped; format:check clean; PR required success; services+tools page gutting reports orphans; 6 push-guard scratch-repo cases with real exit codes; every fixture mutation-verified" }, { @@ -15394,7 +15393,7 @@ "ref": "PR-1507", "head": "12e5c8c977a873a7b900596fdc310a1a78d863f0", "scope": "PR #1507 current-main merge and ledger normalization", - "outcome": "APPROVED — no findings after current-main sync; feature diff unchanged and ledger reduced to three unique append-only review rows.", + "outcome": "APPROVED \u2014 no findings after current-main sync; feature diff unchanged and ledger reduced to three unique append-only review rows.", "checks": "focused Vitest 2 files/40 tests PASS; outstanding-issues PASS; branch-review-ledger PASS; diff check PASS; merge-tree f8f88bd79706c2fb36637014a25e93af6e08eb99" }, { @@ -15410,7 +15409,7 @@ "ref": "PR-1507", "head": "5e22b89f7bdb73335d12a0cf4091915615b20dd7", "scope": "PR #1507 remote ancestry reconciliation", - "outcome": "APPROVED — identical-tree remote merge ancestry reconciled without content change; no remaining findings.", + "outcome": "APPROVED \u2014 identical-tree remote merge ancestry reconciled without content change; no remaining findings.", "checks": "focused Vitest 2 files/40 tests PASS on identical tree; issue and ledger guards PASS; diff check PASS; merge-tree d6594063a4aa2c5f8b7a9ec72c1c41c94e6937fa" }, { @@ -15530,7 +15529,7 @@ "ref": "1374", "head": "c14edb9c6f0bdbbfb147752503e016f2543fd803", "scope": "PR #1374 review + merge", - "outcome": "merged as 3704007c — DocumentViewer identity-bound state clear (P1) implemented and verified red without it; all 12 review threads resolved", + "outcome": "merged as 3704007c \u2014 DocumentViewer identity-bound state clear (P1) implemented and verified red without it; all 12 review threads resolved", "checks": "verify:cheap exit 0 (429 files / 4403 tests); PR required success; Production UI success" }, { @@ -15538,7 +15537,7 @@ "ref": "1391", "head": "baecef05cac86c4d52af895d483a33ba3c40cd61", "scope": "PR #1391 review", - "outcome": "reviewed clean — text-4xs retirement confirmed against globals.css (--text-3xs 0.625rem present, --text-4xs absent); orphan guard proven to fail on a reintroduced class; six Playwright retries all retry action-plus-effect so a genuine regression still fails. Resolved the outstanding-issues #108/#109 double-allocation (renumbered to #110/#111, marker to 112) and recorded #111 done", + "outcome": "reviewed clean \u2014 text-4xs retirement confirmed against globals.css (--text-3xs 0.625rem present, --text-4xs absent); orphan guard proven to fail on a reintroduced class; six Playwright retries all retry action-plus-effect so a genuine regression still fails. Resolved the outstanding-issues #108/#109 double-allocation (renumbered to #110/#111, marker to 112) and recorded #111 done", "checks": "verify:cheap exit 0 (429 files / 4404 tests); design-token-contract 28 passed; check:branch-review-ledger passed" }, { @@ -15602,7 +15601,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb", "head": "df29f311b60cadf8e43bf51283a9d6f496b295e3", "scope": "branch-cleanup-deletion-pending", - "outcome": "DELETION PENDING — content proven fully on main. Branch tip IS the merge-base with main (df29f311), so the tip is a direct ancestor of main; tree comparison of merge-base vs tip shows 0 changed files. Backs no open PR. Deletion blocked by HTTP 403; HEAD recorded here so the later branch-cleanup row can be keyed to it after the ref is gone. Supersedes the aggregate main-keyed row at 855aa291, which recorded no candidate HEADs.", + "outcome": "DELETION PENDING \u2014 content proven fully on main. Branch tip IS the merge-base with main (df29f311), so the tip is a direct ancestor of main; tree comparison of merge-base vs tip shows 0 changed files. Backs no open PR. Deletion blocked by HTTP 403; HEAD recorded here so the later branch-cleanup row can be keyed to it after the ref is gone. Supersedes the aggregate main-keyed row at 855aa291, which recorded no candidate HEADs.", "checks": "local git only for the content proof: git merge-base, git diff --name-only (0 files), git diff --name-only origin/main... (0 files), full history after git fetch --unshallow. PROVIDER-BACKED evidence obtained (GitHub reads, authorised repo-scope): open-PR head cross-check via GitHub API against PRs #1374/#1377/#1384/#1385/#1386/#1387, and GitHub MCP capability inspection. PROVIDER-BACKED MUTATION ATTEMPTED AND REJECTED: git push origin --delete returned HTTP 403; no branch was deleted. No OpenAI/Supabase/hosted-CI calls." }, { @@ -15610,7 +15609,7 @@ "ref": "claude/dazzling-blackwell-f348d0", "head": "c9bec8f9dce38cb647de9aa64ebf08bf7823a524", "scope": "branch-cleanup-deletion-pending", - "outcome": "DELETION PENDING — content proven fully on main. Branch tip IS the merge-base with main (c9bec8f9), so the tip is a direct ancestor of main; tree comparison of merge-base vs tip shows 0 changed files. Backs no open PR. Deletion blocked by HTTP 403; HEAD recorded here so the later branch-cleanup row can be keyed to it after the ref is gone. Supersedes the aggregate main-keyed row at 855aa291, which recorded no candidate HEADs.", + "outcome": "DELETION PENDING \u2014 content proven fully on main. Branch tip IS the merge-base with main (c9bec8f9), so the tip is a direct ancestor of main; tree comparison of merge-base vs tip shows 0 changed files. Backs no open PR. Deletion blocked by HTTP 403; HEAD recorded here so the later branch-cleanup row can be keyed to it after the ref is gone. Supersedes the aggregate main-keyed row at 855aa291, which recorded no candidate HEADs.", "checks": "local git only for the content proof: git merge-base, git diff --name-only (0 files), git diff --name-only origin/main... (0 files), full history after git fetch --unshallow. PROVIDER-BACKED evidence obtained (GitHub reads, authorised repo-scope): open-PR head cross-check via GitHub API against PRs #1374/#1377/#1384/#1385/#1386/#1387, and GitHub MCP capability inspection. PROVIDER-BACKED MUTATION ATTEMPTED AND REJECTED: git push origin --delete returned HTTP 403; no branch was deleted. No OpenAI/Supabase/hosted-CI calls." }, { @@ -15625,7 +15624,7 @@ "date": "2026-07-29", "ref": "claude/latency-findings-impl-s8g01v", "head": "0e937f80f1c4fdfa66a4e5abc2918e763ed51bc1", - "scope": "PR #1377 latency findings — operator rollback sequencing", + "scope": "PR #1377 latency findings \u2014 operator rollback sequencing", "outcome": "Codex P2 confirmed and fixed: the index rollback merged the revert migration into the expectation deploy, so the deployed migration would take ACCESS EXCLUSIVE on documents before the concurrent drop; split into three deployed phases (retract required_indexes -> concurrent live drop -> schema.sql removal + idempotent forward drop migration). Apply-side commit-vs-deploy ordering made explicit. Docs only.", "checks": "prettier --check clean; docs:check-links 1355; docs:check-scripts 390; check:branch-review-ledger 1232 records" }, @@ -15633,7 +15632,7 @@ "date": "2026-07-29", "ref": "claude/latency-findings-impl-s8g01v", "head": "310d0fbc4f08ca88cb097f3e480896e75d0007bf", - "scope": "PR #1377 latency findings — search_schema_health registration is a migration", + "scope": "PR #1377 latency findings \u2014 search_schema_health registration is a migration", "outcome": "Codex P2 confirmed and fixed: apply step 5 and rollback phase A described the required_indexes change as a schema.sql edit, but schema.sql is a mirror and search_schema_health() is redefined by create or replace function in 11 migrations (precedent 20260705180000_reconcile_search_health_indexes.sql:62). As written the hosted function never moved, leaving the new indexes unmonitored on apply and, on rollback, letting phase B drop indexes the hosted function still required. Both now specify a create-or-replace-function migration plus matching mirror; apply deploys last. Docs only.", "checks": "prettier --check clean; docs:check-links 1356; docs:check-scripts 390" }, @@ -15641,7 +15640,7 @@ "date": "2026-07-29", "ref": "claude/latency-findings-impl-s8g01v", "head": "39ac6fde537946d0dd94712a206725969689f056", - "scope": "PR #1377 latency findings — RAG canary gate is not lifted by ordering", + "scope": "PR #1377 latency findings \u2014 RAG canary gate is not lifted by ordering", "outcome": "Codex P2 confirmed and fixed: the #102 queue row, the #102 detail row and the runbook bullet described the RAG-path index as canary-gated until/unless/or the unordered .limit(12) is ordered, implying ordering lifts the gate. An unordered LIMIT has no stable selection to preserve, so imposing an order can select a different twelve and is itself an ordering behaviour change on a retrieval surface requiring its own canary pair per AGENTS.md. All four sites now state two canary-gated changes rather than one unlockable gate. Docs only; no src/lib/rag change.", "checks": "prettier --check clean; docs:check-links 1356; docs:check-scripts 390" }, @@ -15650,7 +15649,7 @@ "ref": "claude/latency-findings-impl-s8g01v", "head": "71db10c41de872fca6e400626704a549f145c66c", "scope": "latency audit implementation (PR #1377)", - "outcome": "SUPERSEDES the 78e2beb record: its 'scope-vs-ratelimit overlap with abort' description is stale and describes behaviour that was REVERTED. Codex review raised it P1 and it was correct — an AbortSignal cannot un-execute a statement Postgres already began, and resolveSearchScope only skips the database when there are no filters and no explicit ids (search-scope.ts:242,253), so a throttled caller kept spending DB capacity while collecting 429s. Shipped behaviour is rate-limit admission BEFORE scope evaluation, with request.signal threaded so a client disconnect still cancels scope's paginated queries, pinned by tests/answer-route-preamble.test.ts. Also retracted on this head: the L2-3 'recall is byte-identical' claim, since fetchDocumentTitleAliasRows applies .limit(12) with no ORDER BY.", + "outcome": "SUPERSEDES the 78e2beb record: its 'scope-vs-ratelimit overlap with abort' description is stale and describes behaviour that was REVERTED. Codex review raised it P1 and it was correct \u2014 an AbortSignal cannot un-execute a statement Postgres already began, and resolveSearchScope only skips the database when there are no filters and no explicit ids (search-scope.ts:242,253), so a throttled caller kept spending DB capacity while collecting 429s. Shipped behaviour is rate-limit admission BEFORE scope evaluation, with request.signal threaded so a client disconnect still cancels scope's paginated queries, pinned by tests/answer-route-preamble.test.ts. Also retracted on this head: the L2-3 'recall is byte-identical' claim, since fetchDocumentTitleAliasRows applies .limit(12) with no ORDER BY.", "checks": "verify:cheap exit 0 (423 files, 4278 passed/4 skipped); check:branch-review-ledger pass; focused preamble + server-timing suites pass" }, { @@ -15665,7 +15664,7 @@ "date": "2026-07-29", "ref": "claude/latency-findings-impl-s8g01v", "head": "881b7cfe9f4c9b313e70496968d5a7591f2b594d", - "scope": "PR #1377 latency findings — #103 drift allowlist is not a reconciliation route", + "scope": "PR #1377 latency findings \u2014 #103 drift allowlist is not a reconciliation route", "outcome": "Codex P2 confirmed and fixed: the #103 queue and detail rows offered drift-allowlist.json as an alternative to mirroring document_table_facts_text_trgm_idx into schema.sql. The allowlist header scopes it to live-vs-schema.sql divergence, so it cannot reconcile migrations with the mirror; a fresh db reset still runs 20260714190000 while schema.sql omits the index, leaving the row outcome unmet. Both rows now give exactly two routes (mirror, or forward-migration drop after live scan evidence) and record that no offline gate catches this. Docs only.", "checks": "prettier --check clean; docs:check-links 1356; docs:check-scripts 390" }, @@ -15673,7 +15672,7 @@ "date": "2026-07-29", "ref": "claude/latency-findings-impl-s8g01v", "head": "9e2ee65ca0bcce45a3cb6a0539e265ec8d961582", - "scope": "PR #1377 latency findings — #098 stale offline-harness references", + "scope": "PR #1377 latency findings \u2014 #098 stale offline-harness references", "outcome": "Codex P2 confirmed and fixed: the #098 row in docs/outstanding-issues.md still named test-cache-path.mjs and check-rag-fixtures.mjs as the offline fixtures for the round-trip counting harness. Neither exercises a RAG request (cache paths; fixture-manifest validation), so a harness built on them would count nothing. The audit doc carried the retraction at :358 but this row did not - the same local-retraction pattern flagged in two prior rounds. Now names eval-rag-offline.mjs, test-rag-offline.mjs, rag-offline-contract.mjs and the contract fixture, all verified present, with the correction recorded inline. Docs only.", "checks": "prettier --check clean; docs:check-links 1363; docs:check-scripts 390; grep confirms no stale refs remain" }, @@ -15738,7 +15737,7 @@ "ref": "claude/test-coverage-analysis-2vcd8a", "head": "f4a3f50048fa113d5e4e704defdafad2d37ba8d2", "scope": "prlanded", - "outcome": "MERGED AND VERIFIED. PR #1383 squash-merged as f4a3f50. Content diff between the squash commit and branch tip bebc6c02 is EMPTY — nothing orphaned by the auto-merge race despite four concurrent pushes during the merge window. Landed on main: tests/calculator-scoring.test.ts (60 tests, 8 validated instruments), 9 batch signed-URL cases in tests/private-access-routes.test.ts, coverage floors raised 48/38/43/50 -> 62/53/55/64. Follow-ups renumbered #098/#099 -> #106/#107 during the main merge (main had claimed #098-#105); both rows verified present with content intact and next-id marker at 108. The three red 'PR required' results at 0922d7f/6f476b5/b72bc20 were concurrency cancellations (issue #095), not defects — all upstream jobs reported 'cancelled'; the clean run 30447852418 at tip bebc6c0 superseded them.", + "outcome": "MERGED AND VERIFIED. PR #1383 squash-merged as f4a3f50. Content diff between the squash commit and branch tip bebc6c02 is EMPTY \u2014 nothing orphaned by the auto-merge race despite four concurrent pushes during the merge window. Landed on main: tests/calculator-scoring.test.ts (60 tests, 8 validated instruments), 9 batch signed-URL cases in tests/private-access-routes.test.ts, coverage floors raised 48/38/43/50 -> 62/53/55/64. Follow-ups renumbered #098/#099 -> #106/#107 during the main merge (main had claimed #098-#105); both rows verified present with content intact and next-id marker at 108. The three red 'PR required' results at 0922d7f/6f476b5/b72bc20 were concurrency cancellations (issue #095), not defects \u2014 all upstream jobs reported 'cancelled'; the clean run 30447852418 at tip bebc6c0 superseded them.", "checks": "post-merge verification only: content diff squash-vs-tip EMPTY; origin/main content spot-checks PASS (test file present, floors 62/53/55/64, #106/#107 rows, 13 signed-urls refs); pre-merge local gates on the merged tree: test:coverage PASS exit 0 (424 files, 4371 passed | 4 skipped, no threshold errors); no provider-backed checks" }, { @@ -15770,7 +15769,7 @@ "ref": "codex/document-reader-condensed-view", "head": "b5cdbf301d517239ffe9ed941b9ebe809aea0bfd", "scope": "branch-cleanup-deletion-pending", - "outcome": "DELETION PENDING — content proven fully on main. Merge-base with main is 855aa291 and tree(merge-base) equals tree(tip): git diff --name-only 855aa291 b5cdbf30 reports 0 files, so the tip introduces nothing beyond a state already in main. Its work landed as main's tip via squash. Backs no open PR. Deletion blocked by HTTP 403; HEAD recorded here so the later branch-cleanup row can be keyed to it after the ref is gone. Supersedes the aggregate main-keyed row at 855aa291, which recorded no candidate HEADs.", + "outcome": "DELETION PENDING \u2014 content proven fully on main. Merge-base with main is 855aa291 and tree(merge-base) equals tree(tip): git diff --name-only 855aa291 b5cdbf30 reports 0 files, so the tip introduces nothing beyond a state already in main. Its work landed as main's tip via squash. Backs no open PR. Deletion blocked by HTTP 403; HEAD recorded here so the later branch-cleanup row can be keyed to it after the ref is gone. Supersedes the aggregate main-keyed row at 855aa291, which recorded no candidate HEADs.", "checks": "local git only for the content proof: git merge-base, git diff --name-only (0 files), git diff --name-only origin/main... (0 files), full history after git fetch --unshallow. PROVIDER-BACKED evidence obtained (GitHub reads, authorised repo-scope): open-PR head cross-check via GitHub API against PRs #1374/#1377/#1384/#1385/#1386/#1387, and GitHub MCP capability inspection. PROVIDER-BACKED MUTATION ATTEMPTED AND REJECTED: git push origin --delete returned HTTP 403; no branch was deleted. No OpenAI/Supabase/hosted-CI calls." }, { @@ -15834,7 +15833,7 @@ "ref": "cursor/page-anchored-search-composer-30ee", "head": "7ff134ca7f614db527b8d142676640305533669d", "scope": "branch-cleanup-deletion-pending", - "outcome": "DELETION PENDING — content proven fully on main. Merge-base with main is 79d1c879 and tree(merge-base) equals tree(tip): git diff --name-only 79d1c879 7ff134ca reports 0 files, so the tip introduces nothing beyond a state already in main. Backs no open PR. Deletion blocked by HTTP 403; HEAD recorded here so the later branch-cleanup row can be keyed to it after the ref is gone. Supersedes the aggregate main-keyed row at 855aa291, which recorded no candidate HEADs.", + "outcome": "DELETION PENDING \u2014 content proven fully on main. Merge-base with main is 79d1c879 and tree(merge-base) equals tree(tip): git diff --name-only 79d1c879 7ff134ca reports 0 files, so the tip introduces nothing beyond a state already in main. Backs no open PR. Deletion blocked by HTTP 403; HEAD recorded here so the later branch-cleanup row can be keyed to it after the ref is gone. Supersedes the aggregate main-keyed row at 855aa291, which recorded no candidate HEADs.", "checks": "local git only for the content proof: git merge-base, git diff --name-only (0 files), git diff --name-only origin/main... (0 files), full history after git fetch --unshallow. PROVIDER-BACKED evidence obtained (GitHub reads, authorised repo-scope): open-PR head cross-check via GitHub API against PRs #1374/#1377/#1384/#1385/#1386/#1387, and GitHub MCP capability inspection. PROVIDER-BACKED MUTATION ATTEMPTED AND REJECTED: git push origin --delete returned HTTP 403; no branch was deleted. No OpenAI/Supabase/hosted-CI calls." }, { @@ -15842,7 +15841,7 @@ "ref": "cursor/pr-1379-babysit-ledger-9365", "head": "be2de03f855cb7fdfccea4bb74d05eb4c9bf6c61", "scope": "branch-cleanup-deletion-pending", - "outcome": "DELETION PENDING — content proven fully on main. Merge-base with main is b2740480 and tree(merge-base) equals tree(tip): git diff --name-only b2740480 be2de03f reports 0 files, so the tip introduces nothing beyond a state already in main. Backs no open PR. Deletion blocked by HTTP 403; HEAD recorded here so the later branch-cleanup row can be keyed to it after the ref is gone. Supersedes the aggregate main-keyed row at 855aa291, which recorded no candidate HEADs.", + "outcome": "DELETION PENDING \u2014 content proven fully on main. Merge-base with main is b2740480 and tree(merge-base) equals tree(tip): git diff --name-only b2740480 be2de03f reports 0 files, so the tip introduces nothing beyond a state already in main. Backs no open PR. Deletion blocked by HTTP 403; HEAD recorded here so the later branch-cleanup row can be keyed to it after the ref is gone. Supersedes the aggregate main-keyed row at 855aa291, which recorded no candidate HEADs.", "checks": "local git only for the content proof: git merge-base, git diff --name-only (0 files), git diff --name-only origin/main... (0 files), full history after git fetch --unshallow. PROVIDER-BACKED evidence obtained (GitHub reads, authorised repo-scope): open-PR head cross-check via GitHub API against PRs #1374/#1377/#1384/#1385/#1386/#1387, and GitHub MCP capability inspection. PROVIDER-BACKED MUTATION ATTEMPTED AND REJECTED: git push origin --delete returned HTTP 403; no branch was deleted. No OpenAI/Supabase/hosted-CI calls." }, { @@ -15898,7 +15897,7 @@ "ref": "main", "head": "855aa2914fd9cf29f9ce34f67e197d7a2d0c1a86", "scope": "branch-cleanup-deletion-pending", - "outcome": "Full-history branch-cleanup review of all 92 remote branches. IMPORTANT PRECONDITION: the session clone was SHALLOW (74 commits of origin/main); every merge-base and cherry-pick result computed before 'git fetch --unshallow' was invalid, and an initial pass wrongly showed 90/91 branches as carrying unmerged work. After unshallowing (2829 commits) the analysis is sound. Cherry-pick matching alone finds only 2 candidates because squash merges collapse N commits into 1 so per-commit patch-ids never match; a content test (files touched vs merge-base, compared between branch tip and main) finds 5. VERIFIED SAFE TO DELETE — each introduces an empty diff against main and backs no open PR: claude/clinical-kb-pwa-review-asi3wb, claude/dazzling-blackwell-f348d0, codex/document-reader-condensed-view, cursor/page-anchored-search-composer-30ee, cursor/pr-1379-babysit-ledger-9365. DELETION BLOCKED: the session git proxy rejects ref deletion with HTTP 403 and the GitHub MCP toolset exposes no delete-branch capability, so the five remain and must be removed from the GitHub UI or an interactive session. The other 87 were NOT cleared: their touched files still differ from main, which is the conservative direction (a branch whose files main later modified reads as not-landed). Local cleanup done: stale local main fast-forwarded to origin/main (0 ahead, 0 patch-unique after unshallow — its earlier 'ahead 52 / unrelated histories' was purely the shallow-clone artifact); redundant local claude/prlanded-ledger-1383 deleted after confirming its row is in the pushed branch.", + "outcome": "Full-history branch-cleanup review of all 92 remote branches. IMPORTANT PRECONDITION: the session clone was SHALLOW (74 commits of origin/main); every merge-base and cherry-pick result computed before 'git fetch --unshallow' was invalid, and an initial pass wrongly showed 90/91 branches as carrying unmerged work. After unshallowing (2829 commits) the analysis is sound. Cherry-pick matching alone finds only 2 candidates because squash merges collapse N commits into 1 so per-commit patch-ids never match; a content test (files touched vs merge-base, compared between branch tip and main) finds 5. VERIFIED SAFE TO DELETE \u2014 each introduces an empty diff against main and backs no open PR: claude/clinical-kb-pwa-review-asi3wb, claude/dazzling-blackwell-f348d0, codex/document-reader-condensed-view, cursor/page-anchored-search-composer-30ee, cursor/pr-1379-babysit-ledger-9365. DELETION BLOCKED: the session git proxy rejects ref deletion with HTTP 403 and the GitHub MCP toolset exposes no delete-branch capability, so the five remain and must be removed from the GitHub UI or an interactive session. The other 87 were NOT cleared: their touched files still differ from main, which is the conservative direction (a branch whose files main later modified reads as not-landed). Local cleanup done: stale local main fast-forwarded to origin/main (0 ahead, 0 patch-unique after unshallow \u2014 its earlier 'ahead 52 / unrelated histories' was purely the shallow-clone artifact); redundant local claude/prlanded-ledger-1383 deleted after confirming its row is in the pushed branch.", "checks": "npm run sweep:branch-ledger (report-only, 2 candidates); full-history recompute after git fetch --unshallow; per-branch git diff origin/main... empty for all 5; open-PR head cross-check against PRs #1374/#1377/#1384/#1385/#1386/#1387; no branch deleted (HTTP 403); no provider-backed checks" }, { @@ -15986,7 +15985,7 @@ "ref": "`codex/fix-p2-audit-20260719`", "head": "d99a71b82abf605f26fcc81ba61cdc805a99a36f", "scope": "Bugbot-style unique product delta vs origin/main (playwright SW block, ClinicalDashboard focus drop, sheet Tab trap, clinical-search neuroleptic/clozapine/med-dose, rag-retrieval-variants, supporting tests)", - "outcome": "CHANGES REQUESTED. No P0. P1: `medicationDoseQueryContext` named-medication gate requires canonical generic token in evidence (`evidenceTokens.has(\"clozapine\")`) and ignores brand aliases, so Clozaril-only evidence fails for Clozaril/clozapine monitoring queries and can rank below unrelated high-hybrid monitoring docs (−0.24 / missed +0.26). P2: neuroleptic side-effects early `document_lookup` return preempts dose classification (`What dose applies for neuroleptic side effect management?` → `document_lookup`). Cleared: SW block + PWA allow, documents `focus:true` removal on in-place pushState ask path, clozapine blood-token retention, Clozaril→clozapine variant intent via analysis.medications. Highest residual: sheet Tab trap rewrite has no Tab-cycle DOM proof.", + "outcome": "CHANGES REQUESTED. No P0. P1: `medicationDoseQueryContext` named-medication gate requires canonical generic token in evidence (`evidenceTokens.has(\"clozapine\")`) and ignores brand aliases, so Clozaril-only evidence fails for Clozaril/clozapine monitoring queries and can rank below unrelated high-hybrid monitoring docs (\u22120.24 / missed +0.26). P2: neuroleptic side-effects early `document_lookup` return preempts dose classification (`What dose applies for neuroleptic side effect management?` \u2192 `document_lookup`). Cleared: SW block + PWA allow, documents `focus:true` removal on in-place pushState ask path, clozapine blood-token retention, Clozaril\u2192clozapine variant intent via analysis.medications. Highest residual: sheet Tab trap rewrite has no Tab-cycle DOM proof.", "checks": "Offline red proofs via temporary Vitest probes (brand gate + neuroleptic class); focused clinical-search regressions 6/6; no OpenAI/Supabase/hosted CI." }, { @@ -16178,7 +16177,7 @@ "ref": "cursor/pr-policy-caveman-docs-dc4e", "head": "c0fe85980b998a7790e99e4a0ab4a04c01934536", "scope": "pr-1335", - "outcome": "docs-ready: caveman×pr-policy + consolidation ledger", + "outcome": "docs-ready: caveman\u00d7pr-policy + consolidation ledger", "checks": "content-proofread,check:branch-review-ledger" }, { @@ -16186,7 +16185,7 @@ "ref": "cursor/pr-policy-caveman-docs-dc4e", "head": "e449eccc7e050736519588a89d2c35b2348e4380", "scope": "pr-1335", - "outcome": "docs-ready: caveman×pr-policy guidance", + "outcome": "docs-ready: caveman\u00d7pr-policy guidance", "checks": "content-proofread" }, { @@ -16210,7 +16209,7 @@ "ref": "open-prs@2026-07-28", "head": "ac786b3553252df48bd13ef414afbcc62e1b41e9", "scope": "open-pr-usefulness", - "outcome": "TRIAGE of 19 open PRs vs origin/main ac786b35: CLOSE #1364 (author throwaway), #1322 (superseded by #1335), #1352 (stale continuation of merged #1305; 595 behind; real merge-tree conflicts; deletes private-access tests / diverges answer+upload). KEEP product: #1366 Claude settings diagnostic, #1365 issues #096/#097, #1335 caveman×pr-policy docs, #1360 npm-ci CI, #1361 sheet max-h, #1362 calculator/therapy mockups, #1311 doc-nav mockups+viewer, #1351 error/a11y audit, #1298 sheet-focus/P2 tests, #1295 tablet mode-home, #1268/#1269/#1267 dependabot. FOLD ledger-only #1353+#1341+#1363 into one hygiene PR then close the extras. Order: land #1335 before depending on caveman guidance; sync #1361 vs #1298 (same sheet.tsx, different deltas); refresh #1267 after #1366; do not land #096's seven unrun follow-ups piecemeal.", + "outcome": "TRIAGE of 19 open PRs vs origin/main ac786b35: CLOSE #1364 (author throwaway), #1322 (superseded by #1335), #1352 (stale continuation of merged #1305; 595 behind; real merge-tree conflicts; deletes private-access tests / diverges answer+upload). KEEP product: #1366 Claude settings diagnostic, #1365 issues #096/#097, #1335 caveman\u00d7pr-policy docs, #1360 npm-ci CI, #1361 sheet max-h, #1362 calculator/therapy mockups, #1311 doc-nav mockups+viewer, #1351 error/a11y audit, #1298 sheet-focus/P2 tests, #1295 tablet mode-home, #1268/#1269/#1267 dependabot. FOLD ledger-only #1353+#1341+#1363 into one hygiene PR then close the extras. Order: land #1335 before depending on caveman guidance; sync #1361 vs #1298 (same sheet.tsx, different deltas); refresh #1267 after #1366; do not land #096's seven unrun follow-ups piecemeal.", "checks": "gh-pr-list; git-fetch-prune; ahead/behind+cherry-pick+merge-tree per tip; three-dot file inventory; overlap matrix; #1305 MERGED proof; content compare SettingsStateProvider/Overlay/z-ladder already on main; #1335 body supersedes #1322; no provider checks; no closes performed" }, { @@ -16298,7 +16297,7 @@ "ref": "PR #1285 / `cursor/pdf-extractor-sigkill-137-0687`", "head": "f1e422e8ee64f7e161e78d9a56707a1a83cc3374", "scope": "CI babysit: PR policy + main sync", - "outcome": "Before: PR marked ready → PR policy FAIL (missing Clinical Governance Preflight); GitHub CONFLICTING/DIRTY but merge-tree clean (17 behind). 0 unresolved review threads; Bugbot no P0/P1. After: merged origin/main; PR body updated with complete Clinical Governance Preflight (7/7 checked).", + "outcome": "Before: PR marked ready \u2192 PR policy FAIL (missing Clinical Governance Preflight); GitHub CONFLICTING/DIRTY but merge-tree clean (17 behind). 0 unresolved review threads; Bugbot no P0/P1. After: merged origin/main; PR body updated with complete Clinical Governance Preflight (7/7 checked).", "checks": "Local pr-policy evaluate ok; Vitest process-failure 2/2; no provider checks." }, { @@ -16338,7 +16337,7 @@ "ref": "PR #1287 / `claude/site-audit-quick-wins-21v9gb`", "head": "b90d659be12efedd339297daa2d289c2bd7ebb03", "scope": "Sync main + Format check on outstanding-issues", - "outcome": "FIXED. Cause of GitHub CONFLICTING/DIRTY: branch 1 behind main (`11a4ed74` numeric claim truncation); `git merge-tree` CLEAN — ledger union auto-merge. Cause of Static PR red: Prettier on `docs/outstanding-issues.md` after queue closeout rewrite. Merged main; reformatted file; `#012` remains Resolved and out of the recommended queue.", + "outcome": "FIXED. Cause of GitHub CONFLICTING/DIRTY: branch 1 behind main (`11a4ed74` numeric claim truncation); `git merge-tree` CLEAN \u2014 ledger union auto-merge. Cause of Static PR red: Prettier on `docs/outstanding-issues.md` after queue closeout rewrite. Merged main; reformatted file; `#012` remains Resolved and out of the recommended queue.", "checks": "merge-tree CLEAN; `prettier --check` PASS; `check:branch-review-ledger` PASS; no provider-backed checks." }, { @@ -16362,7 +16361,7 @@ "ref": "PR #1289 / `codex/rag-reliability-final`", "head": "d49af8acb42ccedbfe6c8b3f03d30769ba906ec7", "scope": "Bugbot review (exact head)", - "outcome": "APPROVE. No high-confidence P0–P2. Application `src/`/`supabase/`/`tests/`/`scripts/` trees are unchanged vs prior APPROVE tip `a1ca6a01`; tip delta is docs evidence + clean merge from `main`. No unresolved `cursor[bot]` Bugbot threads. Residual risk: unapplied BMJ attestation migration (`#022`) correctly fails closed with `503 source_review_v2_unavailable` until qualified hosted apply.", + "outcome": "APPROVE. No high-confidence P0\u2013P2. Application `src/`/`supabase/`/`tests/`/`scripts/` trees are unchanged vs prior APPROVE tip `a1ca6a01`; tip delta is docs evidence + clean merge from `main`. No unresolved `cursor[bot]` Bugbot threads. Residual risk: unapplied BMJ attestation migration (`#022`) correctly fails closed with `503 source_review_v2_unavailable` until qualified hosted apply.", "checks": "Focused high-risk Vitest 358 + 1502 passed; merge-tree CLEAN vs `origin/main`; no provider-backed checks; no PR comment mutations." }, { @@ -16442,7 +16441,7 @@ "ref": "PR #1294 / `execute-typography-fixes-clean-2`", "head": "41da30ed82eb1cb6685883b6afbaa1e3198ee37d", "scope": "CI green closeout", - "outcome": "APPROVE. Hosted required aggregate green after diagnosis-detail S: clone locator scope + Prettier + main sync (#1275). Bugbot: 0 unresolved cursor[bot] threads; no P0/P1 on unique product delta (mockup h3→h2 + test locator). Mergeable; 0 behind main.", + "outcome": "APPROVE. Hosted required aggregate green after diagnosis-detail S: clone locator scope + Prettier + main sync (#1275). Bugbot: 0 unresolved cursor[bot] threads; no P0/P1 on unique product delta (mockup h3\u2192h2 + test locator). Mergeable; 0 behind main.", "checks": "Hosted Static PR / Unit / Build / Safety / Advisory UI / Production UI / PR required PASS; focused Chromium diagnosis-detail PASS 1/1 earlier; no provider-backed checks." }, { @@ -16482,7 +16481,7 @@ "ref": "PR #1294 / `execute-typography-fixes-clean-2`", "head": "9ac401fd3f9997c1a18c83dc2e5190ff02fcad63", "scope": "CI babysit re-request", - "outcome": "FIXED drift. Hosted required checks already green on prior tip `10157dec`; GitHub DIRTY was staleness (merge-tree CLEAN, 31 behind). Merged origin/main cleanly; unique delta unchanged (mockup h3→h2 + diagnosis-detail S: clone locator). Bugbot: 0 unresolved cursor[bot] threads; no P0/P1.", + "outcome": "FIXED drift. Hosted required checks already green on prior tip `10157dec`; GitHub DIRTY was staleness (merge-tree CLEAN, 31 behind). Merged origin/main cleanly; unique delta unchanged (mockup h3\u2192h2 + diagnosis-detail S: clone locator). Bugbot: 0 unresolved cursor[bot] threads; no P0/P1.", "checks": "Prior hosted Production UI/PR required PASS on `10157dec`; merge-tree CLEAN; prettier check PASS; no provider-backed checks." }, { @@ -16498,7 +16497,7 @@ "ref": "PR #1294 / `execute-typography-fixes-clean-2`", "head": "da6cc04bc3a3823db4d2f14581ceec15f7757b80", "scope": "Codex P2 heading hierarchy", - "outcome": "FIXED. Reverted mockup popup/sheet titles h2→h3 under Section h2 (hierarchy regression; same finding as PR #1200). Added answer-evidence-popups-heading-contract. Retained CI fixes: diagnosis-detail S: locator + Build RAM-guard CI warn.", + "outcome": "FIXED. Reverted mockup popup/sheet titles h2\u2192h3 under Section h2 (hierarchy regression; same finding as PR #1200). Added answer-evidence-popups-heading-contract. Retained CI fixes: diagnosis-detail S: locator + Build RAM-guard CI warn.", "checks": "Vitest heading+guard contracts 3/3; no provider-backed checks." }, { @@ -16594,7 +16593,7 @@ "ref": "PR #1296 / `css-layout-audit-complete`", "head": "84d846d8d0d168ca2babcc6d699e0a88bb0379c0", "scope": "Inspect closeout: sync main + forced-colors scope", - "outcome": "FIXED. GitHub CONFLICTING was unpushed main sync (local merge-tree CLEAN, 3 behind on remote tip). Pushed merge. Bugbot P2: removed broad forced-colors `!important` wipe on `.edge-glass-header`/`[aria-selected=true]`/`.surface-raised` (token remap retained; header Canvas fill already earlier). Mockup board `z-[2147483647]` → ladder `z-[100]`. Prior CodeRabbit/Codex threads remain resolved.", + "outcome": "FIXED. GitHub CONFLICTING was unpushed main sync (local merge-tree CLEAN, 3 behind on remote tip). Pushed merge. Bugbot P2: removed broad forced-colors `!important` wipe on `.edge-glass-header`/`[aria-selected=true]`/`.surface-raised` (token remap retained; header Canvas fill already earlier). Mockup board `z-[2147483647]` \u2192 ladder `z-[100]`. Prior CodeRabbit/Codex threads remain resolved.", "checks": "lint/typecheck/format:check PASS; vitest 4197; local build PASS; no provider checks." }, { @@ -16602,7 +16601,7 @@ "ref": "PR #1296 / `css-layout-audit-complete`", "head": "957a79e4", "scope": "Re-inspect: main sync + Bugbot", - "outcome": "FIXED CONFLICTING/DIRTY: 1 commit behind main (#1294 typography) — ledger/tests auto-merged clean. Prior CodeRabbit/Codex threads remain resolved. Local Bugbot: no P0/P1. Residual only intentional z-token demotions for mockup/popover.", + "outcome": "FIXED CONFLICTING/DIRTY: 1 commit behind main (#1294 typography) \u2014 ledger/tests auto-merged clean. Prior CodeRabbit/Codex threads remain resolved. Local Bugbot: no P0/P1. Residual only intentional z-token demotions for mockup/popover.", "checks": "lint+typecheck PASS; focused vitest 19/19; awaiting exact-head hosted CI; no provider checks." }, { @@ -16858,7 +16857,7 @@ "ref": "PR #1305 / `execute-audit-remediation-fixes`", "head": "6c089f2fa5ce5a0e6057dc99ff0199fce136d105", "scope": "CI/conflict babysit + Bugbot + PR policy body", - "outcome": "FIXED. Merged origin/main (was CONFLICTING); restored fail-closed clinical-notes `answer:\"\"` wipe; fixed upload merge hazard (undefined canonicalAuthority → 500); restored phone chrome viewport breakpoints; kept ClinicalDashboard under 4140-line budget via settingsState handle + memoized provider; updated account-access source contract; completed Clinical Governance Preflight in PR body. Zero unresolved review threads; zero cursor[bot] Bugbot findings.", + "outcome": "FIXED. Merged origin/main (was CONFLICTING); restored fail-closed clinical-notes `answer:\"\"` wipe; fixed upload merge hazard (undefined canonicalAuthority \u2192 500); restored phone chrome viewport breakpoints; kept ClinicalDashboard under 4140-line budget via settingsState handle + memoized provider; updated account-access source contract; completed Clinical Governance Preflight in PR body. Zero unresolved review threads; zero cursor[bot] Bugbot findings.", "checks": "`npm run verify:cheap` PASS (4115 tests); local pr-policy evaluate ok; no provider-backed checks." }, { @@ -16874,7 +16873,7 @@ "ref": "PR #1305 / `execute-audit-remediation-fixes`", "head": "b488485d075912bc54d514ea65a1cf73c3d9b413", "scope": "PR policy body sync closeout", - "outcome": "SUPERSEDES prior #1305 babysit tip. Synced complete Summary/Verification/Risk/governance via temporary `PR_POLICY_BODY.md` (gh/API cannot edit PR body — 403), then deleted template. PR policy PASS; mergeable CLEAN.", + "outcome": "SUPERSEDES prior #1305 babysit tip. Synced complete Summary/Verification/Risk/governance via temporary `PR_POLICY_BODY.md` (gh/API cannot edit PR body \u2014 403), then deleted template. PR policy PASS; mergeable CLEAN.", "checks": "Sync PR policy body SUCCESS; PR policy PASS; `verify:cheap` prior tip green." }, { @@ -16914,7 +16913,7 @@ "ref": "PR #1307 / `claude/rag-019-fallback-guard`", "head": "0827d65d12f5c25faffdf4ebca036f00fc2512cd", "scope": "CI babysit + Bugbot", - "outcome": "FIXED. Build failed because `guard-next-build.mjs` hard-failed when GitHub runners reported 7.8 GiB RAM (<10 GiB); prior tip Build succeeded on a larger runner (flake). Softened to warn-and-continue under CI/GITHUB_ACTIONS; local/Docker still hard-fail. PR policy FAIL: missing `## Clinical Governance Preflight` — body updated. Bugbot: zero cursor[bot] findings; reviewThreads=0 (nothing to resolve). merge-tree clean vs origin/main.", + "outcome": "FIXED. Build failed because `guard-next-build.mjs` hard-failed when GitHub runners reported 7.8 GiB RAM (<10 GiB); prior tip Build succeeded on a larger runner (flake). Softened to warn-and-continue under CI/GITHUB_ACTIONS; local/Docker still hard-fail. PR policy FAIL: missing `## Clinical Governance Preflight` \u2014 body updated. Bugbot: zero cursor[bot] findings; reviewThreads=0 (nothing to resolve). merge-tree clean vs origin/main.", "checks": "Unit: guard-next-build + #019 fallback + extractive-answer-formatting 137/137; prettier/eslint clean on touched files; pr-policy evaluate ok; no provider checks." }, { @@ -16930,7 +16929,7 @@ "ref": "PR #1309 / `claude/gates-skill`", "head": "7dfe103bfa408052c9e899211b8373c7ccb708d3", "scope": "Conflict sync + Codex/CodeRabbit + Bugbot", - "outcome": "FIXED. GitHub CONFLICTING/DIRTY was main-staleness only (`merge-tree` clean); merged `origin/main`. Codex P2: skill wrongly claimed `verify:ui` exits 0 under heavy-lock contention — corrected to 15m queue then exit 1 via `run-playwright.mjs`; mirrored in AGENTS.md. CodeRabbit: marked `${PIPESTATUS[0]}` as Bash-specific. Bugbot: zero `cursor[bot]` findings; confirmed same P2. No CI failures on prior tip.", + "outcome": "FIXED. GitHub CONFLICTING/DIRTY was main-staleness only (`merge-tree` clean); merged `origin/main`. Codex P2: skill wrongly claimed `verify:ui` exits 0 under heavy-lock contention \u2014 corrected to 15m queue then exit 1 via `run-playwright.mjs`; mirrored in AGENTS.md. CodeRabbit: marked `${PIPESTATUS[0]}` as Bash-specific. Bugbot: zero `cursor[bot]` findings; confirmed same P2. No CI failures on prior tip.", "checks": "`prettier --check` PASS; `docs:check-links` 1287 PASS; no provider-backed checks." }, { @@ -16946,7 +16945,7 @@ "ref": "PR #1310 / claude/branch-review-ledger-fixes-42575f", "head": "7c870c139211a419fe8b4dfacae3195a7a7caa2b", "scope": "PR babysit: CI + Codex P2s + Bugbot-equivalent", - "outcome": "Hosted PR required SUCCESS on 7c870c13. Fixed 3 Codex P2s (exact scope match, supersede mints distinct scope, verify full SHAs via git rev-parse) plus n/a-embedded hex and parenthetical ref-token false matches. 3 review threads replied+resolved. Mergeable; 0 behind main. Hosted Cursor Bugbot check not produced — bot-authored bugbot run/cursor review comments ignored; local Bugbot-style review done and defects fixed.", + "outcome": "Hosted PR required SUCCESS on 7c870c13. Fixed 3 Codex P2s (exact scope match, supersede mints distinct scope, verify full SHAs via git rev-parse) plus n/a-embedded hex and parenthetical ref-token false matches. 3 review threads replied+resolved. Mergeable; 0 behind main. Hosted Cursor Bugbot check not produced \u2014 bot-authored bugbot run/cursor review comments ignored; local Bugbot-style review done and defects fixed.", "checks": "check:branch-review-ledger PASS; vitest repo-hygiene 25/25; lint; typecheck; full vitest 4133 pass; hosted Static/Unit/Build/Safety/PR-required SUCCESS. No provider-backed gates." }, { @@ -16986,7 +16985,7 @@ "ref": "PR #1335 / cursor/pr-policy-caveman-docs-dc4e (merged)", "head": "fd5651c821426605df0cb9df44236d6c67e65f41", "scope": "open-pr-merge-sweep", - "outcome": "MERGED ledger fold. Product AGENTS/handoff already on main via #1322 (two-dot empty). Fixed Codex P2: pr-* ledger refs → resolvable branch names; resolved blocking thread (reply 403).", + "outcome": "MERGED ledger fold. Product AGENTS/handoff already on main via #1322 (two-dot empty). Fixed Codex P2: pr-* ledger refs \u2192 resolvable branch names; resolved blocking thread (reply 403).", "checks": "hosted-pr-required,static,circleci,resolveReviewThread" }, { @@ -17042,7 +17041,7 @@ "ref": "PR #1352 / execute-audit-remediation-fixes", "head": "dcdcb5b2b0546eddbb5bfd6efdb68122be2eabaa", "scope": "open-pr-merge-sweep", - "outcome": "SKIP-CLOSE confirmed: stale continuation of merged #1305; REAL merge-tree conflicts across answer route, ClinicalDashboard, OverlayProvider, z-index ladder, private-access tests, etc. Close attempted → 403.", + "outcome": "SKIP-CLOSE confirmed: stale continuation of merged #1305; REAL merge-tree conflicts across answer route, ClinicalDashboard, OverlayProvider, z-index ladder, private-access tests, etc. Close attempted \u2192 403.", "checks": "merge-tree-conflicts,gh-pr-1305-MERGED" }, { @@ -17066,7 +17065,7 @@ "ref": "PR #1371 / cursor/document-viewer-ci-guards-eac3 (merged)", "head": "64be97b96b46617e63f7d004fef4f9bcb14bf710", "scope": "open-pr-merge-sweep", - "outcome": "MERGED. Useful Production UI drift guards (document-overview id ownership + phone section sheet selectors). Draft→ready; sync main; squash+delete-branch.", + "outcome": "MERGED. Useful Production UI drift guards (document-overview id ownership + phone section sheet selectors). Draft\u2192ready; sync main; squash+delete-branch.", "checks": "hosted-pr-required,static,unit,circleci,merge-tree-clean" }, { @@ -17114,7 +17113,7 @@ "ref": "`claude/clinical-kb-pwa-review-asi3wb` (PR #1050: eval cost readout fix + issues-ledger capture)", "head": "eb1046be132d8e94d9d6b4905d7e240a99f33187", "scope": "Retrospective disposition row for PR #1050 (omitted at merge time; ride-along from the 2026-07-26 scheduled-runs reader)", - "outcome": "MERGED 2026-07-22 as squash `9fb9bc7`. External reviews dispositioned pre-merge: one Codex P2 and one CodeRabbit Major converged on the same defect (zero-usage cases with a provider attempt must stay `n/a`, not `$0`) plus two CodeRabbit ledger Minors and a real merge conflict against #1049's concurrent ID allocation — all resolved in `eb1046b` (provider-attempt cost branch; issue rows renumbered #018-#023, next-id 024), threads resolved and confirmed by the reviewer. Cost readout subsequently validated live twice: merged-main canary `30018289898` (2026-07-23) and scheduled run `30216191889` (2026-07-26, Estimated cost USD 0.235936; 9 priced + 35 provably-zero-cost cases, no `n/a`), archiving issue #020.", + "outcome": "MERGED 2026-07-22 as squash `9fb9bc7`. External reviews dispositioned pre-merge: one Codex P2 and one CodeRabbit Major converged on the same defect (zero-usage cases with a provider attempt must stay `n/a`, not `$0`) plus two CodeRabbit ledger Minors and a real merge conflict against #1049's concurrent ID allocation \u2014 all resolved in `eb1046b` (provider-attempt cost branch; issue rows renumbered #018-#023, next-id 024), threads resolved and confirmed by the reviewer. Cost readout subsequently validated live twice: merged-main canary `30018289898` (2026-07-23) and scheduled run `30216191889` (2026-07-26, Estimated cost USD 0.235936; 9 priced + 35 provably-zero-cost cases, no `n/a`), archiving issue #020.", "checks": "PR CI green at merge (squash auto-merge armed by the user); post-merge validation read-only from hosted run logs; tests 28/28 on `tests/eval-quality.test.ts` plus typecheck and prettier at `eb1046b`; no provider dispatch or live RAG spend for this row." }, { @@ -17258,7 +17257,7 @@ "ref": "open-PR recommendation implementation (Cursor)", "head": "multi-head", "scope": "Implement review recommendations safely", - "outcome": "CLOSED #1261/#1262/#1263 without merge (unsafe audit lineage). Pushed fixes: #1273 type-scale + phone-frame scroll + PriorityDock selection; #1275 prefetch source-contract tighten; #1280 rail MutationObserver + main sync; #1281 StepBuilderCard completeness + clipboard draft test (automerge temporarily disabled to land polish). Opened #PDF-137 salvage branch for exit-code 137. Dependabot #1267-1269 left HOLD — workflow approve/update-branch 403 for this integration token; no merge to main.", + "outcome": "CLOSED #1261/#1262/#1263 without merge (unsafe audit lineage). Pushed fixes: #1273 type-scale + phone-frame scroll + PriorityDock selection; #1275 prefetch source-contract tighten; #1280 rail MutationObserver + main sync; #1281 StepBuilderCard completeness + clipboard draft test (automerge temporarily disabled to land polish). Opened #PDF-137 salvage branch for exit-code 137. Dependabot #1267-1269 left HOLD \u2014 workflow approve/update-branch 403 for this integration token; no merge to main.", "checks": "type-scale strict PASS; focused Vitest safety-plan 3/3 and prefetch contract 1/1 and band 9/9; PDF extractor pymupdf tests skipped in this VM; no provider-backed checks; no main merges." }, { @@ -17266,7 +17265,7 @@ "ref": "open-PR review + Bugbot sweep (Cursor)", "head": "multi-head", "scope": "Fresh review of all open PRs + pr-bugbot on each head", - "outcome": "Reviewed 10 open PRs after #1277 merged. No hosted `cursor[bot]` Bugbot comments existed on any PR; ran repo `pr-bugbot` triage per head instead. Cluster: close #1261/#1263 (unsafe audit lineage); salvage/rebuild only thin #1262 bits; hold Dependabot #1267→#1268→#1269 pending workflow approval; fix #1273 type-scale + mockup UX before design trust; sync #1275 and restore ledger from main; #1280 blocked by unrelated Loading-answer strict-mode flake; #1281 sound clinical follow-up with two P2 polish items.", + "outcome": "Reviewed 10 open PRs after #1277 merged. No hosted `cursor[bot]` Bugbot comments existed on any PR; ran repo `pr-bugbot` triage per head instead. Cluster: close #1261/#1263 (unsafe audit lineage); salvage/rebuild only thin #1262 bits; hold Dependabot #1267\u2192#1268\u2192#1269 pending workflow approval; fix #1273 type-scale + mockup UX before design trust; sync #1275 and restore ledger from main; #1280 blocked by unrelated Loading-answer strict-mode flake; #1281 sound clinical follow-up with two P2 polish items.", "checks": "merge-tree classification; gh PR/CI/thread inventory; pr-bugbot review-only agents; no provider-backed checks; no PR mutations." }, { @@ -17306,7 +17305,7 @@ "ref": "PR #1267 / `dependabot/github_actions/...`", "head": "fdc6bdf5e235", "scope": "Bugbot review", - "outcome": "HOLD then MERGE after workflow approval. Pin `anthropics/claude-code-action` b76a077→be7b93b (v1.0.183) SHA matches annotated tag. merge-tree CLEAN; required CI awaiting Dependabot approval.", + "outcome": "HOLD then MERGE after workflow approval. Pin `anthropics/claude-code-action` b76a077\u2192be7b93b (v1.0.183) SHA matches annotated tag. merge-tree CLEAN; required CI awaiting Dependabot approval.", "checks": "pin/tag verify; merge-tree; no provider checks." }, { @@ -17322,7 +17321,7 @@ "ref": "PR #1269 / `dependabot/npm-development/...`", "head": "c9114439e6e6", "scope": "Bugbot review", - "outcome": "HOLD; rebase after #1268. Playwright 1.61.1→1.62.0 is residual flake risk; prettier/eslint-config-next/@next/bundle-analyzer patches otherwise low risk.", + "outcome": "HOLD; rebase after #1268. Playwright 1.61.1\u21921.62.0 is residual flake risk; prettier/eslint-config-next/@next/bundle-analyzer patches otherwise low risk.", "checks": "package.json/lock diff; merge-tree CLEAN; no provider checks." }, { @@ -17474,7 +17473,7 @@ "ref": "PR #1280 / `claude/top-search-design-mockups-w53znc`", "head": "93a9f90ff287", "scope": "Bugbot + CI debug", - "outcome": "NOT READY until Production UI green. Product band rebuild looks sound; Advisory UI green. Hosted failure is Answer Suspense `Loading answer` strict-mode (2 nodes / one hidden) in ui-smoke — not caused by band diff. Optional P2: `useRailOverflow` can miss child-list changes.", + "outcome": "NOT READY until Production UI green. Product band rebuild looks sound; Advisory UI green. Hosted failure is Answer Suspense `Loading answer` strict-mode (2 nodes / one hidden) in ui-smoke \u2014 not caused by band diff. Optional P2: `useRailOverflow` can miss child-list changes.", "checks": "Production UI log job 90037898852; unique diff vs main; focused band unit 9/9 on tip; no provider checks." }, { @@ -17498,7 +17497,7 @@ "ref": "PR #1280 / `claude/top-search-design-mockups-w53znc`", "head": "c844560da909b7f88a1ef351fc833ad45cfb0a81 vs origin/main 7740535a", "scope": "Thorough merge-readiness review vs main", - "outcome": "APPROVE AFTER MAIN SYNC. No P0/P1. Presentation-only shared results band rebuild; clean merge-tree; hosted PR required + Production UI green on tip; 0 unresolved threads. Branch is 1 commit behind unrelated safety-plan #1281 — final-merge audit fails closed until tip contains origin/main. Residual P2 (non-blocking): phone overflowing-rail `mask-image` lacks forced-colors clear (pattern exists for edge-glass); ResizeObserver does not unobserve removed children.", + "outcome": "APPROVE AFTER MAIN SYNC. No P0/P1. Presentation-only shared results band rebuild; clean merge-tree; hosted PR required + Production UI green on tip; 0 unresolved threads. Branch is 1 commit behind unrelated safety-plan #1281 \u2014 final-merge audit fails closed until tip contains origin/main. Residual P2 (non-blocking): phone overflowing-rail `mask-image` lacks forced-colors clear (pattern exists for edge-glass); ResizeObserver does not unobserve removed children.", "checks": "Diff review of 6 unique files; `git merge-tree` clean; `audit:final-merge --dry-run` fails only on missing main ancestor; band DOM 9/9; hosted checks green on tip; no provider-backed app checks." }, { @@ -17538,7 +17537,7 @@ "ref": "PR #1285 / `cursor/pdf-extractor-sigkill-137-0687`", "head": "pending-push", "scope": "CI babysit + Bugbot + main sync", - "outcome": "Before: required CI SUCCESS on tip `630792c9`; mergeable but BEHIND main; 0 unresolved review threads; no `cursor[bot]` Bugbot comments. After: merged `origin/main` cleanly; pr-bugbot found no P0/P1 — fixed P2 by moving SIGKILL/exit-137 regressions out of `describe.runIf(hasPyMuPDF)` and asserting `PdfExtractorProcessError` by name so the OOM path cannot silently skip or pass via JS fallback.", + "outcome": "Before: required CI SUCCESS on tip `630792c9`; mergeable but BEHIND main; 0 unresolved review threads; no `cursor[bot]` Bugbot comments. After: merged `origin/main` cleanly; pr-bugbot found no P0/P1 \u2014 fixed P2 by moving SIGKILL/exit-137 regressions out of `describe.runIf(hasPyMuPDF)` and asserting `PdfExtractorProcessError` by name so the OOM path cannot silently skip or pass via JS fallback.", "checks": "Focused Vitest `tests/pdf-extractor.test.ts` 2 passed / 4 skipped (PyMuPDF absent locally); merge-tree clean; no provider-backed checks." }, { @@ -17585,8 +17584,8 @@ "date": "2026-07-27", "ref": "PR #1287 / `claude/site-audit-quick-wins-21v9gb`", "head": "18fcfae24b41cdd5caebd2780afa963a2a1335a5", - "scope": "Follow-up — Bugbot/CodeRabbit residuals addressed (supersedes the 97ab067 Bugbot row)", - "outcome": "Residual P2 closed: import-graph lock added — an allowlist test asserts `cross-mode-differentials.ts` may import ONLY the precomputed index + the (type-only) catalog type, catching direct, transitive-via-new-import, and dynamic `import()`/`require` reintroductions of `@/lib/differentials`. P3s closed: stale `cross-mode-links.tsx` comment fixed; `build-cross-mode-differentials-index.mjs` listed in `scripts-index.md`. CodeRabbit's two Minor nits (guard depth + this ledger refresh) addressed.", + "scope": "Follow-up \u2014 Bugbot/CodeRabbit residuals addressed (supersedes the 97ab067 Bugbot row)", + "outcome": "Residual P2 closed: import-graph lock added \u2014 an allowlist test asserts `cross-mode-differentials.ts` may import ONLY the precomputed index + the (type-only) catalog type, catching direct, transitive-via-new-import, and dynamic `import()`/`require` reintroductions of `@/lib/differentials`. P3s closed: stale `cross-mode-links.tsx` comment fixed; `build-cross-mode-differentials-index.mjs` listed in `scripts-index.md`. CodeRabbit's two Minor nits (guard depth + this ledger refresh) addressed.", "checks": "vitest `cross-mode-differentials-index` 3/3; typecheck + lint PASS; `docs:check-scripts` + `docs:check-links` PASS; `check:cross-mode-index` PASS; no provider-backed checks." }, { @@ -17594,7 +17593,7 @@ "ref": "PR #1287 / `claude/site-audit-quick-wins-21v9gb`", "head": "5c2816d1dc2e7a99c37d27310b487bcac5232db3", "scope": "Production UI CI fix: differentials-home hydration strict-mode", - "outcome": "FIXED. Hosted Production UI failed solely on `dashboard differentials mode param redirects…`: `getByTestId(differentials-home)` hit 2 nodes (server+client overlap). Applied `expectSingleSettledOwner` before the visibility assert. No product change.", + "outcome": "FIXED. Hosted Production UI failed solely on `dashboard differentials mode param redirects\u2026`: `getByTestId(differentials-home)` hit 2 nodes (server+client overlap). Applied `expectSingleSettledOwner` before the visibility assert. No product change.", "checks": "Focused production Playwright journey PASS 1/1 via `npm run test:e2e` (system Chrome); no provider-backed checks." }, { @@ -17618,7 +17617,7 @@ "ref": "PR #1287 / `claude/site-audit-quick-wins-21v9gb`", "head": "88d8638974075fa91334c2bb4a0e6b54fda00176", "scope": "Review closeout: main sync + resolved-graph guard + ledger attribution", - "outcome": "FIXED. Cause of GitHub CONFLICTING/DIRTY: both tips appended `docs/branch-review-ledger.md` (union); `git merge-tree` was clean — merged `origin/main` (#1284 ledger rows). CodeRabbit recursive import-graph ask: walk resolved runtime imports from `cross-mode-differentials.ts` (services/forms boundary pattern) + keep entry allowlist. Supersedes residual wording on rows 1148/1149: import-graph lock + scripts-index + comment already landed; `client-performance-boundaries` guards the consumer dynamic import, `cross-mode-differentials-index` guards the catalog module/graph. Hosted Production UI already green after hydration settle.", + "outcome": "FIXED. Cause of GitHub CONFLICTING/DIRTY: both tips appended `docs/branch-review-ledger.md` (union); `git merge-tree` was clean \u2014 merged `origin/main` (#1284 ledger rows). CodeRabbit recursive import-graph ask: walk resolved runtime imports from `cross-mode-differentials.ts` (services/forms boundary pattern) + keep entry allowlist. Supersedes residual wording on rows 1148/1149: import-graph lock + scripts-index + comment already landed; `client-performance-boundaries` guards the consumer dynamic import, `cross-mode-differentials-index` guards the catalog module/graph. Hosted Production UI already green after hydration settle.", "checks": "Focused vitest index+boundaries 10/10; `check:cross-mode-index` PASS; merge-tree CLEAN vs origin/main; prior Production UI PASS on `f738f083`; no provider-backed checks." }, { @@ -17626,7 +17625,7 @@ "ref": "PR #1287 / `claude/site-audit-quick-wins-21v9gb`", "head": "97ab067bfdca644e0750bfbc717da7d58ecd27ee", "scope": "Bugbot defect hunt (cursoragent request; no hosted cursor[bot] threads)", - "outcome": "APPROVE pending exact-head required CI. No P0/P1. Projection ≡ live helpers (201 diagnoses / 31 presentations / 20 alias keys); `--check` compares parsed values (Prettier-safe); CI `static-pr` + `verify:cheap` wire `check:cross-mode-index`. Residual P2: re-importing `@/lib/differentials` into `cross-mode-differentials.ts` would restore the ~1.2 MB lazy-chunk weight while data gates stay green — no import-graph lock yet. P3: stale comment in `cross-mode-links.tsx`; scripts-index omits new generator.", + "outcome": "APPROVE pending exact-head required CI. No P0/P1. Projection \u2261 live helpers (201 diagnoses / 31 presentations / 20 alias keys); `--check` compares parsed values (Prettier-safe); CI `static-pr` + `verify:cheap` wire `check:cross-mode-index`. Residual P2: re-importing `@/lib/differentials` into `cross-mode-differentials.ts` would restore the ~1.2 MB lazy-chunk weight while data gates stay green \u2014 no import-graph lock yet. P3: stale comment in `cross-mode-links.tsx`; scripts-index omits new generator.", "checks": "`check:cross-mode-index` PASS; vitest `cross-mode-differentials-index` 2/2; gate-manifest PASS; drift/invalid-JSON proofs FAIL closed; import-graph grep clean today; no provider-backed checks." }, { @@ -17738,7 +17737,7 @@ "ref": "PR #1192 / `cursor/fix-mobile-composer-edge-scroll-5b1d`", "head": "head 2597dd305fd61e4e16166cccd109ff6f8eae0a33 / squash c4d5f47a39", "scope": "prlanded after squash merge", - "outcome": "LANDED. Phone Answer edge-dock hide/reveal, layout-clamp versus upward-intent detection, and composer focus binding, reconciled against the #1222 cross-breakpoint header. `git diff c4d5f47a 2597dd30` empty, so the content landed intact; remote branch deleted at merge; required contexts Gitleaks, PR required and PR policy all SUCCESS on the merged head. Two things worth keeping: merging `main` made the ledger's `union` driver re-append records both sides already carried, failing `check:branch-review-ledger` twice in one hour (see #082), and the final head was a `coderabbitai[bot]` auto-fix swapping an inline two-step upward scroll for the shared `scrollPrimarySurface` helper in `tests/ui-smoke.spec.ts` — an identical earlier auto-fix had been reverted on this branch, so it was re-proven rather than trusted.", + "outcome": "LANDED. Phone Answer edge-dock hide/reveal, layout-clamp versus upward-intent detection, and composer focus binding, reconciled against the #1222 cross-breakpoint header. `git diff c4d5f47a 2597dd30` empty, so the content landed intact; remote branch deleted at merge; required contexts Gitleaks, PR required and PR policy all SUCCESS on the merged head. Two things worth keeping: merging `main` made the ledger's `union` driver re-append records both sides already carried, failing `check:branch-review-ledger` twice in one hour (see #082), and the final head was a `coderabbitai[bot]` auto-fix swapping an inline two-step upward scroll for the shared `scrollPrimarySurface` helper in `tests/ui-smoke.spec.ts` \u2014 an identical earlier auto-fix had been reverted on this branch, so it was re-proven rather than trusted.", "checks": "`npm run verify:ui` 285/285 Chromium on the production build; `npm run verify:cheap` pass except the pre-existing `tests/pdf-extractor.test.ts` Python-OCR case, whose subject is absent from the diff (3437/3439 otherwise); `ui-chrome-scroll` + `ui-phone-scroll` 30/30 across phone, tablet and desktop; `use-hide-on-scroll` + `header-scroll-hide-contract` + `mobile-composer-reserve` 39/39; the CodeRabbit-modified in-flow collapse test re-run 3/3. No provider-backed checks." }, { @@ -17810,7 +17809,7 @@ "ref": "PR #1241 / `cursor/imp04-prune-dead-exports-01f2`", "head": "2c6d9c96 merge of origin/main 5475fcfb", "scope": "Main sync after GitHub CONFLICTING", - "outcome": "SIMPLE. `git merge-tree --write-tree` clean before merge; GitHub DIRTY was staleness behind #1227/#1245/#1200. Ledger union auto-merge. Calculator path rename `calculator-mockups`→`calculators` detected; IMP-04 dead-export prune content carried onto new paths (`calculatorById`/`useCalculatorState` still absent). No conflicting intents; no conflict markers.", + "outcome": "SIMPLE. `git merge-tree --write-tree` clean before merge; GitHub DIRTY was staleness behind #1227/#1245/#1200. Ledger union auto-merge. Calculator path rename `calculator-mockups`\u2192`calculators` detected; IMP-04 dead-export prune content carried onto new paths (`calculatorById`/`useCalculatorState` still absent). No conflicting intents; no conflict markers.", "checks": "merge-tree clean; merge ort; `check:branch-review-ledger`; `tsc --noEmit` clean; no stale calculator-mockups imports. No provider calls." }, { @@ -17834,7 +17833,7 @@ "ref": "PR #1241 / `cursor/imp04-prune-dead-exports-01f2`", "head": "ac056083bad351659cc970171c8cd62bbb3526a5", "scope": "Codex P2: sync recipe catalogs after prune", - "outcome": "FIXED. Updated `.design-sync/conventions.md` + `docs/redesign/09-ui-primitives-recipes.md` (plus badge/design-system mentions) so catalogs no longer advertise deleted or module-private recipes (`insetCard`, `iconTile`, `compactMetadataRow`, `commandInput`, `toneWarningQuiet`, …).", + "outcome": "FIXED. Updated `.design-sync/conventions.md` + `docs/redesign/09-ui-primitives-recipes.md` (plus badge/design-system mentions) so catalogs no longer advertise deleted or module-private recipes (`insetCard`, `iconTile`, `compactMetadataRow`, `commandInput`, `toneWarningQuiet`, \u2026).", "checks": "Doc grep of catalogs vs `ui-primitives` export surface; `check:branch-review-ledger`. No provider calls." }, { @@ -17930,7 +17929,7 @@ "ref": "PR #1253 / `remediate-system-audit-findings`", "head": "cc1fa9d48434c809e2cf73dfeb3124d2b36f0968", "scope": "Authorized babysit peek", - "outcome": "CLOSED before sweep actions. CONFLICTING vs main with clinical/answer/privacy paths; non-trivial — no merge attempted. Policy failure was missing Clinical Governance Preflight (body not agent-managed).", + "outcome": "CLOSED before sweep actions. CONFLICTING vs main with clinical/answer/privacy paths; non-trivial \u2014 no merge attempted. Policy failure was missing Clinical Governance Preflight (body not agent-managed).", "checks": "merge-tree conflict inventory only; no provider-backed checks." }, { @@ -18002,7 +18001,7 @@ "ref": "PR #1255 / `execute-audit-remediation-plan`", "head": "cc645928cefb18e4c08870ddc1c483bc051a92b9", "scope": "Authorized babysit peek", - "outcome": "CLOSED before sweep actions. CONFLICTING vs main including `api/answer`, ClinicalDashboard, privacy routes; non-trivial — no merge attempted. Policy failure was missing Clinical Governance Preflight.", + "outcome": "CLOSED before sweep actions. CONFLICTING vs main including `api/answer`, ClinicalDashboard, privacy routes; non-trivial \u2014 no merge attempted. Policy failure was missing Clinical Governance Preflight.", "checks": "merge-tree conflict inventory only; no provider-backed checks." }, { @@ -18122,15 +18121,15 @@ "ref": "`cursor/fix-mobile-composer-edge-scroll-5b1d` (PR #1192)", "head": "333e67b8", "scope": "pr-ci-fix: Static PR checks / Maintainability hotspot budgets", - "outcome": "Main merge (e688c6e2) expanded a JSX comment from 2→3 lines while restructuring heroComposerBreakpoint/heroOwnsPhoneComposer declarations, netting +2 lines vs budget-fix commit (ae77f8c3). ClinicalDashboard.tsx hit 4141 vs 4140 budget. Fix: compressed 3-line comment back to 2 lines. Zero behaviour change.", - "checks": "`npm run check:maintainability-budgets` → PASS (4140/4140). No provider-backed checks." + "outcome": "Main merge (e688c6e2) expanded a JSX comment from 2\u21923 lines while restructuring heroComposerBreakpoint/heroOwnsPhoneComposer declarations, netting +2 lines vs budget-fix commit (ae77f8c3). ClinicalDashboard.tsx hit 4141 vs 4140 budget. Fix: compressed 3-line comment back to 2 lines. Zero behaviour change.", + "checks": "`npm run check:maintainability-budgets` \u2192 PASS (4140/4140). No provider-backed checks." }, { "date": "2026-07-25", "ref": "`cursor/fix-mode-switch-lag-22f6`", "head": "0ef62ff521fb9f0457f685e9d2f50a24d640e663", "scope": "Frontend-architecture review: loading/navigation performance for modes/pages", - "outcome": "No P0. P1: (1) GlobalSearchShell statically imports ClinicalDashboard into shared (search-app) layout client graph — every namespaced mode pays dashboard module weight; (2) ClientHydrationBoundary blanks standalone mode children until hydrate — defeats RSC paint for DSM/factsheets/etc. P2: ClinicalDashboard↔standalone remount + grid-template-columns transition; dashboard URL sync still useEffect+rAF (shell already render-time); ToolsHub ssr:false on /?mode=tools; MutationObserver portal rebind cost on mode-home slot changes; SearchCommandProvider value tied to query in shell. P3/#007: /tools vs /?mode=tools dual entry (PT-11 vs nav). Quick wins: dynamic() ClinicalDashboard; remove/narrow ClientHydrationBoundary; point tools href to /tools. Larger: unify shells / extract shared chrome.", + "outcome": "No P0. P1: (1) GlobalSearchShell statically imports ClinicalDashboard into shared (search-app) layout client graph \u2014 every namespaced mode pays dashboard module weight; (2) ClientHydrationBoundary blanks standalone mode children until hydrate \u2014 defeats RSC paint for DSM/factsheets/etc. P2: ClinicalDashboard\u2194standalone remount + grid-template-columns transition; dashboard URL sync still useEffect+rAF (shell already render-time); ToolsHub ssr:false on /?mode=tools; MutationObserver portal rebind cost on mode-home slot changes; SearchCommandProvider value tied to query in shell. P3/#007: /tools vs /?mode=tools dual entry (PT-11 vs nav). Quick wins: dynamic() ClinicalDashboard; remove/narrow ClientHydrationBoundary; point tools href to /tools. Larger: unify shells / extract shared chrome.", "checks": "Static architecture review of SharedSearchAppShell/GlobalSearchShell/ClinicalDashboard/MasterSearchHeader/app-modes/search-route-ownership/mode homes/tools routes; prior mode-switch ledger rows at b9484396/775d15ad noted. No browser, verify:ui, bundle measure, or provider-backed checks." }, { @@ -18138,7 +18137,7 @@ "ref": "`cursor/fix-mode-switch-lag-22f6`", "head": "b9484396347defaaa934571604b9d165ae6d8b98", "scope": "Same-class mode-switch thrash review + fixes", - "outcome": "FIXED prior open P2s from 54d45f68 hunt: crossModeSearch now mirrors selectSearchMode (navigate-only when leaving dashboard); shared shell resets phone scrollTop + scroll-hide on pathname; hero portal keeps default composer until host attaches; ModeHomeRouteLoading uses --shell-header-h; services/forms contentAlign stays startOnPhone while loading. No P0/P1. Residual P2: ClinicalDashboard↔standalone shell remount + sidebar grid-template-columns transition; dashboard-internal Answer↔Documents still eager setSearchMode (overlay/hero flip by design, scroll now reset). Residual P3/#007: /tools vs /?mode=tools dual entry.", + "outcome": "FIXED prior open P2s from 54d45f68 hunt: crossModeSearch now mirrors selectSearchMode (navigate-only when leaving dashboard); shared shell resets phone scrollTop + scroll-hide on pathname; hero portal keeps default composer until host attaches; ModeHomeRouteLoading uses --shell-header-h; services/forms contentAlign stays startOnPhone while loading. No P0/P1. Residual P2: ClinicalDashboard\u2194standalone shell remount + sidebar grid-template-columns transition; dashboard-internal Answer\u2194Documents still eager setSearchMode (overlay/hero flip by design, scroll now reset). Residual P3/#007: /tools vs /?mode=tools dual entry.", "checks": "Focused Vitest ownership/align/hide-on-scroll/merge-artifacts/overlay 46/46; typecheck; static contracts for portal/scroll reset/crossModeSearch. No verify:ui / provider-backed checks." }, { @@ -18146,7 +18145,7 @@ "ref": "`cursor/fix-mode-switch-lag-22f6` / PR #1187", "head": "775d15adef8155aba68e43f0e9354adf60f1ea8d", "scope": "Same-class thrash fixes lint closeout", - "outcome": "Supersedes b9484396 row for lint follow-up: pathname bottomComposerHidden reset moved to render-time; removed unused desktopHomeComposerFallback. verify:cheap green. Residual unchanged (dashboard↔standalone remount; #007 Tools dual entry).", + "outcome": "Supersedes b9484396 row for lint follow-up: pathname bottomComposerHidden reset moved to render-time; removed unused desktopHomeComposerFallback. verify:cheap green. Residual unchanged (dashboard\u2194standalone remount; #007 Tools dual entry).", "checks": "verify:cheap 3345 passed / 3 skipped; focused ownership tests; eslint clean on touched shell/header. No provider checks." }, { @@ -18154,8 +18153,8 @@ "ref": "`cursor/fix-mode-switch-lag-22f6` / PR #1187", "head": "876d7ecfa1ae8ec79fc0f0bdf1198c6640ad89b8", "scope": "Parallel loading UX + frontend-architecture review + quick-win fixes", - "outcome": "No P0. Confirmed live: H1 dashboard↔standalone remount dominant (~0.6–1.2s settle); H4 hero portal rebind; H3 registry post-paint. FIXED quick wins: remove ClientHydrationBoundary blanking; ModeHomeRouteLoading startOnPhone; mode-home loading.tsx alignment/additions; forms server defaultFormSlug + client-boundary test; dynamic ClinicalDashboard; sidebar grid transition mount-gate; forms drop key=query; DocumentViewer key=id; therapy Suspense ModeHomeRouteLoading; redirect /?mode=services|forms. Residual P2: unify shells (H1), stable hero slot, registry abort+LRU/summary fields, Tools dual entry #007, prescribing full-catalogue cliff.", - "checks": "Parallel explore×3 + debug measurement; focused Vitest loading/forms/ownership/align contracts; typecheck; eslint touched shell. No verify:ui / provider-backed checks." + "outcome": "No P0. Confirmed live: H1 dashboard\u2194standalone remount dominant (~0.6\u20131.2s settle); H4 hero portal rebind; H3 registry post-paint. FIXED quick wins: remove ClientHydrationBoundary blanking; ModeHomeRouteLoading startOnPhone; mode-home loading.tsx alignment/additions; forms server defaultFormSlug + client-boundary test; dynamic ClinicalDashboard; sidebar grid transition mount-gate; forms drop key=query; DocumentViewer key=id; therapy Suspense ModeHomeRouteLoading; redirect /?mode=services|forms. Residual P2: unify shells (H1), stable hero slot, registry abort+LRU/summary fields, Tools dual entry #007, prescribing full-catalogue cliff.", + "checks": "Parallel explore\u00d73 + debug measurement; focused Vitest loading/forms/ownership/align contracts; typecheck; eslint touched shell. No verify:ui / provider-backed checks." }, { "date": "2026-07-25", @@ -18217,7 +18216,7 @@ "date": "2026-07-25", "ref": "automated-audit-remediations (PR #1158)", "head": "aa745922f00", - "scope": "Babysit sweep: automated audit remediations — squash-merged", + "scope": "Babysit sweep: automated audit remediations \u2014 squash-merged", "outcome": "pr-required", "checks": "merged" }, @@ -18233,7 +18232,7 @@ "date": "2026-07-25", "ref": "canary-comparison-preflight (PR #1180)", "head": "43f261cf229", - "scope": "Babysit sweep: canary comparison preflight docs — squash-merged", + "scope": "Babysit sweep: canary comparison preflight docs \u2014 squash-merged", "outcome": "pr-required", "checks": "merged" }, @@ -18257,7 +18256,7 @@ "date": "2026-07-25", "ref": "codex/complete-all-pending-tasks (PR #1191)", "head": "e2488dbb108", - "scope": "Babysit sweep: scoped-label pagination + order assertion for CodeRabbit thread — squash-merged", + "scope": "Babysit sweep: scoped-label pagination + order assertion for CodeRabbit thread \u2014 squash-merged", "outcome": "unit + pr-required", "checks": "merged" }, @@ -18329,7 +18328,7 @@ "date": "2026-07-25", "ref": "cursor-indexing-ignore (PR #1171)", "head": "3a4036580df", - "scope": "Babysit sweep: Cursor indexing ignore rules — squash-merged", + "scope": "Babysit sweep: Cursor indexing ignore rules \u2014 squash-merged", "outcome": "pr-required", "checks": "merged" }, @@ -18345,7 +18344,7 @@ "date": "2026-07-25", "ref": "cursor/alias-slot-disjointness-guard-6273 (PR #1215)", "head": "406cf21eb730809fb06df00b1a9299e3462c728a", - "scope": "prlanded — generalized #030 contracts + ledger #081", + "scope": "prlanded \u2014 generalized #030 contracts + ledger #081", "outcome": "LANDED. Squash `b2d794c532ea8b7e259751005165f69906fcd784`. Adds two table-independent guards to `tests/eval-document-matching.test.ts`: pairwise alias disjointness across every multi-slot eval case, and the structural rule that one document can never satisfy every slot of a multi-slot case. Also opened ledger item #081 for the then-open PR #1196 alias conflict. Content verified by tree comparison against the squash commit (identical); remote branch deleted at merge, local pruned.", "checks": "`npm run verify:cheap` green; hosted `PR required` green; tree-identity check `git diff b2d794c5 406cf21e` empty. No provider-backed checks." }, @@ -18386,14 +18385,14 @@ "ref": "cursor/eval-matching-distinct-identity-6273", "head": "f5620e3a4a2d60fd8a67fd43d8046726f1761e5f", "scope": "Self-review of the merged #030/#075 fixes against current main", - "outcome": "Before: merged coverage matched expectations to distinct source _positions_, so one document repeated across `answer.citations` still filled both comparison slots, and first-come assignment made `allHit` depend on `expectedFiles` order; `PR_POLICY_BODY.md` was back on main (via #1153) ready to overwrite the next PR body; the #030/#075 queue row survived their archival. After: coverage dedupes by document text and assigns by maximum bipartite matching, label accumulation is linear, the stale template is removed, and #080 records the removed admission widening for approved eval re-test. Both new contracts were verified failing against main's matcher before the fix. RAG impact: no retrieval behaviour change — eval matching and label bookkeeping only.", + "outcome": "Before: merged coverage matched expectations to distinct source _positions_, so one document repeated across `answer.citations` still filled both comparison slots, and first-come assignment made `allHit` depend on `expectedFiles` order; `PR_POLICY_BODY.md` was back on main (via #1153) ready to overwrite the next PR body; the #030/#075 queue row survived their archival. After: coverage dedupes by document text and assigns by maximum bipartite matching, label accumulation is linear, the stale template is removed, and #080 records the removed admission widening for approved eval re-test. Both new contracts were verified failing against main's matcher before the fix. RAG impact: no retrieval behaviour change \u2014 eval matching and label bookkeeping only.", "checks": "Focused Vitest 39/39 (eval-document-matching, eval-utils, eval-search, search-scope, rag-imputation-contract); fail-closed proof 2 failed on the `origin/main` matcher; `npm run verify:cheap` pass (3379 passed, 5 skipped); `check:branch-review-ledger` and `check:pr-policy` pass; no OpenAI/Supabase/provider-backed checks run." }, { "date": "2026-07-25", "ref": "cursor/eval-matching-distinct-identity-6273 (PR #1204)", "head": "c0db5f5810a37dbe7df9efa3d5479db134c98e10", - "scope": "prlanded — #030 coverage hardening", + "scope": "prlanded \u2014 #030 coverage hardening", "outcome": "LANDED. Squash `eb443dfda0fcfca8181e6839d156d9986dfc52db`. `expectedFileCoverage` now dedupes the citation window by document identity and assigns sources by maximum bipartite matching, closing two re-entry routes into #030 (repeat chunk citations of one document; order-dependent greedy assignment). Content verified by tree comparison against the squash commit (identical). Remote branch deleted at merge; local branch pruned 2026-07-25 after that verification.", "checks": "`npm run verify:cheap` green pre-merge; hosted `PR required` green; tree-identity check `git diff eb443dfd c0db5f58` empty. No provider-backed checks." }, @@ -18426,14 +18425,14 @@ "ref": "cursor/fix-mode-switch-lag-22f6", "head": "54d45f687e3723f51fa3d7e9940692c9a6e3b52c", "scope": "Same-class bug hunt: mode-switch/layout thrash after reserve-flip fix", - "outcome": "No P0. Branch fix mitigates pathname∧searchMode gate, shell changeMode optimistic setSearchMode, selectSearchMode leaving dashboard, and always-on padding-bottom transitions. Still open P2s: (1) ClinicalDashboard.crossModeSearch still setSearchMode before router.push without isDashboardModeHref guard; (2) dashboard-internal Answer↔/?mode=* still eager setSearchMode → overlay/collapse + heroBreakpoint + portal rebind; (3) standalone shell persists #main-content scrollTop + phoneScrollHide across mode homes; (4) ClinicalDashboard↔GlobalStandaloneSearchShellClient remount + grid-template-columns transition; (5) hero portal null gap while slot/MutationObserver rebinds; (6) ModeHomeRouteLoading phone min-h 13.5rem vs idle-reserve mode homes; (7) /tools vs /?mode=tools dual shell (#007). P3: services/forms contentAlign center→startOnPhone after registry load.", + "outcome": "No P0. Branch fix mitigates pathname\u2227searchMode gate, shell changeMode optimistic setSearchMode, selectSearchMode leaving dashboard, and always-on padding-bottom transitions. Still open P2s: (1) ClinicalDashboard.crossModeSearch still setSearchMode before router.push without isDashboardModeHref guard; (2) dashboard-internal Answer\u2194/?mode=* still eager setSearchMode \u2192 overlay/collapse + heroBreakpoint + portal rebind; (3) standalone shell persists #main-content scrollTop + phoneScrollHide across mode homes; (4) ClinicalDashboard\u2194GlobalStandaloneSearchShellClient remount + grid-template-columns transition; (5) hero portal null gap while slot/MutationObserver rebinds; (6) ModeHomeRouteLoading phone min-h 13.5rem vs idle-reserve mode homes; (7) /tools vs /?mode=tools dual shell (#007). P3: services/forms contentAlign center\u2192startOnPhone after registry load.", "checks": "Static source audit of shell/dashboard/header/reserve/CSS/app-modes/skeletons; no browser/provider checks." }, { "date": "2026-07-25", "ref": "cursor/ledger-009-010-032-041-063-519b (PR #1175)", "head": "87b6b432c19", - "scope": "Babysit sweep: close ledger #009/#010/#032/#041/#063 — resolved outstanding-issues merge + prettier, squash-merged", + "scope": "Babysit sweep: close ledger #009/#010/#032/#041/#063 \u2014 resolved outstanding-issues merge + prettier, squash-merged", "outcome": "static-pr + pr-required", "checks": "merged" }, @@ -18449,7 +18448,7 @@ "date": "2026-07-25", "ref": "cursor/ledger-081-closeout-6273 (PR #1220)", "head": "84e91194ecca7f74c0d70b9e30e1dbd05ab7853f", - "scope": "prlanded — archive outstanding item #081", + "scope": "prlanded \u2014 archive outstanding item #081", "outcome": "LANDED. Squash `e7e60c6d02a37c1f5958cb97936bd3533c7a2f46`. #081 moved from Open items to Resolved/archive after PR #1196 was closed 2026-07-25 as superseded by #913 / current main; successor #1198 does not touch `src/lib/eval-document-matching.ts`, and the #1215 contracts fail closed on any re-added dual-listed alias. Merge friction worth recording: a `github-actions[bot]` branch-sync merge landed every 10-20 minutes and every bot-authored head produced `action_required` workflow runs, so the three required checks never reported and both normal and `--admin` merges were refused; runs on agent-pushed heads execute normally, so the resolution was to push an own-authored head and merge on green. Content verified by tree comparison against the squash commit (identical); remote branch deleted at merge, local pruned.", "checks": "`npm run verify:cheap` on merged main: 387 files / 3431 tests pass; hosted CI, SAST, Secret Scan and PR Policy green on `84e91194`; `npm run docs:check-links` pass. No provider-backed checks." }, @@ -18530,7 +18529,7 @@ "ref": "cursor/pr1197-fix-regressions-d06a (PR #1197 fix)", "head": "c1e9696de6000440ad5b44e4d2fb2738a858deae", "scope": "Fix-forward after Bugbot do-not-merge review", - "outcome": "FIXED for tip. Synced to origin/main; restored clinical-notes trust gate + boundary tests + summaryMode 400 contract by taking main; removed ISSUE-07 RAG pre-classifier (rag.ts matches main — RAG impact: no retrieval behaviour change). Kept only additive SQL remediation: migration 20260725000000 (real worker URL + ISSUE-05 revokes), schema.sql URL/[REDACTED] fix + ISSUE-05, regenerated drift-manifest. Dropped broken upload authority refs (undefined canonicalAuthority).", + "outcome": "FIXED for tip. Synced to origin/main; restored clinical-notes trust gate + boundary tests + summaryMode 400 contract by taking main; removed ISSUE-07 RAG pre-classifier (rag.ts matches main \u2014 RAG impact: no retrieval behaviour change). Kept only additive SQL remediation: migration 20260725000000 (real worker URL + ISSUE-05 revokes), schema.sql URL/[REDACTED] fix + ISSUE-05, regenerated drift-manifest. Dropped broken upload authority refs (undefined canonicalAuthority).", "checks": "Vitest: summaryMode reject + ClinicalNotes boundary 4/4; rag-classifier-memo + rag-tail-latency 17/17; upload smart-title/cleanup 3/3; check:migration-role pass; drift:manifest regenerated via Docker. No provider-backed checks." }, { @@ -18554,7 +18553,7 @@ "ref": "cursor/search-performance-review-4ee9 (PR #1134)", "head": "692834a86e612cc8b311dc6895e007f182f5c5b8", "scope": "Open-PR maintenance: superseded docs-link thread and clean main sync", - "outcome": "Before: branch was behind current main with one outdated docs-link thread; its product tree already matched main. After: merged current main cleanly and verified the route-group-aware docs-link fix now covers legacy route references. RAG impact: no retrieval behaviour change — history sync and docs tooling verification only.", + "outcome": "Before: branch was behind current main with one outdated docs-link thread; its product tree already matched main. After: merged current main cleanly and verified the route-group-aware docs-link fix now covers legacy route references. RAG impact: no retrieval behaviour change \u2014 history sync and docs tooling verification only.", "checks": "`node scripts/check-docs-links.mjs` pass (1154 references); clean merge-tree; no live RAG canary or provider-backed check run." }, { @@ -18610,7 +18609,7 @@ "ref": "execute-audit-code-remediation (PR #1162)", "head": "d5455837231f5cb6a927e8c4752ef5aa9c72767c", "scope": "Merge conflict + CI + Bugbot review", - "outcome": "Merged origin/main (164 behind). Fixed conflicts in ClinicalDashboard/global-search-shell/mode-home/search-scope/tests/pdf extractor. Renamed duplicate migration 20260724120000→20260724130200. CI: skills openai.yaml, owner-scope setup-status exemption, sitemap, drift hash, answer-render duplicate key, setup-status mock `.eq`. Bugbot: fixed Codex P1 view-only indexing + P2 differential back; also fixed P2 viewer visibility for retained images and duplicate-upload cleanup ledger fail-closed.", + "outcome": "Merged origin/main (164 behind). Fixed conflicts in ClinicalDashboard/global-search-shell/mode-home/search-scope/tests/pdf extractor. Renamed duplicate migration 20260724120000\u219220260724130200. CI: skills openai.yaml, owner-scope setup-status exemption, sitemap, drift hash, answer-render duplicate key, setup-status mock `.eq`. Bugbot: fixed Codex P1 view-only indexing + P2 differential back; also fixed P2 viewer visibility for retained images and duplicate-upload cleanup ledger fail-closed.", "checks": "Focused Vitest (back-href/worker/skills/setup-status/owner-scope/drift/sitemap/search-scope/favourites/forms/therapy/document-detail/upload-ledger) + typecheck + check:skills/migration-role/sitemap; no provider-backed checks." }, { @@ -18681,7 +18680,7 @@ "date": "2026-07-25", "ref": "fix-physics-animation-audit (PR #1142)", "head": "e966b5aa972", - "scope": "Babysit sweep: spring physics / reduced-motion — auto-merged after main sync", + "scope": "Babysit sweep: spring physics / reduced-motion \u2014 auto-merged after main sync", "outcome": "pr-required", "checks": "merged" }, @@ -18697,7 +18696,7 @@ "date": "2026-07-25", "ref": "implement-audit-recommendations-fix (PR #1140)", "head": "f4ae0a7217e", - "scope": "Babysit sweep: viewport/keyboard audit — squash-merged after CI green + thread triage", + "scope": "Babysit sweep: viewport/keyboard audit \u2014 squash-merged after CI green + thread triage", "outcome": "production-ui + pr-required", "checks": "merged" }, @@ -18761,7 +18760,7 @@ "date": "2026-07-25", "ref": "information-page-shell (PR #1148)", "head": "5b9574af480", - "scope": "Babysit sweep: unify information-page structure — squash-merged", + "scope": "Babysit sweep: unify information-page structure \u2014 squash-merged", "outcome": "pr-required", "checks": "merged" }, @@ -18777,7 +18776,7 @@ "date": "2026-07-25", "ref": "mobile-ergonomics-fixes (PR #1156)", "head": "de1a82b4936", - "scope": "Babysit sweep: mobile touch ergonomics — squash-merged", + "scope": "Babysit sweep: mobile touch ergonomics \u2014 squash-merged", "outcome": "pr-required", "checks": "merged" }, @@ -18817,7 +18816,7 @@ "date": "2026-07-25", "ref": "PR #1090 / `cursor/fix-phone-dock-edge-1b1d`", "head": "c993975f6b18393a9ff09f9145fd42dbb35df942 (merged as 09028ef217209fceb53f1122ac7738b509bce323)", - "scope": "prlanded — phone dock edge-to-edge / white-strip fix", + "scope": "prlanded \u2014 phone dock edge-to-edge / white-strip fix", "outcome": "MERGED. Content verified on `origin/main` (empty three-dot diff; spot-check dock CSS, ClinicalDashboard inset-0 shell, edge-to-edge Playwright test). No orphaned late commits. Remote branch already deleted; local branch removed. Codex review found no major issues; required CI green at merge.", "checks": "Hosted required + Production UI green at merge; local maintainability budget + Prettier follow-ups landed in tip `c993975f`." }, @@ -18826,7 +18825,7 @@ "ref": "PR #1162 / `execute-audit-code-remediation`", "head": "692eb248c095d64443a5f9ed0ab7b02394f0ed4b", "scope": "Explicit thorough Antigravity PR review", - "outcome": "CONDITIONAL after rebase. Substantive upload RPC + batch signed-URL work looks sound (service_role-only SECURITY DEFINER; batch auth equivalent to single-image). Still CONFLICTING vs main (ClinicalDashboard, global-search-shell, mode-home-template, search-scope, tests, pdf extractor). P2: batch rate-limit amplification ×100; mobile back `push` vs `back` semantics; duplicate-hash match via plpgsql message text. CI red on Static/Safety/Unit/UI/Migration.", + "outcome": "CONDITIONAL after rebase. Substantive upload RPC + batch signed-URL work looks sound (service_role-only SECURITY DEFINER; batch auth equivalent to single-image). Still CONFLICTING vs main (ClinicalDashboard, global-search-shell, mode-home-template, search-scope, tests, pdf extractor). P2: batch rate-limit amplification \u00d7100; mobile back `push` vs `back` semantics; duplicate-hash match via plpgsql message text. CI red on Static/Safety/Unit/UI/Migration.", "checks": "merge-tree conflict list; static auth/RPC review. No provider/migration replay." }, { @@ -18866,7 +18865,7 @@ "ref": "PR #1186 / `remediate-repository-audit-findings`", "head": "8637fec36dea6534c02e5b3f12e5a913c10bc455", "scope": "Explicit thorough Antigravity PR review", - "outcome": "DO NOT MERGE. P0: duplicate `const results` in `scripts/eval-retrieval.ts` (RAG eval surface; needs RAG impact line). P0: skills catalog 32→35 breaks `tests/database-skills.test.ts`. P1: stale-lock heartbeat never fires under `spawnSync`; `skill-create` YAML wrong shape; `sweep-merged-branches` destructive without dry-run + shell interpolation. Inherits conflict markers.", + "outcome": "DO NOT MERGE. P0: duplicate `const results` in `scripts/eval-retrieval.ts` (RAG eval surface; needs RAG impact line). P0: skills catalog 32\u219235 breaks `tests/database-skills.test.ts`. P1: stale-lock heartbeat never fires under `spawnSync`; `skill-create` YAML wrong shape; `sweep-merged-branches` destructive without dry-run + shell interpolation. Inherits conflict markers.", "checks": "`git show` eval-retrieval duplicate const; marker scan. No provider/eval runs." }, { @@ -18874,7 +18873,7 @@ "ref": "PR #1187 / `cursor/fix-mode-switch-lag-22f6`", "head": "113de416970cceea8952df55b3fe41cd7a2ca82a", "scope": "Explicit thorough open-PR review", - "outcome": "DO NOT MERGE. CONFLICTING on `globals.css` (semantic vs main motion tokens). P1: `isDashboardModeHref` early-return breaks Answer→Documents cross-mode search (`/documents/search` keeps ClinicalDashboard mounted; stale mode + `run=1` can fire unintended answer generation). P2: dock reveal snap; phone dock flash on mode-home nav; forced scrollTop=0 on every pathname; skeleton min-height overshoot. PR body mismatched.", + "outcome": "DO NOT MERGE. CONFLICTING on `globals.css` (semantic vs main motion tokens). P1: `isDashboardModeHref` early-return breaks Answer\u2192Documents cross-mode search (`/documents/search` keeps ClinicalDashboard mounted; stale mode + `run=1` can fire unintended answer generation). P2: dock reveal snap; phone dock flash on mode-home nav; forced scrollTop=0 on every pathname; skeleton min-height overshoot. PR body mismatched.", "checks": "Static path trace through app-modes/search-route-ownership; merge-tree confirmed globals.css conflict. Hosted CI previously red (Static PR + Production UI). No provider calls." }, { @@ -18922,7 +18921,7 @@ "ref": "PR #1190 / `remediate-dark-mode-audit`", "head": "00eca49b9b0d7e5fbfa5703a15e9e930963984a6", "scope": "Cursor review+Bugbot+prlanded+debug (fresh pass, same HEAD)", - "outcome": "DO NOT MERGE; NOT LANDED (OPEN, mergeable=CONFLICTING/DIRTY, 468 behind / 2 ahead). Reconfirmed P0: conflict resolution deleted `trustGatedAnswerForClinicalNotes` (0 hits on head; main L584/632/659/1075) — Clinical Notes consumes ungated answer. P1: `src/app/api/answer/route.ts:6` imports nonexistent `@/lib/rag` (tsc TS2307; stream correctly uses `@/lib/rag/rag`). P1: merge-tree conflicts on answer/upload/evidence-panels + 10 paths; literal `<<<<<<<` in docs audit plan; migration timestamp collision risk vs main. Intentional dark-mode delta is only commit `363672602` (~10 files). Salvage: `cursor/pr1190-dark-mode-salvage-f453` cherry-picks that commit onto current main, restores unused-manifest-import cleanup, keeps clinical gate. Close #1190 after salvage lands.", + "outcome": "DO NOT MERGE; NOT LANDED (OPEN, mergeable=CONFLICTING/DIRTY, 468 behind / 2 ahead). Reconfirmed P0: conflict resolution deleted `trustGatedAnswerForClinicalNotes` (0 hits on head; main L584/632/659/1075) \u2014 Clinical Notes consumes ungated answer. P1: `src/app/api/answer/route.ts:6` imports nonexistent `@/lib/rag` (tsc TS2307; stream correctly uses `@/lib/rag/rag`). P1: merge-tree conflicts on answer/upload/evidence-panels + 10 paths; literal `<<<<<<<` in docs audit plan; migration timestamp collision risk vs main. Intentional dark-mode delta is only commit `363672602` (~10 files). Salvage: `cursor/pr1190-dark-mode-salvage-f453` cherry-picks that commit onto current main, restores unused-manifest-import cleanup, keeps clinical gate. Close #1190 after salvage lands.", "checks": "Bugbot; `git grep` gate/import/markers; merge-tree; `tsc` TS2307 proof; gh pr view/checks (PR policy fail). Salvage: tsc clean; visual-evidence+overlay tests 13/13; eslint on changed files. No provider/UI matrix." }, { @@ -18938,7 +18937,7 @@ "ref": "PR #1192 / `cursor/fix-mobile-composer-edge-scroll-5b1d`", "head": "0c2b60a646fd6e7a53cf24f778aa59e3d54ba8aa", "scope": "Explicit thorough open-PR review (Antigravity/Cursor queue)", - "outcome": "REQUEST CHANGES. P1: `composerChromeFocused` latches forever when focused dock unmounts (no blur), pinning header scroll-hide permanently. P2: reserve-only hide gate ignores offset → near-bottom clamp (stress: 120/224 frames on answer geometry; 584 clamp-risk across sweep). P2s: submit blur to body; autofocus re-fire; non-answer `focus=1` unfixed; untested collapseKind DOM mapping; PR body copy-paste mismatch.", + "outcome": "REQUEST CHANGES. P1: `composerChromeFocused` latches forever when focused dock unmounts (no blur), pinning header scroll-hide permanently. P2: reserve-only hide gate ignores offset \u2192 near-bottom clamp (stress: 120/224 frames on answer geometry; 584 clamp-risk across sweep). P2s: submit blur to body; autofocus re-fire; non-answer `focus=1` unfixed; untested collapseKind DOM mapping; PR body copy-paste mismatch.", "checks": "Focused Vitest mobile-composer-reserve + use-hide-on-scroll PASS in detached worktree; Node stress of reserve-only gate; static diff review. No provider/UI browser matrix." }, { @@ -18962,7 +18961,7 @@ "ref": "PR #1192 / `cursor/fix-mobile-composer-edge-scroll-5b1d`", "head": "70abb74f7ceee5a50748c4c1e6baa730d7225cf4", "scope": "User-requested /review + Bugbot + /debug + /prlanded on current tip", - "outcome": "APPROVE with notes. Prior P1 focus latch and P2 near-bottom reserve-only clamp confirmed fixed on `5b5ecf405` and retained through main merge. No new P0/P1. Residual P2s: PR body was wrong audit-remediation paste (fixing); non-answer `focus=1` autofocus still broad; earlier document-detail double-header findings unchanged/out of Answer-dock scope. /prlanded: still OPEN, not merged. GitHub CONFLICTING was staleness (merge-tree clean) — merged origin/main.", + "outcome": "APPROVE with notes. Prior P1 focus latch and P2 near-bottom reserve-only clamp confirmed fixed on `5b5ecf405` and retained through main merge. No new P0/P1. Residual P2s: PR body was wrong audit-remediation paste (fixing); non-answer `focus=1` autofocus still broad; earlier document-detail double-header findings unchanged/out of Answer-dock scope. /prlanded: still OPEN, not merged. GitHub CONFLICTING was staleness (merge-tree clean) \u2014 merged origin/main.", "checks": "Bugbot; focused Vitest use-hide-on-scroll + mobile-composer-reserve 28/28 before and after main merge; merge-tree clean; no provider/UI browser matrix this pass." }, { @@ -18970,7 +18969,7 @@ "ref": "PR #1192 / `cursor/fix-mobile-composer-edge-scroll-5b1d`", "head": "73e87da63f5a9eca4162534074755891f952a4ee", "scope": "CORRECTION/supersede: final head after Bugbot fixes + main sync + review ledger push", - "outcome": "APPROVE with notes retained from prior row. Product fixes from `5b5ecf405` still present; branch now 0 behind / mergeable (BLOCKED on CI). Wrong audit-remediation PR body corrected. /prlanded: still OPEN — do not delete branch.", + "outcome": "APPROVE with notes retained from prior row. Product fixes from `5b5ecf405` still present; branch now 0 behind / mergeable (BLOCKED on CI). Wrong audit-remediation PR body corrected. /prlanded: still OPEN \u2014 do not delete branch.", "checks": "Focused Vitest 28/28 on pre-sync tip; merge-tree clean; CI re-queued on tip; no provider-backed checks." }, { @@ -18985,8 +18984,8 @@ "date": "2026-07-25", "ref": "PR #1192 / cursor/fix-mobile-composer-edge-scroll-5b1d @ 2955bc5c", "head": "df72c725", - "scope": "CI / Production UI failure — non-answer phone header keeps the in-flow collapse hide", - "outcome": "FIXED. Single failing Playwright test: `tests/ui-smoke.spec.ts:3780 — non-answer phone header keeps the in-flow collapse hide`. Root cause: RAF debouncing in useHideOnScroll.onScroll coalesces a layout-clamp scroll event with the test's deliberate -24px upward scroll into one RAF evaluation. The hook sees lastMaxOffsetRef stale (pre-collapse visibleMaxOffset V) while the net offset is already V-96 (= newMaxOffset-24). The clamp detection fires (`lastOffset V > newMaxOffset V-72`), incorrectly suppressing the genuine reveal. Fix: added `offset >= maxOffset - revealIntentDistance` guard to the clamp detection in `computeScrollHideUpdate`. Only treat movement as geometry feedback when the net offset is within revealIntentDistance (12 px) of the new bottom edge. Unit test added. PR-required failure is downstream of Production UI only (no independent breakage).", + "scope": "CI / Production UI failure \u2014 non-answer phone header keeps the in-flow collapse hide", + "outcome": "FIXED. Single failing Playwright test: `tests/ui-smoke.spec.ts:3780 \u2014 non-answer phone header keeps the in-flow collapse hide`. Root cause: RAF debouncing in useHideOnScroll.onScroll coalesces a layout-clamp scroll event with the test's deliberate -24px upward scroll into one RAF evaluation. The hook sees lastMaxOffsetRef stale (pre-collapse visibleMaxOffset V) while the net offset is already V-96 (= newMaxOffset-24). The clamp detection fires (`lastOffset V > newMaxOffset V-72`), incorrectly suppressing the genuine reveal. Fix: added `offset >= maxOffset - revealIntentDistance` guard to the clamp detection in `computeScrollHideUpdate`. Only treat movement as geometry feedback when the net offset is within revealIntentDistance (12 px) of the new bottom edge. Unit test added. PR-required failure is downstream of Production UI only (no independent breakage).", "checks": "verify:cheap pass (exit 0); npm run test 20/20 on use-hide-on-scroll.test.ts; Playwright chromium 9/9 scroll-hide smoke tests; Playwright chromium 1/1 target test. No provider-backed checks." }, { @@ -19010,7 +19009,7 @@ "ref": "PR #1195 / `subagent-Asset-Optimization-Implementer-self-b295a5bb`", "head": "8888bf87cbdc5a061bb6d3a2cf46b638af773b1b", "scope": "Cursor review+Bugbot+/debug (supersedes f3d90ecc Bugbot row)", - "outcome": "CONDITIONAL READY after favicon fix. Prior tip DO NOT MERGE (conflict-marker pollution) cleared by Bugbot main-merge; SignedImage transform silent no-op removed; check:assets now compare-only. Remaining P1 found+fixed: SVGO-stripped `icon.svg` failed `brand:check` and removed dark-mode favicon styles — restored `brandIconSvg()` and excluded that file from SVGO gate. Residual P2: orphan AVIF/WebP binaries unused by demo/mockup PNG refs; year-long immutable Cache-Control on unversioned `/icons/*`; `minimumCacheTTL: 86400` still a long lower bound for any optimized next/image. NOT LANDED (OPEN).", + "outcome": "CONDITIONAL READY after favicon fix. Prior tip DO NOT MERGE (conflict-marker pollution) cleared by Bugbot main-merge; SignedImage transform silent no-op removed; check:assets now compare-only. Remaining P1 found+fixed: SVGO-stripped `icon.svg` failed `brand:check` and removed dark-mode favicon styles \u2014 restored `brandIconSvg()` and excluded that file from SVGO gate. Residual P2: orphan AVIF/WebP binaries unused by demo/mockup PNG refs; year-long immutable Cache-Control on unversioned `/icons/*`; `minimumCacheTTL: 86400` still a long lower bound for any optimized next/image. NOT LANDED (OPEN).", "checks": "Bugbot; marker scan clean; brand:check + check:assets PASS; signed-image vitest 7/7; hosted Static/Safety were red on pre-fix tip (brand:check). No provider-backed app checks." }, { @@ -19082,7 +19081,7 @@ "ref": "PR #1196 / codex/fix-p2-audit-20260719", "head": "6d59b038514a92566e986d302b0c75707f13ea30", "scope": "fresh bug/regression review + Bugbot (clinical/RAG/search/auth/privacy)", - "outcome": "Changes requested. Not merge-ready. No P0. P1: search/embedding last-waiter abort leaves dying inflight map entry so healthy same-key retry can coalesce onto aborted work (HTTP 500 / AbortError); also present on main — fixed forward in cursor/pr1196-coalesce-main-4711 / PR #1212. P2: fractional PDF render dimensions rejected by Number.isSafeInteger(pixels), aborting JS fallback — also fixed in #1212. Cleared after inspection: public storage_path omission, document chunk UUID fail-closed schema, factsheet save persistence, therapy capability flags, extractive section-dedup exemption, auth definitive-vs-retryable handling. Blockers: GitHub mergeable CONFLICTING; ~680 commits behind main; ~23 content conflicts including openai.ts, rag.ts, semantic-rerank, supabase client, package.json, therapies-index. PR body RAG impact understates clinical-search / answer-ranking / retrieval-variant edits. prlanded: state OPEN, not merged.", + "outcome": "Changes requested. Not merge-ready. No P0. P1: search/embedding last-waiter abort leaves dying inflight map entry so healthy same-key retry can coalesce onto aborted work (HTTP 500 / AbortError); also present on main \u2014 fixed forward in cursor/pr1196-coalesce-main-4711 / PR #1212. P2: fractional PDF render dimensions rejected by Number.isSafeInteger(pixels), aborting JS fallback \u2014 also fixed in #1212. Cleared after inspection: public storage_path omission, document chunk UUID fail-closed schema, factsheet save persistence, therapy capability flags, extractive section-dedup exemption, auth definitive-vs-retryable handling. Blockers: GitHub mergeable CONFLICTING; ~680 commits behind main; ~23 content conflicts including openai.ts, rag.ts, semantic-rerank, supabase client, package.json, therapies-index. PR body RAG impact understates clinical-search / answer-ranking / retrieval-variant edits. prlanded: state OPEN, not merged.", "checks": "Bugbot + offline static/diff review + pure-JS race/fractional-pixel proofs; focused Vitest on #1212 fix (163 passed). Full PR #1196 Vitest/UI not re-run on stale tip. No OpenAI/Supabase/provider writes. Hosted CI for #1196 only showed PR policy pass + GitGuardian fail; required suite not green on this head." }, { @@ -19217,7 +19216,7 @@ "date": "2026-07-25", "ref": "sitewide-design-review-ledger (PR #1181)", "head": "8284fcd4420", - "scope": "Babysit sweep: design-review ledger — auto-merged after sync", + "scope": "Babysit sweep: design-review ledger \u2014 auto-merged after sync", "outcome": "pr-required", "checks": "merged" }, @@ -19258,7 +19257,7 @@ "ref": "`codex/review-search-bar-behavior-and-establish-rules` (PR #1137)", "head": "b10514374ac7640e5d3395f707c6f958764ae131 + ledger bookkeeping", "scope": "PR babysit: CI fix + Codex threads + drift", - "outcome": "COMPLETED for current head. Restored Tools arm in `showDesktopHomeComposer` and moved `0rem` reserve comment to `mobileComposerReserve` (3d82ead2); replaced unresolvable ledger SHA `bcf4571…` with `6ee0484…`; formatted `docs/search-chrome-behaviour.md`; merged `origin/main` (`0cc0ee2d`). 3/3 Codex review threads resolved via GraphQL (inline replies 403 with this token). Prior CI failures (syntax from misplaced comment) cleared on 3d82ead2; Production UI job cancelled mid-aggregate before this merge — CI re-running after push.", + "outcome": "COMPLETED for current head. Restored Tools arm in `showDesktopHomeComposer` and moved `0rem` reserve comment to `mobileComposerReserve` (3d82ead2); replaced unresolvable ledger SHA `bcf4571\u2026` with `6ee0484\u2026`; formatted `docs/search-chrome-behaviour.md`; merged `origin/main` (`0cc0ee2d`). 3/3 Codex review threads resolved via GraphQL (inline replies 403 with this token). Prior CI failures (syntax from misplaced comment) cleared on 3d82ead2; Production UI job cancelled mid-aggregate before this merge \u2014 CI re-running after push.", "checks": "Local: format:check on touched files; Vitest `ui-overlay-css-contract` + `mobile-composer-reserve` 15/15. Hosted: static/unit/build/advisory green on 3d82ead2. No provider-backed checks run." }, { @@ -19298,7 +19297,7 @@ "ref": "`cursor/docs-reliability-review-c38b`", "head": "af5d44abf031581d256006b51a1be98563d441d5", "scope": "Documentation reliability review vs repo state (setup, env, ops runbooks, testing safety)", - "outcome": "Fixed P1/P2 doc drift: worker region Sydney→Railway Singapore; DR golden gate 23/23→36/36; Railway health `/api/health/ready`; auth checklist aligned to magic-link+OAuth UI; staging identity vars in `.env.example`; provider-approval boundary on testing/readiness docs; mode count 11→13. No P0. Residual: historical `23/23` mentions in point-in-time/archive docs left alone.", + "outcome": "Fixed P1/P2 doc drift: worker region Sydney\u2192Railway Singapore; DR golden gate 23/23\u219236/36; Railway health `/api/health/ready`; auth checklist aligned to magic-link+OAuth UI; staging identity vars in `.env.example`; provider-approval boundary on testing/readiness docs; mode count 11\u219213. No P0. Residual: historical `23/23` mentions in point-in-time/archive docs left alone.", "checks": "`npm run docs:check-links`; `npm run docs:check-index`; `git diff --check`. No provider/OpenAI/Supabase/Railway mutation." }, { @@ -19306,7 +19305,7 @@ "ref": "`cursor/search-performance-review-4ee9` / PR #1134", "head": "76d47871c44c607f942a683351378230173dcbe3", "scope": "Search performance findings remediation (prescribing, differentials, typeahead docs timeout, shared shell, answer rate-limit fallback)", - "outcome": "FIXED. P1 prescribing catalogue now debounces (250 ms), aborts in-flight fetches, and uses `fields=index`. Differentials catalogue + evidence search abort/debounce. Universal documents typeahead timeout 6 s→750 ms (RAG impact: no retrieval behaviour change — typeahead timeout only). Shared `(search-app)` layout keeps GlobalSearchShell mounted across mode homes. Answer rate-limit fails closed only in production; development uses in-memory fallback when durable RPC is unavailable.", + "outcome": "FIXED. P1 prescribing catalogue now debounces (250\u202fms), aborts in-flight fetches, and uses `fields=index`. Differentials catalogue + evidence search abort/debounce. Universal documents typeahead timeout 6\u202fs\u2192750\u202fms (RAG impact: no retrieval behaviour change \u2014 typeahead timeout only). Shared `(search-app)` layout keeps GlobalSearchShell mounted across mode homes. Answer rate-limit fails closed only in production; development uses in-memory fallback when durable RPC is unavailable.", "checks": "Focused Vitest 362 via test:focused; api-rate-limit/search-shell/universal/route/site-map suites green; `npm run ensure` smoke 200 on mode homes; `/api/answer/stream` 200 after fallback. No OpenAI spend beyond local answer stream smoke; no live eval/soak." }, { @@ -19314,7 +19313,7 @@ "ref": "`cursor/sidebar-six-item-land-cfa0` / PR #1174 content-proof `d97c11e6`", "head": "d97c11e6", "scope": "#066 land/proof of six-item sidebar from `cd54e68f` onto main", - "outcome": "PROVE — feature content landed; focused 20/20; verify:pr-local PASS; ensure spot-check PASS; verify:ui 267/267. Not merged to main.", + "outcome": "PROVE \u2014 feature content landed; focused 20/20; verify:pr-local PASS; ensure spot-check PASS; verify:ui 267/267. Not merged to main.", "checks": "vitest favourites+therapy; verify:pr-local; ensure+computerUse spot-check; verify:ui" }, { @@ -19330,8 +19329,8 @@ "ref": "`main`", "head": "6ceaaff50712e10e857bf9a5a7ec88b530bf7b35", "scope": "Search performance across modes (load + typeahead + submit; local ensure)", - "outcome": "CHANGES REQUESTED / findings. No P0. P1: Prescribing `useMedicationCatalog(query)` refetches the full ~2.5–2.9 MB medication catalogue on every keystroke without debounce, abort, or `fields=index` (~25× larger than index). P2: differentials catalogue + evidence `/api/search` lack abort/debounce; universal typeahead `tookMs` dominated by empty live documents domain (~130–340 ms); cross-namespace mode switches remount the search shell; Answer submit returns 503 `rate_limit_unavailable` when durable limiter is down (fail-closed). Mode HTML load medians ~40–75 ms; typeahead wall ~160–180 ms (`ssri`) / ~350–400 ms (`agitation im lorazepam`) + 250 ms client debounce; catalogue submits (differentials) ~45 ms; document `/api/search` demo-degraded ~230–430 ms. Highest residual live risk: cold hybrid RPC tails (docs #25), not re-measured with soak/eval.", - "checks": "`npm run ensure` → http://localhost:4461; `/api/local-project-id` Clinical KB; paced universal typeahead across 13 modes × 2 queries (Server-Timing); `/api/search` + `/api/medications` (+`fields=index`) + differentials APIs + registry payload sizes; NDJSON vs JSON first-byte; browser walkthrough of 13 mode homes; static review of ClinicalDashboard / universal-search / medication+differential hooks. No OpenAI generation, no `eval:retrieval:latency`, no soak, no hosted CI. Environment had Supabase secrets so universal ran live (`publicAccess`); `/api/search` degraded to demo (`supabase_api_key_configuration_unavailable`)." + "outcome": "CHANGES REQUESTED / findings. No P0. P1: Prescribing `useMedicationCatalog(query)` refetches the full ~2.5\u20132.9\u202fMB medication catalogue on every keystroke without debounce, abort, or `fields=index` (~25\u00d7 larger than index). P2: differentials catalogue + evidence `/api/search` lack abort/debounce; universal typeahead `tookMs` dominated by empty live documents domain (~130\u2013340\u202fms); cross-namespace mode switches remount the search shell; Answer submit returns 503 `rate_limit_unavailable` when durable limiter is down (fail-closed). Mode HTML load medians ~40\u201375\u202fms; typeahead wall ~160\u2013180\u202fms (`ssri`) / ~350\u2013400\u202fms (`agitation im lorazepam`) + 250\u202fms client debounce; catalogue submits (differentials) ~45\u202fms; document `/api/search` demo-degraded ~230\u2013430\u202fms. Highest residual live risk: cold hybrid RPC tails (docs #25), not re-measured with soak/eval.", + "checks": "`npm run ensure` \u2192 http://localhost:4461; `/api/local-project-id` Clinical KB; paced universal typeahead across 13 modes \u00d7 2 queries (Server-Timing); `/api/search` + `/api/medications` (+`fields=index`) + differentials APIs + registry payload sizes; NDJSON vs JSON first-byte; browser walkthrough of 13 mode homes; static review of ClinicalDashboard / universal-search / medication+differential hooks. No OpenAI generation, no `eval:retrieval:latency`, no soak, no hosted CI. Environment had Supabase secrets so universal ran live (`publicAccess`); `/api/search` degraded to demo (`supabase_api_key_configuration_unavailable`)." }, { "date": "2026-07-24", @@ -19346,15 +19345,15 @@ "ref": "`main` / `01c209576207a3c279972697718d06c819fff000`", "head": "01c209576207a3c279972697718d06c819fff000", "scope": "Sitewide design/UX/interactive review (production pages, breakpoints, a11y)", - "outcome": "CHANGES REQUESTED / findings. No P0. Two confirmed P2 UX defects: (1) mobile presentation Compare tab is a self-link that drops `ids`/`q` and resets selection (1→default 4) + clears Query chip; (2) document “Browse by tag” / `searchByTag` navigates to `/?mode=documents&q=…` without `run=1`, so results do not run. P3: comparison disabled dropdown/filter controls lack `aria-describedby` placeholder contract; bare `/documents` 404 (no inbound links; `/documents/search` is canonical); phone mode-switcher truncates “Differenti…”. Deduped: `/tools` vs `/?mode=tools` remains #007; coming-soon density/favourites/forms remain #010. Phone docks flush `bottom:0` on sampled result routes; no document horizontal overflow at 390/768/1280 across 30 routes.", - "checks": "`npm run workflow:design-sweep -- --write-evidence`; `npm run ensure` → http://localhost:4461 identity Clinical KB; Playwright HTTP+overflow matrix 30/30 no overflow; live Compare/tag proofs + phone route matrix; `npm run test:e2e:accessibility` 12/12; screenshots under `/opt/cursor/artifacts/screenshots/design-review-2026-07-24/`. No OpenAI/Supabase/GitHub/hosted CI/provider mutations. Added project subagent `.cursor/agents/design-review.md`." + "outcome": "CHANGES REQUESTED / findings. No P0. Two confirmed P2 UX defects: (1) mobile presentation Compare tab is a self-link that drops `ids`/`q` and resets selection (1\u2192default 4) + clears Query chip; (2) document \u201cBrowse by tag\u201d / `searchByTag` navigates to `/?mode=documents&q=\u2026` without `run=1`, so results do not run. P3: comparison disabled dropdown/filter controls lack `aria-describedby` placeholder contract; bare `/documents` 404 (no inbound links; `/documents/search` is canonical); phone mode-switcher truncates \u201cDifferenti\u2026\u201d. Deduped: `/tools` vs `/?mode=tools` remains #007; coming-soon density/favourites/forms remain #010. Phone docks flush `bottom:0` on sampled result routes; no document horizontal overflow at 390/768/1280 across 30 routes.", + "checks": "`npm run workflow:design-sweep -- --write-evidence`; `npm run ensure` \u2192 http://localhost:4461 identity Clinical KB; Playwright HTTP+overflow matrix 30/30 no overflow; live Compare/tag proofs + phone route matrix; `npm run test:e2e:accessibility` 12/12; screenshots under `/opt/cursor/artifacts/screenshots/design-review-2026-07-24/`. No OpenAI/Supabase/GitHub/hosted CI/provider mutations. Added project subagent `.cursor/agents/design-review.md`." }, { "date": "2026-07-24", "ref": "`main` / `037b4808100946f96aee28b8ff51939ae2986851`", "head": "037b4808100946f96aee28b8ff51939ae2986851", "scope": "frontend-ui review: clinical-dashboard sidebar streamlining, global-search-shell, mobile-composer-reserve, globals.css forced-colors/reduced-motion, evidence-panels aria, answer-result-surface, visual-evidence-tabs DOM tests", - "outcome": "APPROVE with notes (P2 closed on `cursor/frontend-ui-review-docs-e8d9`). No P0/P1. One P2 was docs-only: `docs/codebase-index.md` mode-home list omitted `/therapy-compass`, `/dsm`, `/specifiers`, and `/factsheets` while `isStandaloneModeHome` already handles them — fixed in the follow-up docs PR. What holds: sidebar streamlining (`primarySidebarToolIds` Set) is correct; global reduced-motion CSS covers `animate-spin`; forced-colors token remap is comprehensive; mobile-composer-reserve and overlay CSS contracts intact; tab/tabpanel ARIA associations pass in jsdom; icon-only collapsed rail links carry `aria-label`+`title`; lucide-react defaults SVG `aria-hidden=\"true\"`.", + "outcome": "APPROVE with notes (P2 closed on `cursor/frontend-ui-review-docs-e8d9`). No P0/P1. One P2 was docs-only: `docs/codebase-index.md` mode-home list omitted `/therapy-compass`, `/dsm`, `/specifiers`, and `/factsheets` while `isStandaloneModeHome` already handles them \u2014 fixed in the follow-up docs PR. What holds: sidebar streamlining (`primarySidebarToolIds` Set) is correct; global reduced-motion CSS covers `animate-spin`; forced-colors token remap is comprehensive; mobile-composer-reserve and overlay CSS contracts intact; tab/tabpanel ARIA associations pass in jsdom; icon-only collapsed rail links carry `aria-label`+`title`; lucide-react defaults SVG `aria-hidden=\"true\"`.", "checks": "Full unit suite 3261/3264 passed (3 pre-existing skips); typecheck clean; lint clean; static read of globals.css forced-colors/reduced-motion, overlay contracts, aria patterns, and mobile-composer-reserve. Docs mode-home list aligned to `isStandaloneModeHome`. No live Supabase/OpenAI/Railway mutation." }, { @@ -19362,7 +19361,7 @@ "ref": "`main` / PR #1122 tip `037b4808100946f96aee28b8ff51939ae2986851`", "head": "037b4808100946f96aee28b8ff51939ae2986851", "scope": "Code-quality review of tip commit (streamlined sidebar tool list)", - "outcome": "No P0-P1. Two P2 maintainability findings: (1) dual catalogue — `sidebarToolItems` still defines specialist tools that `primarySidebarToolIds` always filters out, leaving unused Lucide imports and a footgun where new catalogue rows do not appear unless also added to the Set; (2) favourites-auth-gate asserts primary IDs by regex-parsing the Set initializer source, which couples the suite to TypeScript formatting. Highest residual risk is quiet nav drift if specialists are re-added only to `sidebarToolItems`. #066 in outstanding-issues still describes this sidebar land as open despite the tip merge.", + "outcome": "No P0-P1. Two P2 maintainability findings: (1) dual catalogue \u2014 `sidebarToolItems` still defines specialist tools that `primarySidebarToolIds` always filters out, leaving unused Lucide imports and a footgun where new catalogue rows do not appear unless also added to the Set; (2) favourites-auth-gate asserts primary IDs by regex-parsing the Set initializer source, which couples the suite to TypeScript formatting. Highest residual risk is quiet nav drift if specialists are re-added only to `sidebarToolItems`. #066 in outstanding-issues still describes this sidebar land as open despite the tip merge.", "checks": "Static diff inspection of `ClinicalSidebar.tsx`, `tests/favourites-auth-gate.test.ts`, `tests/ui-smoke.spec.ts`; no lint/test/provider runs (pure review)." }, { @@ -19378,8 +19377,8 @@ "ref": "`origin/main`", "head": "6ceaaff50712e10e857bf9a5a7ec88b530bf7b35", "scope": "sitewide design/UX review (production pages)", - "outcome": "FINDINGS CAPTURED. No P0. Confirmed defects later archived as `#070`–`#074` after ID collision with main `#068`/`#069`. Updated `#010` for Compact/Detailed selected-but-disabled look. Deduped against `#007`/`#016`/`#038`–`#041`/`#063`–`#066`. Residual: large mobile PWA install sheet density; compare URL-state sync; axe coverage beyond home (`#040`). No product code fixes in this pass.", - "checks": "Offline: design-system-contract, type-scale, icon-scale, brand:check, design-sweep evidence. Live: `npm run ensure` → `http://localhost:4461` identity OK; mode-home/detail HTTP 200 + no document overflow at 390/1280; presentation href + forced Overview navigation proof; Tools Sort/More DOM proof; `test:e2e:accessibility` 12/12. Screenshots under `/opt/cursor/artifacts/screenshots/`. No OpenAI/Supabase/GitHub/hosted CI/provider calls." + "outcome": "FINDINGS CAPTURED. No P0. Confirmed defects later archived as `#070`\u2013`#074` after ID collision with main `#068`/`#069`. Updated `#010` for Compact/Detailed selected-but-disabled look. Deduped against `#007`/`#016`/`#038`\u2013`#041`/`#063`\u2013`#066`. Residual: large mobile PWA install sheet density; compare URL-state sync; axe coverage beyond home (`#040`). No product code fixes in this pass.", + "checks": "Offline: design-system-contract, type-scale, icon-scale, brand:check, design-sweep evidence. Live: `npm run ensure` \u2192 `http://localhost:4461` identity OK; mode-home/detail HTTP 200 + no document overflow at 390/1280; presentation href + forced Overview navigation proof; Tools Sort/More DOM proof; `test:e2e:accessibility` 12/12. Screenshots under `/opt/cursor/artifacts/screenshots/`. No OpenAI/Supabase/GitHub/hosted CI/provider calls." }, { "date": "2026-07-24", @@ -19402,7 +19401,7 @@ "ref": "audit-remediation (PR #1153)", "head": "c4adfe9e27e43edfdfea78f296257330cda39aca", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: behind/conflicting + PR policy FAIL (missing Clinical Governance Preflight + RAG impact). after: merged origin/main cleanly; PR policy still FAIL — body edit forbidden this sweep (needs human to add Clinical Governance Preflight + RAG impact line); no unresolved review threads worked", + "outcome": "before: behind/conflicting + PR policy FAIL (missing Clinical Governance Preflight + RAG impact). after: merged origin/main cleanly; PR policy still FAIL \u2014 body edit forbidden this sweep (needs human to add Clinical Governance Preflight + RAG impact line); no unresolved review threads worked", "checks": "merge only; no provider-backed checks run" }, { @@ -19482,7 +19481,7 @@ "ref": "codex/audit-remediation-final (PR #1158)", "head": "78fab6be0c43cf5e92361315399d393ee7742f2e", "scope": "Run PR re-sync sweep", - "outcome": "Before: CONFLICTING. After: merged origin/main clean (no RAG conflict markers). NOTE: PR still intentionally adds deterministic broad_summary queryClass shortcut in src/lib/rag/rag.ts (+17) — RAG impact behaviour change, not dropped during merge.", + "outcome": "Before: CONFLICTING. After: merged origin/main clean (no RAG conflict markers). NOTE: PR still intentionally adds deterministic broad_summary queryClass shortcut in src/lib/rag/rag.ts (+17) \u2014 RAG impact behaviour change, not dropped during merge.", "checks": "merge origin/main and/or conflict re-check only; no provider-backed checks run" }, { @@ -19658,7 +19657,7 @@ "ref": "cursor/pr-babysit-bugbot-agents-6c52 (PR #1167)", "head": "6ec7a852", "scope": "Babysit sweep: CI fix + Codex/CodeRabbit threads", - "outcome": "Before: mergeable, PR required green, 8 unresolved agent-guidance threads. After: fixed pr-babysit/pr-bugbot agents (fetch origin/main, no Run PR live-gate auth, pin target head SHA, exact bot identity, ledger-after-every-sweep). Thread reply/resolve 403 on this token — fixes pushed.", + "outcome": "Before: mergeable, PR required green, 8 unresolved agent-guidance threads. After: fixed pr-babysit/pr-bugbot agents (fetch origin/main, no Run PR live-gate auth, pin target head SHA, exact bot identity, ledger-after-every-sweep). Thread reply/resolve 403 on this token \u2014 fixes pushed.", "checks": "typecheck on agent files; no provider-backed checks run" }, { @@ -19730,7 +19729,7 @@ "ref": "cursor/search-correctness-030-075-6273 (PR #1177)", "head": "54ab9f8498751ef7e96815dd2496b8137f29dad7", "scope": "Review + follow-up hardening of #030/#075 search-correctness fixes", - "outcome": "Findings fixed: (P2) one combo-titled source could still make multi-slot allHit true via substring alias hits — `expectedFileCoverage` now assigns each retrieved top-file to at most one expected slot; (P2) label pagination could loop forever on a stuck full-page API — fail-closed page budget added; (P2 process) stale `PR_POLICY_BODY.md` from search-performance leftover was overwriting this PR body via Sync PR policy body — corrected then deleted. No remaining high-confidence P0–P1 in product scope. Residual: human approving review; Unit coverage CI still finishing on later heads. RAG impact: no retrieval behaviour change — eval matching / label pagination only.", + "outcome": "Findings fixed: (P2) one combo-titled source could still make multi-slot allHit true via substring alias hits \u2014 `expectedFileCoverage` now assigns each retrieved top-file to at most one expected slot; (P2) label pagination could loop forever on a stuck full-page API \u2014 fail-closed page budget added; (P2 process) stale `PR_POLICY_BODY.md` from search-performance leftover was overwriting this PR body via Sync PR policy body \u2014 corrected then deleted. No remaining high-confidence P0\u2013P1 in product scope. Residual: human approving review; Unit coverage CI still finishing on later heads. RAG impact: no retrieval behaviour change \u2014 eval matching / label pagination only.", "checks": "Focused Vitest 32/32; `verify:cheap` green; `verify:pr-local` green (lint/typecheck/3326 unit/build/client-bundle/offline RAG fixtures 36/36). No OpenAI/live Supabase/provider-backed canary." }, { @@ -19770,7 +19769,7 @@ "ref": "cursor/search-interactive-perf-af54 (PR #1138 follow-up)", "head": "7e2ccee0", "scope": "Bugfix pass on search interactive performance diff", - "outcome": "Fixed P1 auth-stale differential matches; P2 progressive-reveal hiding selected card; P2 deferred empty/full-catalogue flash on services/forms/formulation/therapy-compass; Prettier CI failure on universal-search test. No remaining high-confidence P0–P2 in scoped diff. Residual: differential debounce skeleton flicker; RelatedDocumentsPanel memo limited by unstable callbacks.", + "outcome": "Fixed P1 auth-stale differential matches; P2 progressive-reveal hiding selected card; P2 deferred empty/full-catalogue flash on services/forms/formulation/therapy-compass; Prettier CI failure on universal-search test. No remaining high-confidence P0\u2013P2 in scoped diff. Residual: differential debounce skeleton flicker; RelatedDocumentsPanel memo limited by unstable callbacks.", "checks": "Focused Vitest 11/11; typecheck; format:check; maintainability budgets. No provider calls." }, { @@ -19786,7 +19785,7 @@ "ref": "cursor/search-interactive-perf-af54 (PR #1138)", "head": "46597a9b", "scope": "Explicit performance + frontend-ui review of search/interactive surfaces; low-risk client deferral/cache/abort/progressive-reveal pass", - "outcome": "Prior document/universal search latency work retained (NDJSON stream, LRU, lazy PDF, content-first detail). New work: differential debounce+abort+LRU; useDeferredValue on catalogue ranking; document results Show more window; RelatedDocumentsPanel memo; universal LRU 100+TTL; deferred registry search extracted from ClinicalDashboard. No RAG/retrieval/ranking edits. No high-confidence P0–P2 defect found in the shipped scope; residual risk = deferred paint lag on large catalogues and progressive reveal missing deep cards until Show more.", + "outcome": "Prior document/universal search latency work retained (NDJSON stream, LRU, lazy PDF, content-first detail). New work: differential debounce+abort+LRU; useDeferredValue on catalogue ranking; document results Show more window; RelatedDocumentsPanel memo; universal LRU 100+TTL; deferred registry search extracted from ClinicalDashboard. No RAG/retrieval/ranking edits. No high-confidence P0\u2013P2 defect found in the shipped scope; residual risk = deferred paint lag on large catalogues and progressive reveal missing deep cards until Show more.", "checks": "Focused Vitest 10/10 (differential + universal + performance boundaries); verify:cheap exit 0 (3262 tests); typecheck clean; verify:ui exit 0 (Chromium). No provider calls." }, { @@ -19794,7 +19793,7 @@ "ref": "cursor/search-interactive-perf-af54 (PR #1138)", "head": "ff4b293d95f922e70ebf5ee9b0c156c41a8bff3b", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Before: CONFLICTING, CI green, 0 threads. RAG impact: no retrieval behaviour change — PR is client deferred-search/UI only (no src/lib/rag/**). After: merged origin/main; conflict resolved in src/components/ui/sheet.tsx by keeping main restoreTimersRef/unmountingRef focus-restore fix; pushed ff4b293d9. Threads: none.", + "outcome": "Before: CONFLICTING, CI green, 0 threads. RAG impact: no retrieval behaviour change \u2014 PR is client deferred-search/UI only (no src/lib/rag/**). After: merged origin/main; conflict resolved in src/components/ui/sheet.tsx by keeping main restoreTimersRef/unmountingRef focus-restore fix; pushed ff4b293d9. Threads: none.", "checks": "merge origin/main only; no provider-backed checks run" }, { @@ -19826,7 +19825,7 @@ "ref": "execute-audit-code-remediation (PR #1162)", "head": "632e84c9436f1f28be9d7aaadbbe942f72618199", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: CONFLICTING + PR policy FAIL + unresolved Codex P1 (conflict markers in answer/route.ts). after: conflict markers removed and pushed (80212dd91, 632e84c94); merge origin/main aborted (non-trivial conflicts: privacy/page.tsx, answer-render-policy.ts, source-authority-metadata.ts, upload/route.ts, supabase/drift-manifest.json, settings-dialog, validation/answer-request, plus UI/docs/tests); PR policy still FAIL (Clinical Governance Preflight missing — body edit forbidden this sweep); thread reply/resolve needs parent (comment 3644028277 / thread PRRT_kwDOSh5Fis6Tfkev) — ManagePullRequest/GitHub write MCP unavailable", + "outcome": "before: CONFLICTING + PR policy FAIL + unresolved Codex P1 (conflict markers in answer/route.ts). after: conflict markers removed and pushed (80212dd91, 632e84c94); merge origin/main aborted (non-trivial conflicts: privacy/page.tsx, answer-render-policy.ts, source-authority-metadata.ts, upload/route.ts, supabase/drift-manifest.json, settings-dialog, validation/answer-request, plus UI/docs/tests); PR policy still FAIL (Clinical Governance Preflight missing \u2014 body edit forbidden this sweep); thread reply/resolve needs parent (comment 3644028277 / thread PRRT_kwDOSh5Fis6Tfkev) \u2014 ManagePullRequest/GitHub write MCP unavailable", "checks": "typecheck:internal pass; vitest clinical-dashboard-merge-artifacts + visual-evidence-tabs pass (9); no provider-backed checks run" }, { @@ -19850,7 +19849,7 @@ "ref": "execute-audit-code-remediation (PR #1162)", "head": "b4675d7b", "scope": "Babysit sweep: drift skipped", - "outcome": "Before: CONFLICTING, PR policy FAIL. Merge origin/main aborted: 20+ conflict files across clinical/auth/API surfaces — needs human resolution.", + "outcome": "Before: CONFLICTING, PR policy FAIL. Merge origin/main aborted: 20+ conflict files across clinical/auth/API surfaces \u2014 needs human resolution.", "checks": "merge --abort; no provider-backed checks run" }, { @@ -19986,7 +19985,7 @@ "ref": "PR #1125 / `codex/answer-relevance-fail-closed`", "head": "8d9fb2408f13e305138749655214baa0020fcfd4", "scope": "Follow-up: clear comparison/`documentBreakdown` in untrusted clinical notes", - "outcome": "APPROVE for the scoped P2. `trustGatedAnswerForClinicalNotes` now clears `documentBreakdown`, `comparisonMatrix`, and `comparisonEvaluationState` when relevance is not source-backed, so Clinical Notes → ClinicalOutputPanel cannot rebuild comparison-detail tables from raw `best_quote` values. Prior visual/section/quote gates remain. Residual risk is still deliberate low-trust rendering for legacy payloads without `isSourceBacked: true`.", + "outcome": "APPROVE for the scoped P2. `trustGatedAnswerForClinicalNotes` now clears `documentBreakdown`, `comparisonMatrix`, and `comparisonEvaluationState` when relevance is not source-backed, so Clinical Notes \u2192 ClinicalOutputPanel cannot rebuild comparison-detail tables from raw `best_quote` values. Prior visual/section/quote gates remain. Residual risk is still deliberate low-trust rendering for legacy payloads without `isSourceBacked: true`.", "checks": "Focused jsdom/policy regressions: `tests/visual-evidence-tabs.dom.test.tsx` 5/5 after hardening the comparison case (caption + matrix values absent). Thread disposition posted and resolved. No live RAG/OpenAI/Supabase mutation." }, { @@ -20010,7 +20009,7 @@ "ref": "PR #1135 / `cursor/sitewide-design-ux-review-6176`", "head": "merge origin/main @ 3d6954a3", "scope": "babysit: re-merge main after #1133; renumber UX archive IDs", - "outcome": "CONFLICTING after `main` advanced with database-interface audit. Kept product UX fixes; rebuilt `docs/outstanding-issues.md` from `origin/main` and archived sitewide UX defects as collision-free `#070`–`#074` (provisional PR IDs `#068`–`#072` collided with main `#068` drift-manifest / `#069` table-facts profile). Native-`disabled` CodeRabbit ask remains declined (focusable coming-soon contract).", + "outcome": "CONFLICTING after `main` advanced with database-interface audit. Kept product UX fixes; rebuilt `docs/outstanding-issues.md` from `origin/main` and archived sitewide UX defects as collision-free `#070`\u2013`#074` (provisional PR IDs `#068`\u2013`#072` collided with main `#068` drift-manifest / `#069` table-facts profile). Native-`disabled` CodeRabbit ask remains declined (focusable coming-soon contract).", "checks": "Local merge conflict resolution only; hosted CI pending on merge commit. No provider-backed gates." }, { @@ -20066,7 +20065,7 @@ "ref": "PR #1175 / `cursor/ledger-009-010-032-041-063-519b`", "head": "f3986abc39468e077643611ec2d95e374c2e901f", "scope": "PR review + CI fix (ledger docs #009/#010/#032/#041/#063)", - "outcome": "FINDINGS FIXED. P1: Static PR checks failed on Prettier (5 docs). P1: leftover `PR_POLICY_BODY.md` from merged #1134 caused Sync PR policy body to overwrite this docs PR description with search-performance text — deleted the stale template. No P0. Product scope remains docs-only; gated brief follow-ups (wire coming-soon, Current Clinical Work storage, Factsheets second mode, governance ranking) correctly not implemented. Residual: human approving review once CI green.", + "outcome": "FINDINGS FIXED. P1: Static PR checks failed on Prettier (5 docs). P1: leftover `PR_POLICY_BODY.md` from merged #1134 caused Sync PR policy body to overwrite this docs PR description with search-performance text \u2014 deleted the stale template. No P0. Product scope remains docs-only; gated brief follow-ups (wire coming-soon, Current Clinical Work storage, Factsheets second mode, governance ranking) correctly not implemented. Residual: human approving review once CI green.", "checks": "Local: prettier --check on touched docs; ledger open/resolved/queue integrity for five IDs; no client fetch(`/api/jobs`); `verify:cheap` earlier on tip 95d68c6b. No OpenAI/Supabase writes." }, { @@ -20135,10 +20134,10 @@ }, { "date": "2026-07-24", - "ref": "repo-auditor (detached HEAD 037b4808 — explicit full-repo structural audit)", + "ref": "repo-auditor (detached HEAD 037b4808 \u2014 explicit full-repo structural audit)", "head": "037b4808100946f96aee28b8ff51939ae2986851", - "scope": "Full-repo structural audit: broken imports, dead files, consolidation. Scope: src/, scripts/, worker/, tests/. Pure triage — no files mutated.", - "outcome": "P0/P1: none. P2: confirmed dead file src/components/clinical-dashboard/prior-answer-turn-surface.tsx (115 lines, zero importers; superseded by answer-thread-turn.tsx per its 'Extracted from ClinicalDashboard.tsx maturity X3' comment; old file exports PriorAnswerTurn type + PriorAnswerTurnSurface component — both replaced). P3: three duplicate package.json script pairs (test:e2e = test:e2e:all; promote:public-documents = promote:public-documents:batch; postinstall = hooks:install — last pair intentional lifecycle). Unused public exports: authorization.ts (administratorRoleClaim/Value internal-only), api-client-error.ts (ApiClientError — only parseApiErrorResponse imported), rag/rag.ts (answerQuestion — superseded by answerQuestionWithScope), supabase/project.ts (isExpectedSupabaseProjectConfig + 2 types). RAG surface note only (do not touch): rag-extractive-first.ts exports hasValidatedRoutineExtractiveRecovery/hasValidatedGenericLaiManagementExtractiveAnswer with no external consumers. Knip false positives: taskkill (win32-gated), railway (opt-in --railway flag). No broken imports (typecheck + lint both exit 0, zero relative ../ imports in src/).", + "scope": "Full-repo structural audit: broken imports, dead files, consolidation. Scope: src/, scripts/, worker/, tests/. Pure triage \u2014 no files mutated.", + "outcome": "P0/P1: none. P2: confirmed dead file src/components/clinical-dashboard/prior-answer-turn-surface.tsx (115 lines, zero importers; superseded by answer-thread-turn.tsx per its 'Extracted from ClinicalDashboard.tsx maturity X3' comment; old file exports PriorAnswerTurn type + PriorAnswerTurnSurface component \u2014 both replaced). P3: three duplicate package.json script pairs (test:e2e = test:e2e:all; promote:public-documents = promote:public-documents:batch; postinstall = hooks:install \u2014 last pair intentional lifecycle). Unused public exports: authorization.ts (administratorRoleClaim/Value internal-only), api-client-error.ts (ApiClientError \u2014 only parseApiErrorResponse imported), rag/rag.ts (answerQuestion \u2014 superseded by answerQuestionWithScope), supabase/project.ts (isExpectedSupabaseProjectConfig + 2 types). RAG surface note only (do not touch): rag-extractive-first.ts exports hasValidatedRoutineExtractiveRecovery/hasValidatedGenericLaiManagementExtractiveAnswer with no external consumers. Knip false positives: taskkill (win32-gated), railway (opt-in --railway flag). No broken imports (typecheck + lint both exit 0, zero relative ../ imports in src/).", "checks": "npm run typecheck (exit 0); npm run lint (exit 0); npm run check:knip (exit 0); knip --reporter json full export/file/type analysis; rg import-graph probes across all source trees" }, { @@ -20282,31 +20281,31 @@ "ref": "PR #1087 / `codex/reconcile-product-truth`", "head": "edbc2260fef59ca2fa7c6973dffb85e32354bce1 (merged as 05dc52fd8408a65117e22a6236e43252203bea92)", "scope": "Product-truth copy, account persistence and unavailable-SSO presentation", - "outcome": "MERGED. Cross-device claims now match favourites/preferences persistence; recent searches are identified as browser-session data; the contradictory “never shared” statement is removed. All unavailable setup providers and Apple elsewhere use the connected accessible “coming soon” placeholder pattern. The single review finding was fixed, replied to and resolved.", + "outcome": "MERGED. Cross-device claims now match favourites/preferences persistence; recent searches are identified as browser-session data; the contradictory \u201cnever shared\u201d statement is removed. All unavailable setup providers and Apple elsewhere use the connected accessible \u201ccoming soon\u201d placeholder pattern. The single review finding was fixed, replied to and resolved.", "checks": "Red DOM proof; focused 19/19; `verify:cheap` 3,220 passed / 1 skipped; `verify:ui` 265/265; PR-local build/secret scan/offline RAG; final hosted required, Production UI, policy and security checks green. No provider calls or RAG spend." }, { "date": "2026-07-21", - "ref": "claude/clinical-kb-pwa-review-asi3wb (E-4 pair verdict — no code change; #1039 merged as 9b655fa)", + "ref": "claude/clinical-kb-pwa-review-asi3wb (E-4 pair verdict \u2014 no code change; #1039 merged as 9b655fa)", "head": "canary run 29800029819 (#60, main 9b655fa = E-3b+PR-B+PR-C)", "scope": "(recorded with Outcome)", - "outcome": "PHASE E-3 WAVE CLOSED — E-4 VERDICT: ADOPT (no revert). 44-case: the ONLY blocking red is the KNOWN persisting neuroleptic citation case (0.0227, identical #57 signature: generation quality-failed → extractive fallback 1 citation — the pre-declared Option A carve-out, retrieval-side, untouched by answer waves); route_ceiling_failures 0 CONFIRMED ON MAIN (E-3b: agitation 23.1s < 25s after 20.3s provider timeout; clozapine 14.5s with exactly one retrieval-exhausted audit cell); grounded 1.0 / unsupported_correct 1.0 / numeric 0 / governance-danger 0 all held; expected_source_hit 0.6136→0.6364 (#1020 widen); generation attempts 19→9 across 44 cases (10+ cases short-circuit via validated_routine_extractive_first at 2-6s, zero generation spend — the absolute wasted-generation seconds collapse; residual 6 discarded attempts are the named E-3d H2 strong/comparison slice). Targeting vs #58 baseline: rate 0.5909→0.6667, dose 1/5→2/4 (sertraline + quetiapine still miss), document_lookup 5/5→6/6, contraindication 2/2, red_result 2/2, pathway 1/2; readability/artifact_leaks 1.0. NOT met: monitoring_schedule flat 1/5 — per-miss lens shows answers of 73-232 chars with NO schedule token available to promote (olanzapine-lai 79ch, metabolic 73ch = single-fact extractive answers; the PR-C promotion is a no-op when no figure-bearing fact is extracted) → root is fact-extraction/retrieval depth on monitoring shapes, queued as the Option-A-wave companion diagnosis (dump artifact 8483731630, 30d retention). WATCH escalated: relevance 0.6 (#58) → 0.5667 (#59) → 0.5333 (#60) — two single-case steps coinciding with more terse extractive answers; fail_closed 0.9 = exactly the #58 main baseline (#59's 0.9333 was the outlier), safety texture flat. Adoption per plan criteria: targeting ≥ baseline ✓, grounded/refusal 1.0 ✓, golden 36/36 ✓ (in-run), ceilings 0 ✓, citation red = carved known case ✓. CodeRabbit post-review follow-up landed pre-merge (02b5c78): interval-regex full-match reorder (atom path proven to intercept the claimed exploit; reorder = drift hardening), clinicalValueAtomKey exported (mirror deleted), guard tests made honestly discriminating + genuine zero-atom \"annually\" coverage both directions. Instrument note: cost rates live on the targeting step env but eval:quality still reports cost n/a (estimator not consuming them in the 44-case path) — minor tooling residual. Spend +~$2-4 → Phase E total ~$8-16 of ≤$20.", - "checks": "Evidence: run #60 job log read in full (Threshold Status: citation-only; Answer Metrics + 44-row diagnostics; targeting metric_rates + 7-miss list); artifact eval-canary-output 8483731630 sha256 d5c7006e… (download blocked in-session — GitHub App scope; log tee carried the targeting output)" + "outcome": "PHASE E-3 WAVE CLOSED \u2014 E-4 VERDICT: ADOPT (no revert). 44-case: the ONLY blocking red is the KNOWN persisting neuroleptic citation case (0.0227, identical #57 signature: generation quality-failed \u2192 extractive fallback 1 citation \u2014 the pre-declared Option A carve-out, retrieval-side, untouched by answer waves); route_ceiling_failures 0 CONFIRMED ON MAIN (E-3b: agitation 23.1s < 25s after 20.3s provider timeout; clozapine 14.5s with exactly one retrieval-exhausted audit cell); grounded 1.0 / unsupported_correct 1.0 / numeric 0 / governance-danger 0 all held; expected_source_hit 0.6136\u21920.6364 (#1020 widen); generation attempts 19\u21929 across 44 cases (10+ cases short-circuit via validated_routine_extractive_first at 2-6s, zero generation spend \u2014 the absolute wasted-generation seconds collapse; residual 6 discarded attempts are the named E-3d H2 strong/comparison slice). Targeting vs #58 baseline: rate 0.5909\u21920.6667, dose 1/5\u21922/4 (sertraline + quetiapine still miss), document_lookup 5/5\u21926/6, contraindication 2/2, red_result 2/2, pathway 1/2; readability/artifact_leaks 1.0. NOT met: monitoring_schedule flat 1/5 \u2014 per-miss lens shows answers of 73-232 chars with NO schedule token available to promote (olanzapine-lai 79ch, metabolic 73ch = single-fact extractive answers; the PR-C promotion is a no-op when no figure-bearing fact is extracted) \u2192 root is fact-extraction/retrieval depth on monitoring shapes, queued as the Option-A-wave companion diagnosis (dump artifact 8483731630, 30d retention). WATCH escalated: relevance 0.6 (#58) \u2192 0.5667 (#59) \u2192 0.5333 (#60) \u2014 two single-case steps coinciding with more terse extractive answers; fail_closed 0.9 = exactly the #58 main baseline (#59's 0.9333 was the outlier), safety texture flat. Adoption per plan criteria: targeting \u2265 baseline \u2713, grounded/refusal 1.0 \u2713, golden 36/36 \u2713 (in-run), ceilings 0 \u2713, citation red = carved known case \u2713. CodeRabbit post-review follow-up landed pre-merge (02b5c78): interval-regex full-match reorder (atom path proven to intercept the claimed exploit; reorder = drift hardening), clinicalValueAtomKey exported (mirror deleted), guard tests made honestly discriminating + genuine zero-atom \"annually\" coverage both directions. Instrument note: cost rates live on the targeting step env but eval:quality still reports cost n/a (estimator not consuming them in the 44-case path) \u2014 minor tooling residual. Spend +~$2-4 \u2192 Phase E total ~$8-16 of \u2264$20.", + "checks": "Evidence: run #60 job log read in full (Threshold Status: citation-only; Answer Metrics + 44-row diagnostics; targeting metric_rates + 7-miss list); artifact eval-canary-output 8483731630 sha256 d5c7006e\u2026 (download blocked in-session \u2014 GitHub App scope; log tee carried the targeting output)" }, { "date": "2026-07-21", "ref": "claude/clinical-kb-pwa-review-asi3wb (Option A rescue review)", "head": "0abf3c9", "scope": "(recorded with Outcome)", - "outcome": "clinical-governance-reviewer on the S3 escalation rescue: APPROVE-WITH-NITS, no P0/P1. P2 = the mandated live canary pair itself (process gate, declared in the PR body; offline-green + review-approved proven insufficient for this surface 2026-07-20). P3s: multi-drug escalation-query recall edge (titled drug + untitled drug — fast-path return can skip the vector leg; recall limitation, not misattribution, mirrors the pre-existing allowlisted-class tradeoff); reviewer probe files must stay uncommitted (relocated to scratchpad). All six clinical concerns verified safe: wrong-document impossible (alias phrases must appear in the query; per-document alias groups, no cross-drug conflation), conservative availability (S3 purely additive via keyed-union merge; sibling retention test-pinned), live expansion acceptable (title-named correct-entity SOP in every firing shape), fail-closed double layer (adversarial short-circuit precedes the predicate; injection-forge case intent=protocol cannot fire — executed), governance metadata unbypassed (same attachDocumentRankingMetadata + status=indexed + access-scope filters), no PHI/provider/schema surface.", + "outcome": "clinical-governance-reviewer on the S3 escalation rescue: APPROVE-WITH-NITS, no P0/P1. P2 = the mandated live canary pair itself (process gate, declared in the PR body; offline-green + review-approved proven insufficient for this surface 2026-07-20). P3s: multi-drug escalation-query recall edge (titled drug + untitled drug \u2014 fast-path return can skip the vector leg; recall limitation, not misattribution, mirrors the pre-existing allowlisted-class tradeoff); reviewer probe files must stay uncommitted (relocated to scratchpad). All six clinical concerns verified safe: wrong-document impossible (alias phrases must appear in the query; per-document alias groups, no cross-drug conflation), conservative availability (S3 purely additive via keyed-union merge; sibling retention test-pinned), live expansion acceptable (title-named correct-entity SOP in every firing shape), fail-closed double layer (adversarial short-circuit precedes the predicate; injection-forge case intent=protocol cannot fire \u2014 executed), governance metadata unbypassed (same attachDocumentRankingMetadata + status=indexed + access-scope filters), no PHI/provider/schema surface.", "checks": "Reviewer checks: escalation-rescue suite 8/8, injection-forge intent derivation executed, static trace of the full S3 chain. Live canary pair = the trust gate, dispatched post-merge." }, { "date": "2026-07-21", - "ref": "claude/clinical-kb-pwa-review-asi3wb (Option A wave verdict — no code change; #1040 merged as cde6c5c)", + "ref": "claude/clinical-kb-pwa-review-asi3wb (Option A wave verdict \u2014 no code change; #1040 merged as cde6c5c)", "head": "canary run 29827012719 (#61, main cde6c5c) vs banked #60 (29800029819)", "scope": "(recorded with Outcome)", - "outcome": "OPTION A WAVE ADOPTED — FIRST FULLY-GREEN 44-CASE CANARY IN PROGRAM HISTORY (Blocking failures: None). (1) Option A payoff EXCEEDED: citation_failure_rate 0.0227→0; the neuroleptic-side-effect-escalation case flipped from wrong-doc→failed-generation→1-citation-fallback to **strong route, successful gpt-5.6-sol generation, passed in 15.4s with no fallback marker** — the rescued S3 retrieval fixed generation itself, not just the citation count; expected_source_hit 0.6364→0.6591. (2) Golden held exactly as the blast-radius analysis promised: 36/36 PASS, content_recall 1.0, mrr@10 0.8921 BYTE-IDENTICAL to the pre-wave baseline (zero ordering movement — no golden case fires the predicate), irrelevant@10 0.1083→0.0917 (slightly better). (3) Parity payoff PARTIAL: monitoring targeting 1/5→2/5 (olanzapine-lai flipped — previously called a retrieval-depth residual; quetiapine-dose also flipped on the dose side); lithium-range (232ch) + metabolic (73ch, byte-identical answer to #60) did NOT flip despite offline-proven fixes — their live chunk sets evidently contain no admissible schedule sentence even under the widened gate → reclassified as retrieval-depth/live-content residuals joining adhd; below the ≥3/5 target but strictly improved, no regression anywhere. Dose 2/5 vs 2/4: same passing count, applicable set grew (new quality-metformin-renal-dosing miss = eval-set churn, not regression). (4) No-worse EXCEEDED: relevance 0.5333→0.6 (the two-step watch-item slide FULLY REVERSED to the #58 level), targeting_rate 0.6667→0.6957, fail_closed 0.9 held, readability/artifact_leaks 1.0, route ceilings 0, grounded 1.0, unsupported_correct 1.0, numeric 0, p95 22.8s, red_result 3/3. Adoption per the measured-gain rule: primary goal achieved, three case flips, relevance recovered, zero regressions. Residual queue: monitoring retrieval-depth trio (lithium-range/metabolic/adhd), E-3d H2 discards, weekly ANSWER_CASE_LIMIT 8→44 raise now unblocked (gate would be green), comparison-class coverage. Wave spend +~$2-4 → Phase E + Option A total ~$12-20 of ≤$20.", + "outcome": "OPTION A WAVE ADOPTED \u2014 FIRST FULLY-GREEN 44-CASE CANARY IN PROGRAM HISTORY (Blocking failures: None). (1) Option A payoff EXCEEDED: citation_failure_rate 0.0227\u21920; the neuroleptic-side-effect-escalation case flipped from wrong-doc\u2192failed-generation\u21921-citation-fallback to **strong route, successful gpt-5.6-sol generation, passed in 15.4s with no fallback marker** \u2014 the rescued S3 retrieval fixed generation itself, not just the citation count; expected_source_hit 0.6364\u21920.6591. (2) Golden held exactly as the blast-radius analysis promised: 36/36 PASS, content_recall 1.0, mrr@10 0.8921 BYTE-IDENTICAL to the pre-wave baseline (zero ordering movement \u2014 no golden case fires the predicate), irrelevant@10 0.1083\u21920.0917 (slightly better). (3) Parity payoff PARTIAL: monitoring targeting 1/5\u21922/5 (olanzapine-lai flipped \u2014 previously called a retrieval-depth residual; quetiapine-dose also flipped on the dose side); lithium-range (232ch) + metabolic (73ch, byte-identical answer to #60) did NOT flip despite offline-proven fixes \u2014 their live chunk sets evidently contain no admissible schedule sentence even under the widened gate \u2192 reclassified as retrieval-depth/live-content residuals joining adhd; below the \u22653/5 target but strictly improved, no regression anywhere. Dose 2/5 vs 2/4: same passing count, applicable set grew (new quality-metformin-renal-dosing miss = eval-set churn, not regression). (4) No-worse EXCEEDED: relevance 0.5333\u21920.6 (the two-step watch-item slide FULLY REVERSED to the #58 level), targeting_rate 0.6667\u21920.6957, fail_closed 0.9 held, readability/artifact_leaks 1.0, route ceilings 0, grounded 1.0, unsupported_correct 1.0, numeric 0, p95 22.8s, red_result 3/3. Adoption per the measured-gain rule: primary goal achieved, three case flips, relevance recovered, zero regressions. Residual queue: monitoring retrieval-depth trio (lithium-range/metabolic/adhd), E-3d H2 discards, weekly ANSWER_CASE_LIMIT 8\u219244 raise now unblocked (gate would be green), comparison-class coverage. Wave spend +~$2-4 \u2192 Phase E + Option A total ~$12-20 of \u2264$20.", "checks": "Evidence: run #61 job log read (Threshold Status: None; Answer Metrics; neuroleptic diagnostics row; targeting metric_rates + 6-miss list; golden 36 PASS lines + summary). Revert drill NOT triggered." }, { @@ -20314,15 +20313,15 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (Option A: title-supported escalation rescue)", "head": "0abf3c9 (parent 1aebf02)", "scope": "rag-retrieval-reviewer PROTECTED-surface review of the S3 document-lookup escalation rescue: shouldAttemptDocumentLookupFastPath exported + gains medication_dose_risk branch firing ONLY when analysis.intent===\"escalation_risk\" && documentTitleTerms.length>0; call site passes queryAnalysis; new tests/rag-document-lookup-escalation-rescue.test.ts.", - "outcome": "APPROVE-WITH-NITS. No P0/P1/P2. Binding constraints held: released-search-order.ts + retrieval-selection.ts clamp + rag-candidate-sources.ts imputation all byte-identical to parent (git diff empty); imputation-contract test green; 0.66/0.055 floor (rag.ts:1765) unmodified and still gates rescued pools (S3 block sits after the 2513 fast-path return + re-runs decideTextFastPath at 2631). BLAST RADIUS empirically proven via 110-case offline probe (44 ragEvalCases + 30 answerQualityEvalCases + 36 golden): EXACTLY 1 fires (neuroleptic-side-effect-escalation, intent=escalation_risk tt=3); all 8 named dose cases non-firing (clozapine-monitoring general, paraphrase general, agitation-pharm general, im-po drug_dosing, typo-dosing drug_dosing, missed-dose-table drug_dosing, LAI general/tt0, prompt-injection-forge intent=protocol). intentFromSignals precedence (clinical-search.ts:575-585) returns drug_dosing before escalation_risk so pure-dose structurally cannot fire — confirmed by construction AND empirically. ADVERSARIAL: prompt-injection-forge intent=protocol => cannot fire (empirical); unsupported short-circuit (rag.ts:2371) precedes S3 block. DOWNSTREAM: buildRetrievalIntent for the escalation query yields EMPTY requiredTermSignals => demote/promote arms (retrieval-selection.ts:354-355/529/555) + wrong-medication cap (rag.ts:730-737, gated on clinical_subject) all inert; end-to-end test proves neuroleptic-doc rank#1 with >=2 citations, sibling retained, arrival-order invariant. golden vector-\\* probes = broad_summary (already allowlisted) => predicate byte-identical => unaffected. TEST HONESTY: S3 fixture (0.92/0.34/0.94/synthetic_text) faithful to searchDocumentLookupFastPath (rag-candidate-sources.ts:570 caps alias documentScore at 0.34 => sim=min(0.92,0.58+0.34+bonus)=0.92, hybrid=min(0.94,0.94)); differently-relevant fixtures (not identical-content); red-proof structurally airtight (e2e gates its own fixture pool on the predicate). EFFORT: one S3 RPC (same call allowlisted classes issue), rescue-only in the non-forceEmbedding path (floor already rejected => query was headed to embedding anyway; successful rescue short-circuits at 2646 pre-embedding = net-neutral/positive). NITS (P3, non-blocking, no code change pre-canary): (1) redundant analysis?. on the documentTitleTerms clause (&& short-circuit already guarantees analysis defined there); (2) a queryMode forcing medication_dose_risk over an originally-escalation-shaped table_threshold could newly fire S3, but table_threshold already ran S3 so behavior-consistent, not a regression; (3) \"forceEmbedding discards S3 merges\" is imprecise — line 2649 merges S3 even under forceEmbedding; the accurate unaffected-reason for vector-\\* probes is broad_summary allowlisting. TRUST GATE = the mandated live canary pair (correctly deferred by the commit).", + "outcome": "APPROVE-WITH-NITS. No P0/P1/P2. Binding constraints held: released-search-order.ts + retrieval-selection.ts clamp + rag-candidate-sources.ts imputation all byte-identical to parent (git diff empty); imputation-contract test green; 0.66/0.055 floor (rag.ts:1765) unmodified and still gates rescued pools (S3 block sits after the 2513 fast-path return + re-runs decideTextFastPath at 2631). BLAST RADIUS empirically proven via 110-case offline probe (44 ragEvalCases + 30 answerQualityEvalCases + 36 golden): EXACTLY 1 fires (neuroleptic-side-effect-escalation, intent=escalation_risk tt=3); all 8 named dose cases non-firing (clozapine-monitoring general, paraphrase general, agitation-pharm general, im-po drug_dosing, typo-dosing drug_dosing, missed-dose-table drug_dosing, LAI general/tt0, prompt-injection-forge intent=protocol). intentFromSignals precedence (clinical-search.ts:575-585) returns drug_dosing before escalation_risk so pure-dose structurally cannot fire \u2014 confirmed by construction AND empirically. ADVERSARIAL: prompt-injection-forge intent=protocol => cannot fire (empirical); unsupported short-circuit (rag.ts:2371) precedes S3 block. DOWNSTREAM: buildRetrievalIntent for the escalation query yields EMPTY requiredTermSignals => demote/promote arms (retrieval-selection.ts:354-355/529/555) + wrong-medication cap (rag.ts:730-737, gated on clinical_subject) all inert; end-to-end test proves neuroleptic-doc rank#1 with >=2 citations, sibling retained, arrival-order invariant. golden vector-\\* probes = broad_summary (already allowlisted) => predicate byte-identical => unaffected. TEST HONESTY: S3 fixture (0.92/0.34/0.94/synthetic_text) faithful to searchDocumentLookupFastPath (rag-candidate-sources.ts:570 caps alias documentScore at 0.34 => sim=min(0.92,0.58+0.34+bonus)=0.92, hybrid=min(0.94,0.94)); differently-relevant fixtures (not identical-content); red-proof structurally airtight (e2e gates its own fixture pool on the predicate). EFFORT: one S3 RPC (same call allowlisted classes issue), rescue-only in the non-forceEmbedding path (floor already rejected => query was headed to embedding anyway; successful rescue short-circuits at 2646 pre-embedding = net-neutral/positive). NITS (P3, non-blocking, no code change pre-canary): (1) redundant analysis?. on the documentTitleTerms clause (&& short-circuit already guarantees analysis defined there); (2) a queryMode forcing medication_dose_risk over an originally-escalation-shaped table_threshold could newly fire S3, but table_threshold already ran S3 so behavior-consistent, not a regression; (3) \"forceEmbedding discards S3 merges\" is imprecise \u2014 line 2649 merges S3 even under forceEmbedding; the accurate unaffected-reason for vector-\\* probes is broad_summary allowlisting. TRUST GATE = the mandated live canary pair (correctly deferred by the commit).", "checks": "Offline only, no provider calls: new test 10/10 + imputation-contract 2/2; protected-surface batch 31/31 (escalation-rescue + imputation-contract + fast-path-ordering + released-search-order + retrieval-selection); 110-case classifier probe (temp test, removed); npm run typecheck exit 0. Not run (provider-gated): eval:retrieval:quality, eval:rag, the live canary pair." }, { "date": "2026-07-21", - "ref": "claude/clinical-kb-pwa-review-asi3wb (pair verdict — no code change; main stays at 22b6a2e)", + "ref": "claude/clinical-kb-pwa-review-asi3wb (pair verdict \u2014 no code change; main stays at 22b6a2e)", "head": "canary run 29794759627 (#59, branch head 7310cb3 = merged PR-B content)", "scope": "(recorded with Outcome)", - "outcome": "E-3b + E-3c PR-B LIVE-VALIDATED (pair vs banked #57/#58): route_ceiling_failures 2→0 (E-3b proven: agitation timeout now fits inside budget; clozapine retrieval-exhausted ceiling honestly excused via the triple-condition cross-region carve-out — exactly one \"retrieval-exhausted\" audit cell in the report); p95 17.4s→15.47s (-11%); golden retrieval SUCCESS 36/36 (stop-ship criterion held); validated_routine_extractive_first fired on 4 of the 6 target cases (patient-safety-plan 3.3s, treatment-team-process 2.6s, ect-procedure 2.2s, illegal-substances 2.2s — all pure extractive, zero generation, was 6-9s each with a discarded attempt), the other 2 (community-home-visits, best-practice-prescribing) stayed on generation+fallback because their extractive candidates legitimately fail validation gates = the designed-conservative outcome; ZERO new failing cases (list 5→2, both known residuals: neuroleptic citation red = Option A territory, admission-comparison expected-doc = non-blocking labeling residual); grounded 1.0 + unsupported_correct 1.0 held; targeting 0.5909→0.619, fail_closed 0.9→0.9333, readability/artifact_leaks/intent_coverage unchanged; relevance 0.6→0.5667 = single-case wobble on n=30, WATCH in E-4, not a gate. Discarded-generation rate materially down (4 conversions; residual = the H2 strong-route slice named as E-3d candidate, per design's 20-33% expectation band). MERGE STANDS (user had armed auto-merge pre-verdict; revert drill not triggered). Spend +~$3-6 → Phase E total ~$6-12 of ≤$20.", + "outcome": "E-3b + E-3c PR-B LIVE-VALIDATED (pair vs banked #57/#58): route_ceiling_failures 2\u21920 (E-3b proven: agitation timeout now fits inside budget; clozapine retrieval-exhausted ceiling honestly excused via the triple-condition cross-region carve-out \u2014 exactly one \"retrieval-exhausted\" audit cell in the report); p95 17.4s\u219215.47s (-11%); golden retrieval SUCCESS 36/36 (stop-ship criterion held); validated_routine_extractive_first fired on 4 of the 6 target cases (patient-safety-plan 3.3s, treatment-team-process 2.6s, ect-procedure 2.2s, illegal-substances 2.2s \u2014 all pure extractive, zero generation, was 6-9s each with a discarded attempt), the other 2 (community-home-visits, best-practice-prescribing) stayed on generation+fallback because their extractive candidates legitimately fail validation gates = the designed-conservative outcome; ZERO new failing cases (list 5\u21922, both known residuals: neuroleptic citation red = Option A territory, admission-comparison expected-doc = non-blocking labeling residual); grounded 1.0 + unsupported_correct 1.0 held; targeting 0.5909\u21920.619, fail_closed 0.9\u21920.9333, readability/artifact_leaks/intent_coverage unchanged; relevance 0.6\u21920.5667 = single-case wobble on n=30, WATCH in E-4, not a gate. Discarded-generation rate materially down (4 conversions; residual = the H2 strong-route slice named as E-3d candidate, per design's 20-33% expectation band). MERGE STANDS (user had armed auto-merge pre-verdict; revert drill not triggered). Spend +~$3-6 \u2192 Phase E total ~$6-12 of \u2264$20.", "checks": "Pair evidence: run #59 job log (Blocking failures = citation only; Answer Case Diagnostics markers; metric_rates + targeting blocks); dump artifact populated for PR-C diagnosis" }, { @@ -20330,23 +20329,23 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (parity commit review)", "head": "1aebf02 (fix landed a3b9a54)", "scope": "(recorded with Outcome)", - "outcome": "rag-retrieval-reviewer on the monitoring evidence-gate parity commit: REQUEST-CHANGES (soft) — P2 reproduced: inflected monitoring kind tokens (monitor\\w*/annual(?:ly)?/blood tests?/ecgs?/lfts?) steal sole-dose-value sentences from the dose arm; dose-intent answers then reject the monitoring-kind fact (\"Quetiapine is monitored at a dose of 200 mg daily\" flipped grounded true→false, source-gap — fails CLOSED, never a wrong dose). P3: monitoring figure escape lacked the dose escape's multi-drug bare-row guard. Clean: over-admission bounded (broad vocab lives in gate/filter only, promotion still corpus-guarded, claim-support unchanged); regex cost negligible; mismatched-unit test relaxation legitimate (synopsis is corpus-verbatim; weeks pin enforced by atom identity + adjacent_context exclusion from both gate and claim corpora).", - "checks": "BOTH FINDINGS FIXED in a3b9a54: kind arm classifies legacy tokens byte-identically and new-inflection-only sentences fall through to the dose arm when they carry a clinicalDoseValuePattern value (both repro sentences pinned as dose-intent tests); multi-drug bare-row guard extended to monitoring_schedule with a discriminating test — red-proven both directions. Reviewer checks: formatting 38/38, focused 644/644; targeting eval deferred to the wave's live canary pair." + "outcome": "rag-retrieval-reviewer on the monitoring evidence-gate parity commit: REQUEST-CHANGES (soft) \u2014 P2 reproduced: inflected monitoring kind tokens (monitor\\w*/annual(?:ly)?/blood tests?/ecgs?/lfts?) steal sole-dose-value sentences from the dose arm; dose-intent answers then reject the monitoring-kind fact (\"Quetiapine is monitored at a dose of 200 mg daily\" flipped grounded true\u2192false, source-gap \u2014 fails CLOSED, never a wrong dose). P3: monitoring figure escape lacked the dose escape's multi-drug bare-row guard. Clean: over-admission bounded (broad vocab lives in gate/filter only, promotion still corpus-guarded, claim-support unchanged); regex cost negligible; mismatched-unit test relaxation legitimate (synopsis is corpus-verbatim; weeks pin enforced by atom identity + adjacent_context exclusion from both gate and claim corpora).", + "checks": "BOTH FINDINGS FIXED in a3b9a54: kind arm classifies legacy tokens byte-identically and new-inflection-only sentences fall through to the dose arm when they carry a clinicalDoseValuePattern value (both repro sentences pinned as dose-intent tests); multi-drug bare-row guard extended to monitoring_schedule with a discriminating test \u2014 red-proven both directions. Reviewer checks: formatting 38/38, focused 644/644; targeting eval deferred to the wave's live canary pair." }, { "date": "2026-07-21", "ref": "claude/clinical-kb-pwa-review-asi3wb (parity commit review)", "head": "1aebf02 (fix landed a3b9a54)", "scope": "(recorded with Outcome)", - "outcome": "clinical-governance-reviewer on the same commit: APPROVE-WITH-NITS. P2 (independently converged with the retrieval reviewer's P3): monitoring figure-escape lacked the dose-path multi-drug cross-entity guard — a bare wrong-drug schedule/level row in a multi-drug chunk could be entity-prefixed for a named-drug monitoring query; downstream gates verify text-vs-source presence, never attribution (worked lithium/valproate LFT path traced through finalize). FIXED in a3b9a54 exactly as its smallest-fix prescribed (guard at the :872-881 site now fires for monitoring_schedule; negative multi-drug test added, red-proven). Clean: unsupported figures impossible (admission-only change; promotion corpus guard + numeric verification + claim support all byte-unchanged); conservative failure intact (figure-bearing-only escape, schedule-free refusal pinned); adjacent-context safety held (sourceEvidenceText excludes adjacent_context; weeks refusal confirmed by probe); no PHI/provider/ranking surface. P3s: RAG impact line (present in the PR body — behaviour-change form, correct since the PR also carries the Option A retrieval change); multi-drug negative test (landed in a3b9a54).", + "outcome": "clinical-governance-reviewer on the same commit: APPROVE-WITH-NITS. P2 (independently converged with the retrieval reviewer's P3): monitoring figure-escape lacked the dose-path multi-drug cross-entity guard \u2014 a bare wrong-drug schedule/level row in a multi-drug chunk could be entity-prefixed for a named-drug monitoring query; downstream gates verify text-vs-source presence, never attribution (worked lithium/valproate LFT path traced through finalize). FIXED in a3b9a54 exactly as its smallest-fix prescribed (guard at the :872-881 site now fires for monitoring_schedule; negative multi-drug test added, red-proven). Clean: unsupported figures impossible (admission-only change; promotion corpus guard + numeric verification + claim support all byte-unchanged); conservative failure intact (figure-bearing-only escape, schedule-free refusal pinned); adjacent-context safety held (sourceEvidenceText excludes adjacent_context; weeks refusal confirmed by probe); no PHI/provider/ranking surface. P3s: RAG impact line (present in the PR body \u2014 behaviour-change form, correct since the PR also carries the Option A retrieval change); multi-drug negative test (landed in a3b9a54).", "checks": "Offline guard-chain trace + targeted vitest probes (named-drug guard, bare-figure admission, conservative gap, adjacent refusal). Provider/release gates deferred per confirmation boundary." }, { "date": "2026-07-21", "ref": "claude/clinical-kb-pwa-review-asi3wb (PR: E-3b budget-aware generation deadlines)", "head": "314d03f", - "scope": "Clinical-governance review of E-3b diff `git diff origin/main...HEAD` (commits 1078264 + 314d03f): answer-side generation timing/gating + telemetry — reserve-aware generation timeout (`generationRequestTimeoutMs`), truncation self-heal budget gate (`deadlineAllowsGenerationRetry`), `route_budget_exhausted_by_retrieval` telemetry, and the cross-region eval carve-out in scripts/eval-quality.ts.", - "outcome": "APPROVE-WITH-NITS. No P0/P1/P2. (a) Conservative failure preserved: reserve-aware timeout fires ~2s early producing the SAME error type — an internal SDK timeout is mapped by mapOpenAIError to PublicApiError(openai_timeout) (openai.ts:525-529), NOT a bare DOMException, so the rag.ts:4636 re-throw guard is not tripped and the existing source-backed fallback/extractive recovery is reached; truncation-skip falls through to the terminal throw (rag.ts:4309-4313) into the same catch. No new answer-producing path. (b) Safety gates intact: all recovery answers finalize through finalizeAnswer→finalizeRagAnswerQuality and isSafeExtractiveFallbackCandidate (grounded/confidence/quality/numeric) — none touched. (c) Eval carve-out env-gated: crossRegionRunner && budgetExhaustedByRetrieval && generationMs===0; EVAL_LATENCY_CONTEXT set only in eval-canary.yml:164, prod caller (eval-quality.ts:1095) passes no options → inert in release/local; generationMs===0 requirement means a generation-side failure (generationMs>0) is never suppressed. (d)/(e) Telemetry additions non-PHI (boolean + mechanical retry-reason strings); no privacy/query-privacy/cross-border/verification source files touched; no new provider call. Nits (P3, non-blocking): carve-out also excuses fast/strong routes when generationMs===0 (sound — provably no generation ran); `requestTimeoutMs` now prod-dead (test-only); report label \"retrieval-exhausted\" (routeDeadlineExceeded && flag) is broader than actual gate suppression (audit label only, gate stays strict).", + "scope": "Clinical-governance review of E-3b diff `git diff origin/main...HEAD` (commits 1078264 + 314d03f): answer-side generation timing/gating + telemetry \u2014 reserve-aware generation timeout (`generationRequestTimeoutMs`), truncation self-heal budget gate (`deadlineAllowsGenerationRetry`), `route_budget_exhausted_by_retrieval` telemetry, and the cross-region eval carve-out in scripts/eval-quality.ts.", + "outcome": "APPROVE-WITH-NITS. No P0/P1/P2. (a) Conservative failure preserved: reserve-aware timeout fires ~2s early producing the SAME error type \u2014 an internal SDK timeout is mapped by mapOpenAIError to PublicApiError(openai_timeout) (openai.ts:525-529), NOT a bare DOMException, so the rag.ts:4636 re-throw guard is not tripped and the existing source-backed fallback/extractive recovery is reached; truncation-skip falls through to the terminal throw (rag.ts:4309-4313) into the same catch. No new answer-producing path. (b) Safety gates intact: all recovery answers finalize through finalizeAnswer\u2192finalizeRagAnswerQuality and isSafeExtractiveFallbackCandidate (grounded/confidence/quality/numeric) \u2014 none touched. (c) Eval carve-out env-gated: crossRegionRunner && budgetExhaustedByRetrieval && generationMs===0; EVAL_LATENCY_CONTEXT set only in eval-canary.yml:164, prod caller (eval-quality.ts:1095) passes no options \u2192 inert in release/local; generationMs===0 requirement means a generation-side failure (generationMs>0) is never suppressed. (d)/(e) Telemetry additions non-PHI (boolean + mechanical retry-reason strings); no privacy/query-privacy/cross-border/verification source files touched; no new provider call. Nits (P3, non-blocking): carve-out also excuses fast/strong routes when generationMs===0 (sound \u2014 provably no generation ran); `requestTimeoutMs` now prod-dead (test-only); report label \"retrieval-exhausted\" (routeDeadlineExceeded && flag) is broader than actual gate suppression (audit label only, gate stays strict).", "checks": "88 offline unit tests PASS (tests/rag-route-budget.test.ts, tests/eval-quality.test.ts, tests/rag-offline-answer.test.ts, tests/rag-answer-fallback.test.ts); no provider/Supabase/OpenAI calls; no files mutated except this ledger row" }, { @@ -20354,7 +20353,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (PR: E-3b budget-aware generation deadlines)", "head": "314d03f (+eb08ec5 review row)", "scope": "(recorded with Outcome)", - "outcome": "ADDENDUM 5 wave E-3b implemented per the design-agent plan: generation attempts clamped to route budget minus a measured 2s recovery reserve (single call-site, all four attempt kinds); truncation self-heal gated on retry viability (reserve+5s floor) with observable truncation_retry_skipped_budget_reserve marker; additive route_budget_exhausted_by_retrieval runtime flag; eval route-ceiling gains the triple-condition cross-region carve-out (context + runtime flag + zero generation) with retrieval-exhausted audit cells — local/release gates provably strict. Fixes I3 (54ms budget overrun after 22.6s provider timeout), I5 (82s truncation waste class), resolves I2 (clozapine 13.3s retrieval vs 12s runtime budget = geography, now suppressed ONLY in the sanctioned cross-region context with full auditability). Reviewer verdicts: rag-retrieval-reviewer APPROVE-WITH-NITS (2 P3: prod-dead requestTimeoutMs retained for symmetry; report-cell coupling cosmetic; cached-replay invariant PROVEN — budget-exhausted answers never cached, carve-out unreachable via replay; marker isolation proven — SLO counters key on fallback_reason not answer_retry_reasons); clinical-governance-reviewer APPROVE-WITH-NITS (prior row) — internal-timeout→PublicApiError→existing-fallback path verified, all safety gates still applied to recovery answers. ALSO BANKED — E-2 targeting baseline (canary run #58, 29788404357, all-green incl. first execution of the !cancelled()-fixed instrument, ~$1-2): metric_rates relevance 0.6 / readability 1.0 / artifact_leaks 1.0 / intent_coverage 0.9333 / fail_closed 0.9; targeting_rate 0.5909 (13/22); by intent: document_lookup 5/5, red_result_action 3/3, contraindication 2/2, dose 1/5, monitoring_schedule 1/5, pathway_referral 1/2; all 9 misses = missing dose figure/schedule-interval (answer lengths 73-232 chars) → E-3c co-primary target alongside the wasted-generation class. Phase E spend ≈$3-6 of ≤$20.", + "outcome": "ADDENDUM 5 wave E-3b implemented per the design-agent plan: generation attempts clamped to route budget minus a measured 2s recovery reserve (single call-site, all four attempt kinds); truncation self-heal gated on retry viability (reserve+5s floor) with observable truncation_retry_skipped_budget_reserve marker; additive route_budget_exhausted_by_retrieval runtime flag; eval route-ceiling gains the triple-condition cross-region carve-out (context + runtime flag + zero generation) with retrieval-exhausted audit cells \u2014 local/release gates provably strict. Fixes I3 (54ms budget overrun after 22.6s provider timeout), I5 (82s truncation waste class), resolves I2 (clozapine 13.3s retrieval vs 12s runtime budget = geography, now suppressed ONLY in the sanctioned cross-region context with full auditability). Reviewer verdicts: rag-retrieval-reviewer APPROVE-WITH-NITS (2 P3: prod-dead requestTimeoutMs retained for symmetry; report-cell coupling cosmetic; cached-replay invariant PROVEN \u2014 budget-exhausted answers never cached, carve-out unreachable via replay; marker isolation proven \u2014 SLO counters key on fallback_reason not answer_retry_reasons); clinical-governance-reviewer APPROVE-WITH-NITS (prior row) \u2014 internal-timeout\u2192PublicApiError\u2192existing-fallback path verified, all safety gates still applied to recovery answers. ALSO BANKED \u2014 E-2 targeting baseline (canary run #58, 29788404357, all-green incl. first execution of the !cancelled()-fixed instrument, ~$1-2): metric_rates relevance 0.6 / readability 1.0 / artifact_leaks 1.0 / intent_coverage 0.9333 / fail_closed 0.9; targeting_rate 0.5909 (13/22); by intent: document_lookup 5/5, red_result_action 3/3, contraindication 2/2, dose 1/5, monitoring_schedule 1/5, pathway_referral 1/2; all 9 misses = missing dose figure/schedule-interval (answer lengths 73-232 chars) \u2192 E-3c co-primary target alongside the wasted-generation class. Phase E spend \u2248$3-6 of \u2264$20.", "checks": "Red-proofs: reserve pinned 3 independent ways (exact 23000ms grant, deadline flag clear, total under budget); self-heal skip pins exact marker + single provider call; offline flag pinned true/false. Focused: route-budget 9/9, eval-quality 27/27, fallback+offline 52/52, parser/abort regressions 15/15. Full suite 3043 passed / 1 known container pdf artifact. typecheck+lint+prettier clean. No provider calls; live proof = E-4 paired run" }, { @@ -20362,7 +20361,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (PR: E-3c PR-B short-circuit)", "head": "f7e6cbb + hardening commit", "scope": "(recorded with Outcome)", - "outcome": "E-3c PR-B: pre-generation validated-extractive short-circuit for gate-passed routine procedural \"What...process/include/required\" queries (marker validated_routine_extractive_first), generalizing the LAI + blocked-recovery precedents via new rag-extractive-first.ts (3 predicates moved byte-verbatim, machine-verified; rag.ts 5029→4908 vs 5030 budget). Kills the run-#57 6x wasted-generation class. REVIEWS (both pre-push): rag-retrieval-reviewer APPROVE-WITH-NITS — move fidelity brace-diff verified byte-identical; confidence-gate skip PROVEN safe (passed-gate is a no-op in applyConfidenceGate; markers pairwise mutually exclusive); comparison false-positives blocked by unchanged classifier precedence; offline/source-only idempotent; zero retrieval/ranking/selection/threshold change; P2 = eval-only assertions (intent_coverage/artifact_leaks/expected-file) unverifiable offline for flip candidates (quality-nocc-document-support, quality-form-required-documentation, quality-discharge-documentation, quality-duress-pathway + rag-set siblings) → pre-merge BRANCH canary recommended and ADOPTED (offline-green + review-approved proven insufficient for this surface, 2026-07-20). clinical-governance-reviewer APPROVE-WITH-NITS — full gate-stack trace: nothing bypassed (same finalizeRagAnswerQuality, same citation scoping, numeric verification not fail-open, ungrounded-finalize defense at rag.ts:3694); P2 = pre-existing bare-cross-reference-with-overlap gap, NOT materially widened (new trigger anti-correlates), hardening recommended → APPLIED this PR: !isBareCrossReferenceAnswer screen in hasValidatedExtractiveCandidate (closes all three short-circuit paths; discriminating test added; disclosed post-review delta, strictly narrows shipping). MERGE GATE: draft until the branch canary pair (baseline #57/#58 vs branch run with answer_case_limit=44 + answer_quality_eval=true, est $3-6 of authorized envelope) is green — zero per-case regressions, recalls 1.0, quality/targeting rates >= baseline.", + "outcome": "E-3c PR-B: pre-generation validated-extractive short-circuit for gate-passed routine procedural \"What...process/include/required\" queries (marker validated_routine_extractive_first), generalizing the LAI + blocked-recovery precedents via new rag-extractive-first.ts (3 predicates moved byte-verbatim, machine-verified; rag.ts 5029\u21924908 vs 5030 budget). Kills the run-#57 6x wasted-generation class. REVIEWS (both pre-push): rag-retrieval-reviewer APPROVE-WITH-NITS \u2014 move fidelity brace-diff verified byte-identical; confidence-gate skip PROVEN safe (passed-gate is a no-op in applyConfidenceGate; markers pairwise mutually exclusive); comparison false-positives blocked by unchanged classifier precedence; offline/source-only idempotent; zero retrieval/ranking/selection/threshold change; P2 = eval-only assertions (intent_coverage/artifact_leaks/expected-file) unverifiable offline for flip candidates (quality-nocc-document-support, quality-form-required-documentation, quality-discharge-documentation, quality-duress-pathway + rag-set siblings) \u2192 pre-merge BRANCH canary recommended and ADOPTED (offline-green + review-approved proven insufficient for this surface, 2026-07-20). clinical-governance-reviewer APPROVE-WITH-NITS \u2014 full gate-stack trace: nothing bypassed (same finalizeRagAnswerQuality, same citation scoping, numeric verification not fail-open, ungrounded-finalize defense at rag.ts:3694); P2 = pre-existing bare-cross-reference-with-overlap gap, NOT materially widened (new trigger anti-correlates), hardening recommended \u2192 APPLIED this PR: !isBareCrossReferenceAnswer screen in hasValidatedExtractiveCandidate (closes all three short-circuit paths; discriminating test added; disclosed post-review delta, strictly narrows shipping). MERGE GATE: draft until the branch canary pair (baseline #57/#58 vs branch run with answer_case_limit=44 + answer_quality_eval=true, est $3-6 of authorized envelope) is green \u2014 zero per-case regressions, recalls 1.0, quality/targeting rates >= baseline.", "checks": "Red-proof + 3 negative guards; focused 61/61 + fallback/offline/contract suites; full suite 3061 passed / 1 known container artifact (pre-hardening tree; hardening re-verified focused); typecheck+lint+prettier clean; maintainability budget passed (4908/5030)" }, { @@ -20370,7 +20369,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (PR: E-3c PR-C figure-aware selection)", "head": "043b030 + P2-fix commit", "scope": "(recorded with Outcome)", - "outcome": "E-3c PR-C: dose/monitoring extractive answers now carry the asked-for figure/schedule when the cited chunk verbatim supports it — lead-slot promotion (dose swaps last of 2 slots, monitoring appends 2nd sentence; no-op when a lead already carries a figure) guarded by the claim-support atom corpus (sourceEvidenceText exported, promotionAtomKey byte-identical to claim-support's atomKey), plus the dose/threshold generation-fallback preferring the safe figure-carrying candidate (safety gate unchanged, filter-order-stable). Fallback helpers extracted to rag-extractive-answer (cycle-check verified); rag.ts 4908→4901. Six discriminating tests each verified red-on-prior-code incl. proving the nuke-guard load-bearing by disabling it. REVIEWS (both pre-push on 043b030): rag-retrieval-reviewer APPROVE-WITH-NITS — no-op path byte-identical verified, atom-key identity verified, filter-vs-find proven side-effect-free, 2-sentence append gate-safe, intent double-gated, zero retrieval/ordering change, imputation contract green; P2 = zero-atom monitoring figures (\"every 6 weeks\" yields no value atom) pass the guard trivially and can be nuked by claim support if sourced only from adjacent context (fails SAFE — evidence gap, never a wrong figure). clinical-governance-reviewer APPROVE-WITH-NITS — all six clinical concerns CLEARED end-to-end (verbatim-support guarantee, citation binding preserved, conservative failure test-proven, unsafe candidates impossible, wrong-drug risk controlled by pre-existing entity/multi-drug guards, no PHI); same zero-atom finding as P3 + one comment-precision nit. P2 FIXED post-review (disclosed): zero-atom figures now require the matched figure substring verbatim in sourceEvidenceText (intentFigureMatchText); proven both directions by 3 new tests (promotes from content, refuses from adjacent-context-only); comment-precision nit folded in.", + "outcome": "E-3c PR-C: dose/monitoring extractive answers now carry the asked-for figure/schedule when the cited chunk verbatim supports it \u2014 lead-slot promotion (dose swaps last of 2 slots, monitoring appends 2nd sentence; no-op when a lead already carries a figure) guarded by the claim-support atom corpus (sourceEvidenceText exported, promotionAtomKey byte-identical to claim-support's atomKey), plus the dose/threshold generation-fallback preferring the safe figure-carrying candidate (safety gate unchanged, filter-order-stable). Fallback helpers extracted to rag-extractive-answer (cycle-check verified); rag.ts 4908\u21924901. Six discriminating tests each verified red-on-prior-code incl. proving the nuke-guard load-bearing by disabling it. REVIEWS (both pre-push on 043b030): rag-retrieval-reviewer APPROVE-WITH-NITS \u2014 no-op path byte-identical verified, atom-key identity verified, filter-vs-find proven side-effect-free, 2-sentence append gate-safe, intent double-gated, zero retrieval/ordering change, imputation contract green; P2 = zero-atom monitoring figures (\"every 6 weeks\" yields no value atom) pass the guard trivially and can be nuked by claim support if sourced only from adjacent context (fails SAFE \u2014 evidence gap, never a wrong figure). clinical-governance-reviewer APPROVE-WITH-NITS \u2014 all six clinical concerns CLEARED end-to-end (verbatim-support guarantee, citation binding preserved, conservative failure test-proven, unsafe candidates impossible, wrong-drug risk controlled by pre-existing entity/multi-drug guards, no PHI); same zero-atom finding as P3 + one comment-precision nit. P2 FIXED post-review (disclosed): zero-atom figures now require the matched figure substring verbatim in sourceEvidenceText (intentFigureMatchText); proven both directions by 3 new tests (promotes from content, refuses from adjacent-context-only); comment-precision nit folded in.", "checks": "Focused post-fix: extractive-formatting 32/32 + fallback/eval-cases/offline/contract/extractive-first 98/98 incl. imputation contract; typecheck+prettier+budgets clean; full-suite 3068-passed baseline pre-P2-fix (fix re-verified focused). Live proof = E-4 pair next" }, { @@ -20378,7 +20377,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (PR: I9 weekly coverage raise)", "head": "see PR head", "scope": "(recorded with Outcome)", - "outcome": "ADDENDUM 5 post-green item I9 (plan-authorized \"after reds fixed\"): weekly scheduled canary ANSWER_CASE_LIMIT default 8→44 — the Sunday 18:00 UTC cron now guards the FULL answer-quality case set instead of the first 8 (both #57 blocking reds historically lived OUTSIDE the first 8, leaving the weekly gate blind to them). Unblocked by run #61 proving the citation gate green on the full 44. Cost: est +$1-2/week (user-authorized in the plan). Contract test pin updated in lockstep (eval-canary-workflow.test.ts). Dispatch shapes unchanged (input override still wins); operational-risk diff, plain-revert rollback.", + "outcome": "ADDENDUM 5 post-green item I9 (plan-authorized \"after reds fixed\"): weekly scheduled canary ANSWER_CASE_LIMIT default 8\u219244 \u2014 the Sunday 18:00 UTC cron now guards the FULL answer-quality case set instead of the first 8 (both #57 blocking reds historically lived OUTSIDE the first 8, leaving the weekly gate blind to them). Unblocked by run #61 proving the citation gate green on the full 44. Cost: est +$1-2/week (user-authorized in the plan). Contract test pin updated in lockstep (eval-canary-workflow.test.ts). Dispatch shapes unchanged (input override still wins); operational-risk diff, plain-revert rollback.", "checks": "check:github-actions PASS; check:ci-scope PASS; check:gate-manifest PASS (20/20); eval-canary-workflow contract 4/4; prettier clean; no provider calls" }, { @@ -20386,7 +20385,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted from 87815f4; PR: E-3a cost self-reporting)", "head": "see PR head + follow-up pin", "scope": "(recorded with Outcome)", - "outcome": "Phase E-3a wave (all $0 diagnostics complete, recorded here) + I8 fix: eval-canary env gains the three RAG_EVAL__\\_USD_PER_MILLION rates (gpt-5.6-terra standard tier, verified from the live OpenAI pricing page 2026-07-21; documented as a LOWER BOUND since gpt-5.6-sol strong retries cost 2x and the estimator applies one rate set) so estimated_cost_usd stops reading n/a in CI. E-3a findings: (1) discarded-generation histogram from run #57 — fast_quality_retry_strong→extractive x6, generation_quality_failed x4, provider_timeout x2; gate sub-reasons fragment_like x2, bad_final_answer_quality x1, ungrounded_extractive_fallback x1 → E-3c targets the fast-attempt-fails-extractive-wins shape first. (2) I2 resolved: routeCeilingExceeded (eval-quality.ts:157/171) keys on the RUNTIME's own route_budget_ms + deadline flag, NOT the cross-region-widened eval gates — clozapine case = 13.3s retrieval vs the runtime's 12s extractive budget, geography-amplified; design → E-3b. (3) FIXTURE-CORPUS DRIFT (major): the live corpus contains ZERO MHSP_-named files; the 44-case fixture's expectedFiles are all MHSP._/CG.MHSP._ and pass only via the eval-document-matching alias tier. All three expected-doc failures triaged: neuroleptic-side-effect-escalation = REAL retrieval-coverage gap (alias exists; Neuroleptic Side Effects (AKG).pdf indexed 11 chunks, 3 contain escalat%, yet answer retrieval returned a single off-point source) → protected-path item awaiting user go-ahead; admission-discharge x2 = top-5 preference for sibling NMHS/RKPG policies over the existing aliased AKG doc → labeling-vs-ranking decision presented to user. No fixture/alias edits made (ground truth requires sign-off).", + "outcome": "Phase E-3a wave (all $0 diagnostics complete, recorded here) + I8 fix: eval-canary env gains the three RAG_EVAL__\\_USD_PER_MILLION rates (gpt-5.6-terra standard tier, verified from the live OpenAI pricing page 2026-07-21; documented as a LOWER BOUND since gpt-5.6-sol strong retries cost 2x and the estimator applies one rate set) so estimated_cost_usd stops reading n/a in CI. E-3a findings: (1) discarded-generation histogram from run #57 \u2014 fast_quality_retry_strong\u2192extractive x6, generation_quality_failed x4, provider_timeout x2; gate sub-reasons fragment_like x2, bad_final_answer_quality x1, ungrounded_extractive_fallback x1 \u2192 E-3c targets the fast-attempt-fails-extractive-wins shape first. (2) I2 resolved: routeCeilingExceeded (eval-quality.ts:157/171) keys on the RUNTIME's own route_budget_ms + deadline flag, NOT the cross-region-widened eval gates \u2014 clozapine case = 13.3s retrieval vs the runtime's 12s extractive budget, geography-amplified; design \u2192 E-3b. (3) FIXTURE-CORPUS DRIFT (major): the live corpus contains ZERO MHSP_-named files; the 44-case fixture's expectedFiles are all MHSP._/CG.MHSP._ and pass only via the eval-document-matching alias tier. All three expected-doc failures triaged: neuroleptic-side-effect-escalation = REAL retrieval-coverage gap (alias exists; Neuroleptic Side Effects (AKG).pdf indexed 11 chunks, 3 contain escalat%, yet answer retrieval returned a single off-point source) \u2192 protected-path item awaiting user go-ahead; admission-discharge x2 = top-5 preference for sibling NMHS/RKPG policies over the existing aliased AKG doc \u2192 labeling-vs-ranking decision presented to user. No fixture/alias edits made (ground truth requires sign-off).", "checks": "check:github-actions PASS; check:ci-scope PASS; check:gate-manifest PASS; prettier clean; Supabase access read-only (documents/document_chunks SELECTs); OpenAI pricing page read via WebFetch" }, { @@ -20394,7 +20393,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted from c308fdc; PR: labeling widen)", "head": "see PR head", "scope": "(recorded with Outcome)", - "outcome": "USER-APPROVED ground-truth widening (AskUserQuestion 2026-07-21: \"Widen to accept siblings\") for the two admission-discharge cases: the WIDER alias tier's AdmissionCommunityPts entry gains the two NMHS \"Admission to Discharge\" titles (Community Mental Health + Mental Health Inpatients). Deliberate exclusions documented in-code: discharge-only docs must not satisfy the admission slot; the MHHITH programme policy is too narrow. STRICT golden tier untouched (bulk-merge prohibition respected). Verified by replaying run #57's actual top-5 lists through expectedFileCoverage: admission-discharge-coverage-paraphrase now passes; admission-discharge-comparison STILL FAILS honestly (its top-5 carries no admission-side doc at all — dup discharge-planning + Falls Prevention) and is retained as a genuine comparison-class retrieval-coverage signal, folded into the same investigation as the neuroleptic case.", + "outcome": "USER-APPROVED ground-truth widening (AskUserQuestion 2026-07-21: \"Widen to accept siblings\") for the two admission-discharge cases: the WIDER alias tier's AdmissionCommunityPts entry gains the two NMHS \"Admission to Discharge\" titles (Community Mental Health + Mental Health Inpatients). Deliberate exclusions documented in-code: discharge-only docs must not satisfy the admission slot; the MHHITH programme policy is too narrow. STRICT golden tier untouched (bulk-merge prohibition respected). Verified by replaying run #57's actual top-5 lists through expectedFileCoverage: admission-discharge-coverage-paraphrase now passes; admission-discharge-comparison STILL FAILS honestly (its top-5 carries no admission-side doc at all \u2014 dup discharge-planning + Falls Prevention) and is retained as a genuine comparison-class retrieval-coverage signal, folded into the same investigation as the neuroleptic case.", "checks": "typecheck PASS; prettier clean; probe script replay recorded (paraphrase allHit true / comparison allHit false, missing admission slot); no retrieval code touched; protected-file edit (eval-document-matching.ts) per explicit user authorization" }, { @@ -20402,23 +20401,23 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted from e02ba3d; PR: E-3c PR-A instrument)", "head": "see PR head", "scope": "(recorded with Outcome)", - "outcome": "ADDENDUM 5 wave E-3c design accepted (Plan agent, full report in session record) and PR-A delivered: eval-answer-quality gains --dump-answers (per-case answer TEXT + sections + targeting verdict JSON for the canary artifact — answers are not retained at rest by privacy design, so miss diagnosis needs eval-time capture), parseArgs/buildAnswerDumpRecord exported behind an import.meta main-guard (eval-quality precedent), canary targeting step wired with the flag. Design highlights for the record: DEFECT 1 root confirmed as fast-attempt-doomed-then-discarded on strong_routine_retrieval procedural shapes — PR-B generalizes the EXISTING validated-extractive short-circuit pattern (LAI + blocked-recovery precedents, hasValidatedExtractiveCandidate) to the measured shape via a new rag-extractive-first.ts module (net ~-110 rag.ts lines against the 5030 budget); DEFECT 2 rank-1 root = extractive lead-slot selection prefers shortest sentence and admits figure-less leads (sort at rag-extractive-answer.ts:917, 1-slot monitoring leads) — PR-C adds intent-figure-aware lead promotion with a claim-support atom-corpus nuke-proofing guard + dose/threshold fallback candidate preference (find(safe && figure) ?? find(safe)); answer-verification CLEARED as direct cause (whole-answer gap or unbold only, never per-figure deletion). H2 (strong-route comparison/complex residual) explicitly deferred as the named E-3d candidate. E-4 metrics set: discarded-generation <20% from ~47%, dose ≥3/5, monitoring ≥3/5, no intent below #58, recalls pinned 1.0, relevance/fail_closed/readability/artifact_leaks ≥ #58.", + "outcome": "ADDENDUM 5 wave E-3c design accepted (Plan agent, full report in session record) and PR-A delivered: eval-answer-quality gains --dump-answers (per-case answer TEXT + sections + targeting verdict JSON for the canary artifact \u2014 answers are not retained at rest by privacy design, so miss diagnosis needs eval-time capture), parseArgs/buildAnswerDumpRecord exported behind an import.meta main-guard (eval-quality precedent), canary targeting step wired with the flag. Design highlights for the record: DEFECT 1 root confirmed as fast-attempt-doomed-then-discarded on strong_routine_retrieval procedural shapes \u2014 PR-B generalizes the EXISTING validated-extractive short-circuit pattern (LAI + blocked-recovery precedents, hasValidatedExtractiveCandidate) to the measured shape via a new rag-extractive-first.ts module (net ~-110 rag.ts lines against the 5030 budget); DEFECT 2 rank-1 root = extractive lead-slot selection prefers shortest sentence and admits figure-less leads (sort at rag-extractive-answer.ts:917, 1-slot monitoring leads) \u2014 PR-C adds intent-figure-aware lead promotion with a claim-support atom-corpus nuke-proofing guard + dose/threshold fallback candidate preference (find(safe && figure) ?? find(safe)); answer-verification CLEARED as direct cause (whole-answer gap or unbold only, never per-figure deletion). H2 (strong-route comparison/complex residual) explicitly deferred as the named E-3d candidate. E-4 metrics set: discarded-generation <20% from ~47%, dose \u22653/5, monitoring \u22653/5, no intent below #58, recalls pinned 1.0, relevance/fail_closed/readability/artifact_leaks \u2265 #58.", "checks": "PR-A gates: new tests/eval-answer-quality.test.ts 4/4; typecheck, check:github-actions, check:ci-scope, eval-canary-workflow test, prettier all clean; no provider calls" }, { "date": "2026-07-21", - "ref": "claude/database-governance-audit-10b6ed (PR #1051: source-governance audit — safe subset)", + "ref": "claude/database-governance-audit-10b6ed (PR #1051: source-governance audit \u2014 safe subset)", "head": "cee396730", "scope": "Governance-metadata observability + UI display + provenance flow test; no ranking/retrieval/generation surface touched.", - "outcome": "IMPLEMENTED + handed off (not a review of prior work). Resolved audit #1 (logger.warn on unrecognized enum values; return value unchanged), #2 (review_due_source added to frontendVisibleWarningCodes → answer-level badge; warning-severity, no refusal impact), #9 (source_metadata retained on safety-finding citations + governance pill in SafetyFindingsListContent), #13 (new tests/provenance-flow.test.ts: DB-normalize→governance→client payload sources+safety citations→render policy). Deferred #4/5/6/8/10 (RAG-protected ranking/selection/LLM-context/cache — need live eval-canary+approval), #11/#5 flag debt (D5/D4), #3 (is_public schema/RLS), #7 (conflict-detection scope), #12 (canary automation). Rebased onto origin/main (was 18 behind; conflict-free — none of the 18 commits touched the 8 files). PR-policy CI green (confirmed no ragRankingPatterns match).", - "checks": "verify:pr-local exit 0 (351 files/3129 tests, production build, client-bundle secret scan, offline RAG fixtures 36/36); typecheck + lint + prettier green. verify:ui NOT run locally: pre-existing globals.css Tailwind/Turbopack dev-compile error (git-clean, unrelated; prod build passed) — CI Production UI job covers it. check:production-readiness deferred (offline env/config validator; PR changes no env/secret/config inputs; secretless worktree). No provider calls." + "outcome": "IMPLEMENTED + handed off (not a review of prior work). Resolved audit #1 (logger.warn on unrecognized enum values; return value unchanged), #2 (review_due_source added to frontendVisibleWarningCodes \u2192 answer-level badge; warning-severity, no refusal impact), #9 (source_metadata retained on safety-finding citations + governance pill in SafetyFindingsListContent), #13 (new tests/provenance-flow.test.ts: DB-normalize\u2192governance\u2192client payload sources+safety citations\u2192render policy). Deferred #4/5/6/8/10 (RAG-protected ranking/selection/LLM-context/cache \u2014 need live eval-canary+approval), #11/#5 flag debt (D5/D4), #3 (is_public schema/RLS), #7 (conflict-detection scope), #12 (canary automation). Rebased onto origin/main (was 18 behind; conflict-free \u2014 none of the 18 commits touched the 8 files). PR-policy CI green (confirmed no ragRankingPatterns match).", + "checks": "verify:pr-local exit 0 (351 files/3129 tests, production build, client-bundle secret scan, offline RAG fixtures 36/36); typecheck + lint + prettier green. verify:ui NOT run locally: pre-existing globals.css Tailwind/Turbopack dev-compile error (git-clean, unrelated; prod build passed) \u2014 CI Production UI job covers it. check:production-readiness deferred (offline env/config validator; PR changes no env/secret/config inputs; secretless worktree). No provider calls." }, { "date": "2026-07-21", "ref": "claude/patient-profile-input-bounds-123366 (PR #1045: FV-03 fail-safe input bounds)", "head": "75303e8b8", - "scope": "Clinical-governance verification of FV-03 (patient-profile numeric fields → medication-safety alert engine). 4-agent adversarial workflow (consumer map + suppression audit + physiological bounds + synthesis).", - "outcome": "ADJUST→implemented. Consumer map: evaluatePatientAlerts is the ONLY numeric consumer, no dose arithmetic, sanitize() is the sole guaranteed chokepoint. Suppression audit found naive null-routing UNSAFE via the bare-renal both-null hole (medication-patient-alerts.ts:286) — nulling one out-of-range renal input while the other is present-normal → false all-clear; fixed with &&→|| (0 bare-renal contraindication rows in corpus → no-op on current data). Bounds VALIDATED (age 0-130, egfr 0-250, crcl 0-400, qtc 240-800, scr µmol/L 15-3000 unit-aware): never reject a legitimate clinical extreme. Reject-to-null (never clamp).", + "scope": "Clinical-governance verification of FV-03 (patient-profile numeric fields \u2192 medication-safety alert engine). 4-agent adversarial workflow (consumer map + suppression audit + physiological bounds + synthesis).", + "outcome": "ADJUST\u2192implemented. Consumer map: evaluatePatientAlerts is the ONLY numeric consumer, no dose arithmetic, sanitize() is the sole guaranteed chokepoint. Suppression audit found naive null-routing UNSAFE via the bare-renal both-null hole (medication-patient-alerts.ts:286) \u2014 nulling one out-of-range renal input while the other is present-normal \u2192 false all-clear; fixed with &&\u2192|| (0 bare-renal contraindication rows in corpus \u2192 no-op on current data). Bounds VALIDATED (age 0-130, egfr 0-250, crcl 0-400, qtc 240-800, scr \u00b5mol/L 15-3000 unit-aware): never reject a legitimate clinical extreme. Reject-to-null (never clamp).", "checks": "typecheck, lint, format:check, full unit+jsdom 349 files/3120 passed/0 failed (incl. 38 new/updated FV-03 tests), design-system-contract (baselines unchanged), type-scale, icon-scale, check:production-readiness READY. verify:ui in CI. No provider calls." }, { @@ -20426,7 +20425,7 @@ "ref": "claude/x4-sast-gate (PR #1012)", "head": "0d4985e63", "scope": "Maturity X4: blocking SAST gate on the untrusted-document parsing surface", - "outcome": "Triage-first per workorder: CI-pinned semgrep/semgrep:1.168.0 over worker/**, src/lib/ingestion*.ts, src/lib/extractors, src/app/api/{ingestion,upload} = 0 ERROR findings (24 TS rules/17 files; 55 Python rules/3 files) — gate starts green with no suppressions. Shipped `semgrep-ingestion-gate` job (no continue-on-error; container digest-pinned to the triage-verified 1.168.0 image) with p/python added for the worker OCR stack; repo-wide advisory job untouched. check-github-action-pins.mjs now enforces both policy halves fail-closed (advisory repo-wide / blocking-and-scoped gate / digest-pinned gate container). Residuals: registry-pack mutability accepted for the narrow surface; making the workflow a branch-protection required check is an operator decision outside this PR.", + "outcome": "Triage-first per workorder: CI-pinned semgrep/semgrep:1.168.0 over worker/**, src/lib/ingestion*.ts, src/lib/extractors, src/app/api/{ingestion,upload} = 0 ERROR findings (24 TS rules/17 files; 55 Python rules/3 files) \u2014 gate starts green with no suppressions. Shipped `semgrep-ingestion-gate` job (no continue-on-error; container digest-pinned to the triage-verified 1.168.0 image) with p/python added for the worker OCR stack; repo-wide advisory job untouched. check-github-action-pins.mjs now enforces both policy halves fail-closed (advisory repo-wide / blocking-and-scoped gate / digest-pinned gate container). Residuals: registry-pack mutability accepted for the narrow surface; making the workflow a branch-protection required check is an operator decision outside this PR.", "checks": "Exact gate command exit 0 in pinned container; check:github-actions (new assertions verified fail-closed); check:ci-scope; yaml-contract vitest 1/1; verify:cheap 3031 tests green. No provider calls (local Docker only)." }, { @@ -20439,26 +20438,26 @@ }, { "date": "2026-07-20", - "ref": "claude/clinical-kb-pwa-review-asi3wb (Phase B live pair — no code change; recorded for eval-history completeness)", + "ref": "claude/clinical-kb-pwa-review-asi3wb (Phase B live pair \u2014 no code change; recorded for eval-history completeness)", "head": "canary runs 29763761133 (#53 baseline) + 29769050798 (#54 tuned)", - "scope": "ADDENDUM 4 Phase B verdict: staged 3-class tuner weights produced ZERO live movement — NOT adopted per the measured-gain rule", - "outcome": "Offline tuner recommendations (document_lookup titleSection→0.9, table_threshold clinicalEvidence→0.95, comparison hybridRelevance→0.95; proxy comparison-mrr 0.833→1.0) staged via the B-PR-1 rag_ranking_config input; #54 log proves the override active (validation step echo). Result vs re-gated baseline: mrr@10 0.8921 vs 0.8922, irrelevant@10 0.1083 vs 0.1083, recalls 1.0/1.0 both, 36/36 both, all four headroom cases byte-identical rr (flowchart 0.20, ciwa-threshold 0.25, patient-safety 0.33, opioid 0.33). Learning: the 5-candidate linear proxy saturates; real headroom lives in fast-path saturated-tie structure (Phase C trigger condition mrr < 0.90 formally met; user authorized C). Nothing to roll back (per-run override). Spend ≈$2-4 of user-raised ≤$20 cap.", + "scope": "ADDENDUM 4 Phase B verdict: staged 3-class tuner weights produced ZERO live movement \u2014 NOT adopted per the measured-gain rule", + "outcome": "Offline tuner recommendations (document_lookup titleSection\u21920.9, table_threshold clinicalEvidence\u21920.95, comparison hybridRelevance\u21920.95; proxy comparison-mrr 0.833\u21921.0) staged via the B-PR-1 rag_ranking_config input; #54 log proves the override active (validation step echo). Result vs re-gated baseline: mrr@10 0.8921 vs 0.8922, irrelevant@10 0.1083 vs 0.1083, recalls 1.0/1.0 both, 36/36 both, all four headroom cases byte-identical rr (flowchart 0.20, ciwa-threshold 0.25, patient-safety 0.33, opioid 0.33). Learning: the 5-candidate linear proxy saturates; real headroom lives in fast-path saturated-tie structure (Phase C trigger condition mrr < 0.90 formally met; user authorized C). Nothing to roll back (per-run override). Spend \u2248$2-4 of user-raised \u2264$20 cap.", "checks": "Both canary runs green (36/36 + answer-quality); override-active proof in #54 job log; no adoption = no code diff" }, { "date": "2026-07-20", - "ref": "claude/clinical-kb-pwa-review-asi3wb (Phase C live verdict — no code change; main stays reverted at 0a498e6)", + "ref": "claude/clinical-kb-pwa-review-asi3wb (Phase C live verdict \u2014 no code change; main stays reverted at 0a498e6)", "head": "canary run 29773198933 (#55, on f96217c)", - "scope": "ADDENDUM 4 Phase C LIVE-REFUTED: canary on the merged tail code FAILED 3/36 (doc_recall 1.0→0.9167, mrr@10 0.8921→0.8138) — the user-ordered revert (#1005) was correct and STANDS", - "outcome": "Failures: patient-safety-plan-include (PtSafetyPlan out of top-5, rr 0.33→0.14), patient-property-visual-table (rr 1.00→0.11) and schizophrenia-overview (rr 1.00→0.14) — two previously rank-1 cases destroyed. Root cause (post-hoc): the S1 lexical-chunk lift spreads hybrid_score, which is the PRIMARY release sort key — inside the dead (0.48,0.5) band it still PREEMPTS every downstream key, so raw ts_rank order overrode the boost/title/subject-aware relevance order that previously decided all-tied-at-0.48 pools. Lexically-loud chunks leapfrogged title-boosted correct documents = the #118 mechanism, reproduced live. The offline S1 test used identical-content candidates (coverage tie) and could not see it. The S2 similarity tail (tie-break-position key) remains reviewer-verified safe in isolation — retrieval reviewer verdict on the full diff: APPROVE-WITH-NITS, P3 only (0.49-lowering proven unreachable via the SQL 0.48 cap; no gate crossings in (0.92,0.94); hardening nits recorded). DISPOSITION: no re-land as-is. Any retry = S2-only + S1 redesigned to a key BELOW relevance in the comparator chain, new design + fresh pair. The staged-rollback discipline (canary pair + instant revert) worked exactly as designed. Spend ≈$4-8 of ≤$20.", + "scope": "ADDENDUM 4 Phase C LIVE-REFUTED: canary on the merged tail code FAILED 3/36 (doc_recall 1.0\u21920.9167, mrr@10 0.8921\u21920.8138) \u2014 the user-ordered revert (#1005) was correct and STANDS", + "outcome": "Failures: patient-safety-plan-include (PtSafetyPlan out of top-5, rr 0.33\u21920.14), patient-property-visual-table (rr 1.00\u21920.11) and schizophrenia-overview (rr 1.00\u21920.14) \u2014 two previously rank-1 cases destroyed. Root cause (post-hoc): the S1 lexical-chunk lift spreads hybrid_score, which is the PRIMARY release sort key \u2014 inside the dead (0.48,0.5) band it still PREEMPTS every downstream key, so raw ts_rank order overrode the boost/title/subject-aware relevance order that previously decided all-tied-at-0.48 pools. Lexically-loud chunks leapfrogged title-boosted correct documents = the #118 mechanism, reproduced live. The offline S1 test used identical-content candidates (coverage tie) and could not see it. The S2 similarity tail (tie-break-position key) remains reviewer-verified safe in isolation \u2014 retrieval reviewer verdict on the full diff: APPROVE-WITH-NITS, P3 only (0.49-lowering proven unreachable via the SQL 0.48 cap; no gate crossings in (0.92,0.94); hardening nits recorded). DISPOSITION: no re-land as-is. Any retry = S2-only + S1 redesigned to a key BELOW relevance in the comparator chain, new design + fresh pair. The staged-rollback discipline (canary pair + instant revert) worked exactly as designed. Spend \u2248$4-8 of \u2264$20.", "checks": "Canary #55 read from job log (3 FAIL lines + summary); reviewer verdict from subagent report; main verified reverted (0 saturationTailUnit refs at 0a498e6)" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (PR: DB easy wins)", "head": "see PR head", - "scope": "User-requested database + process easy-wins pass: read-only Supabase advisor sweep (user-authorized) → canary-liveness probe + advisor-disposition docs; live mutations withheld for per-item confirmation", - "outcome": "Advisors (live, read-only): security = 1 INFO (document_title_words RLS-no-policy = the deliberate fail-closed pattern — now comment-documented at the schema block so it is never 'fixed'); performance = ~33 unused-index INFOs + auth connection-strategy note → docs/db-maintenance.md TRIAGE list with retrieval-surface trgm indexes flagged RAG-protected (dropping = full canary protocol), owner-scoped indexes retained for multi-tenant design, operational candidates deferred (negligible benefit at corpus size). Implemented: ci.yml static-pr warn-only eval-canary staleness probe (actions:read, github-script pinned, >8 days → warning; never fails) — needed because #923 (2026-07-19) moved the canary cadence from daily to weekly Sunday 18:00 UTC, where a dropped fire would go unnoticed for a week (the failure-issue step only reacts to runs that happen). CORRECTION (CodeRabbit review on this PR): the initially recorded \"2026-07-20 dropped Sunday fire\" incident did not occur — 2026-07-20 is a Monday; the Sunday 2026-07-19 slot fired as scheduled run #48 (19:03 UTC, success), and under the weekly cron no 2026-07-20 slot existed. Probe stands as proactive hardening, staleness now measured from updated_at with a finite-timestamp guard. Presented for confirmation (NOT implemented): scheduled telemetry retention (purge:query-logs is owner-scoped + unscheduled; needs owner/window/policy decision), auth percentage connection strategy (dashboard config), any index drops.", + "scope": "User-requested database + process easy-wins pass: read-only Supabase advisor sweep (user-authorized) \u2192 canary-liveness probe + advisor-disposition docs; live mutations withheld for per-item confirmation", + "outcome": "Advisors (live, read-only): security = 1 INFO (document_title_words RLS-no-policy = the deliberate fail-closed pattern \u2014 now comment-documented at the schema block so it is never 'fixed'); performance = ~33 unused-index INFOs + auth connection-strategy note \u2192 docs/db-maintenance.md TRIAGE list with retrieval-surface trgm indexes flagged RAG-protected (dropping = full canary protocol), owner-scoped indexes retained for multi-tenant design, operational candidates deferred (negligible benefit at corpus size). Implemented: ci.yml static-pr warn-only eval-canary staleness probe (actions:read, github-script pinned, >8 days \u2192 warning; never fails) \u2014 needed because #923 (2026-07-19) moved the canary cadence from daily to weekly Sunday 18:00 UTC, where a dropped fire would go unnoticed for a week (the failure-issue step only reacts to runs that happen). CORRECTION (CodeRabbit review on this PR): the initially recorded \"2026-07-20 dropped Sunday fire\" incident did not occur \u2014 2026-07-20 is a Monday; the Sunday 2026-07-19 slot fired as scheduled run #48 (19:03 UTC, success), and under the weekly cron no 2026-07-20 slot existed. Probe stands as proactive hardening, staleness now measured from updated_at with a finite-timestamp guard. Presented for confirmation (NOT implemented): scheduled telemetry retention (purge:query-logs is owner-scoped + unscheduled; needs owner/window/policy decision), auth percentage connection strategy (dashboard config), any index drops.", "checks": "check:github-actions PASS; check:ci-scope PASS; check:function-grants 28/28 PASS; docs:check-links 1034 PASS; supabase-schema vitest 66/66; lint+typecheck+prettier clean; Supabase access read-only only" }, { @@ -20466,7 +20465,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (PR: matcher + artifact follow-ups)", "head": "ab145f6", "scope": "Remaining documented improvements implemented: word-boundary textContainsClinicalTerm + top-10 canary artifact rows", - "outcome": "Matcher: boundaries + internal separators widened to any non-alphanumeric run — PROVEN strict superset by artifact replay on canary #53 (1,126 term×alias×result comparisons, 0 lost matches, 7 gained = exactly the previously-documented punctuation-joined occurrences: treatment,/mood,/(opioid/ptsd.[35]/ciwa-ar ×3). More-tolerant measurement cannot fail a passing case → weekly scheduled canary = free live confirmation. Exported + 3 direct unit-test groups (superset preservation, audit classes incl. line-broken 'ciwa- ar' and 'full-blood-count', substring-inside-word rejections). Artifact: topResultSummary 5→10 rows so rr@10/irrelevant@10 metrics' actual inputs are captured — unblocks the offline irrelevant@10 labeling audit next artifact. docs/rag-behaviour updated to implemented state. Phase E remains gated on separate approval.", + "outcome": "Matcher: boundaries + internal separators widened to any non-alphanumeric run \u2014 PROVEN strict superset by artifact replay on canary #53 (1,126 term\u00d7alias\u00d7result comparisons, 0 lost matches, 7 gained = exactly the previously-documented punctuation-joined occurrences: treatment,/mood,/(opioid/ptsd.[35]/ciwa-ar \u00d73). More-tolerant measurement cannot fail a passing case \u2192 weekly scheduled canary = free live confirmation. Exported + 3 direct unit-test groups (superset preservation, audit classes incl. line-broken 'ciwa- ar' and 'full-blood-count', substring-inside-word rejections). Artifact: topResultSummary 5\u219210 rows so rr@10/irrelevant@10 metrics' actual inputs are captured \u2014 unblocks the offline irrelevant@10 labeling audit next artifact. docs/rag-behaviour updated to implemented state. Phase E remains gated on separate approval.", "checks": "Targeted vitest 59/59; npm run test 3028 passed / 1 known container pdf-budget artifact; lint+typecheck+prettier clean; audit script run recorded above; no provider calls" }, { @@ -20474,7 +20473,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (PR: RAG memory + safeguards)", "head": "see PR head", "scope": "(recorded with Outcome)", - "outcome": "User-directed close-out: durable RAG behaviour memory (docs/rag-behaviour/, 4 files) + AGENTS.md standing protection rules + ENFORCED safeguards — pr-policy blocking `RAG impact:` gate on protected surfaces (self-tested: undeclared/vague blocked, no-change/canary declarations pass) + source-pin contract test on imputation formulas and release comparator key order (red-proven vs a mutated constant). Confirmation canary #56 (29774459706, reverted main 0a498e6): SUCCESS — 36/36 restored, closing the #55-regression→revert→restore arc live. Phase D complete (D-1 ref input #1003, D-2 eval:trend #1006, D-3 policy §3.1 #1006, D-4 latency in trend rows); remaining documented plans: word-boundary matcher (own PR), irrelevant@10 labeling audit, Phase E (separate approval). Spend ≈$5-10 of ≤$20.", + "outcome": "User-directed close-out: durable RAG behaviour memory (docs/rag-behaviour/, 4 files) + AGENTS.md standing protection rules + ENFORCED safeguards \u2014 pr-policy blocking `RAG impact:` gate on protected surfaces (self-tested: undeclared/vague blocked, no-change/canary declarations pass) + source-pin contract test on imputation formulas and release comparator key order (red-proven vs a mutated constant). Confirmation canary #56 (29774459706, reverted main 0a498e6): SUCCESS \u2014 36/36 restored, closing the #55-regression\u2192revert\u2192restore arc live. Phase D complete (D-1 ref input #1003, D-2 eval:trend #1006, D-3 policy \u00a73.1 #1006, D-4 latency in trend rows); remaining documented plans: word-boundary matcher (own PR), irrelevant@10 labeling audit, Phase E (separate approval). Spend \u2248$5-10 of \u2264$20.", "checks": "pr-policy self-test + workflow guard PASS; contract test 4/4 + red-proof; npm run test 3025 passed / 1 known container pdf-budget artifact; lint+typecheck+prettier clean; docs:check-links 1030 refs PASS; check:github-actions PASS" }, { @@ -20482,7 +20481,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (PR: revert Phase C pending review)", "head": "revert of f96217c", "scope": "User-requested revert of #1004 (Phase C saturation-tail primaries): auto-merge fired before the adversarial rag-retrieval-reviewer pass landed; retrieval code returns to the last reviewed state until that verdict is in", - "outcome": "Clean single-commit revert (the documented rollback path — helpers + 2 expression sites + 1 map call; no schema/config/cache surface). Ledger history rows from f96217c retained (docs are append-only record, not behavior). The 19:44Z post-merge canary dispatched on f96217c completes regardless and stands as Phase C's live validation datapoint; re-land decision = reviewer verdict + that pair result together. Offline state of the reverted change remains fully proven (red-proof + 121/121 + envelope tests).", + "outcome": "Clean single-commit revert (the documented rollback path \u2014 helpers + 2 expression sites + 1 map call; no schema/config/cache surface). Ledger history rows from f96217c retained (docs are append-only record, not behavior). The 19:44Z post-merge canary dispatched on f96217c completes regardless and stands as Phase C's live validation datapoint; re-land decision = reviewer verdict + that pair result together. Offline state of the reverted change remains fully proven (red-proof + 121/121 + envelope tests).", "checks": "Revert verified by vitest fast-path suite returning to pre-C 5/5 shape expected in CI; ladder on the revert = hosted pr-required" }, { @@ -20490,47 +20489,47 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted from 5b4098d; PR: E-2 baseline record + instrument fix)", "head": "see PR head", "scope": "(recorded with Outcome)", - "outcome": "ADDENDUM Phase E-2 BASELINE BANKED (canary dispatch #57, run 29786560936, main 5b4098d, answer_case_limit=44): golden retrieval 36/36 green in-run (no-regression net held); eval:quality full-44 RED on exactly two gates — citation_failure_rate 0.0227 (1/44: neuroleptic-side-effect-escalation — expected doc never retrieved, generation quality-failed, extractive fallback with 1 citation) and route_ceiling_failure_count 2 (clozapine-anc-withhold-threshold: 13.3s pure retrieval vs 12s extractive budget, RPC 9.3s, zero generation; agitation-arousal-typo-dosing: 25054ms vs 25000ms after provider_timeout ate 22.6s pre-recovery). Green gates: grounded_supported 1.0, unsupported_correct 1.0 (all 14 refusals incl. both prompt-injection probes at 2ms), numeric grounding failures 0, governance danger 0, p95 17.4s. Non-blocking signals: expected_source_hit 0.6136 (both admission-discharge cases miss MHSP.AdmissionCommunityPts.pdf to sibling NMHS/RKPG policies — labeling-vs-ranking question, §3.1 class), source governance warning rate 0.8182 (metadata debt, waivable class). SYSTEMIC E-3 TARGET: ~9 of 19 generation attempts discarded (fast output fails quality gate → extractive fallback wins; ~7 cases carry fast_quality_retry_strong→extractive reasons) = ~half of generation latency+spend wasted. Instrument defect found+fixed this PR: targeting step was skipped after the red gate (GitHub failure-skip semantics) → if: gains !cancelled() so baselines observe red gates. Spend: est ~$1-2 actual (19 OpenAI-request cases; cost rates unset in CI so report shows n/a) of ≤$20 Phase E envelope. Next: cheap re-dispatch (default limit 8 + answer_quality_eval=true) to bank the skipped 30-case targeting baseline.", + "outcome": "ADDENDUM Phase E-2 BASELINE BANKED (canary dispatch #57, run 29786560936, main 5b4098d, answer_case_limit=44): golden retrieval 36/36 green in-run (no-regression net held); eval:quality full-44 RED on exactly two gates \u2014 citation_failure_rate 0.0227 (1/44: neuroleptic-side-effect-escalation \u2014 expected doc never retrieved, generation quality-failed, extractive fallback with 1 citation) and route_ceiling_failure_count 2 (clozapine-anc-withhold-threshold: 13.3s pure retrieval vs 12s extractive budget, RPC 9.3s, zero generation; agitation-arousal-typo-dosing: 25054ms vs 25000ms after provider_timeout ate 22.6s pre-recovery). Green gates: grounded_supported 1.0, unsupported_correct 1.0 (all 14 refusals incl. both prompt-injection probes at 2ms), numeric grounding failures 0, governance danger 0, p95 17.4s. Non-blocking signals: expected_source_hit 0.6136 (both admission-discharge cases miss MHSP.AdmissionCommunityPts.pdf to sibling NMHS/RKPG policies \u2014 labeling-vs-ranking question, \u00a73.1 class), source governance warning rate 0.8182 (metadata debt, waivable class). SYSTEMIC E-3 TARGET: ~9 of 19 generation attempts discarded (fast output fails quality gate \u2192 extractive fallback wins; ~7 cases carry fast_quality_retry_strong\u2192extractive reasons) = ~half of generation latency+spend wasted. Instrument defect found+fixed this PR: targeting step was skipped after the red gate (GitHub failure-skip semantics) \u2192 if: gains !cancelled() so baselines observe red gates. Spend: est ~$1-2 actual (19 OpenAI-request cases; cost rates unset in CI so report shows n/a) of \u2264$20 Phase E envelope. Next: cheap re-dispatch (default limit 8 + answer_quality_eval=true) to bank the skipped 30-case targeting baseline.", "checks": "Gates this PR: check:github-actions PASS; check:ci-scope PASS; check:gate-manifest PASS; prettier clean. Baseline evidence: job log run 29786560936 (5 failing-case diagnostics + Answer Metrics table read in full)" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted from e6cd6cb; PR: telemetry-retention correction)", "head": "01368ff (+0144e69 main merge-in)", - "scope": "User-directed \"implement your recommendation for all decisions\" close-out: the scheduled-retention recommendation is RETRACTED as founded on a false premise — telemetry retention is ALREADY ACTIVE inside the database via pg_cron; docs corrected, nothing built, no live mutations", - "outcome": "Fresh read-only cron.job verification (2026-07-20) matches docs/privacy-impact-assessment.md §6 exactly: jobid 11 purge-expired-rag-queries daily 03:30 (30d), jobid 12 purge-rag-retrieval-logs daily 03:00 (90d), jobid 13 purge-rag-query-misses daily 03:45 (90d), jobid 16 purge-rag-response-cache hourly (bounded 1000); v3 worker jobs present-inactive under backlog auto-toggle (jobid 10); obsolete unbounded cache job absent; audit_logs indefinite by design. db-maintenance.md \"open decision\" section replaced with the resolved state; purge:query-logs clarified as the MANUAL owner-scoped tool (not the retention mechanism). A GitHub-side weekly deleter would have duplicated pg_cron with window drift (a 90d rag_queries sweep can never out-delete the live 30d job). Remaining decisions stand as documented no-action: auth percentage connection strategy deferred to next instance resize; operational index drops not recommended.", + "scope": "User-directed \"implement your recommendation for all decisions\" close-out: the scheduled-retention recommendation is RETRACTED as founded on a false premise \u2014 telemetry retention is ALREADY ACTIVE inside the database via pg_cron; docs corrected, nothing built, no live mutations", + "outcome": "Fresh read-only cron.job verification (2026-07-20) matches docs/privacy-impact-assessment.md \u00a76 exactly: jobid 11 purge-expired-rag-queries daily 03:30 (30d), jobid 12 purge-rag-retrieval-logs daily 03:00 (90d), jobid 13 purge-rag-query-misses daily 03:45 (90d), jobid 16 purge-rag-response-cache hourly (bounded 1000); v3 worker jobs present-inactive under backlog auto-toggle (jobid 10); obsolete unbounded cache job absent; audit_logs indefinite by design. db-maintenance.md \"open decision\" section replaced with the resolved state; purge:query-logs clarified as the MANUAL owner-scoped tool (not the retention mechanism). A GitHub-side weekly deleter would have duplicated pg_cron with window drift (a 90d rag_queries sweep can never out-delete the live 30d job). Remaining decisions stand as documented no-action: auth percentage connection strategy deferred to next instance resize; operational index drops not recommended.", "checks": "prettier + docs:check-links PASS; Supabase access read-only (single cron.job SELECT, user-authorized read-only envelope); no workflow/schema/config changes" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted from f33890a; PR: Phase E instrument input)", "head": "see PR head + follow-up SHA pin", - "scope": "Phase E kickoff (user-approved with budget): eval-canary gains opt-in `answer_quality_eval` dispatch input running the 30-case eval:answer-quality fixture (5 quality metrics + per-intent targeting) — the instrument was previously never run in CI. Dispatch-only, default-off, informational (exit 0, no --targeting-floor): scheduled runs and existing dispatch shapes byte-identical; gates stay owned by eval:quality. Follows the #1003 input-only precedent.", - "outcome": "E-1 recon (all $0/read-only) recorded here: canary answer gate samples only 8 of 44 eval:quality cases (ANSWER_CASE_LIMIT default); eval:quality --provider-mode offline is a real $0 harness (provider deleted, deterministic source-only path) usable as an E-3 regression guard; live 30-day answer telemetry (34 answer-path rows): 25 full answers, misses = evidence_gap ×4 (avg 26s spent before gap), provider_incomplete_max_output_tokens ×2 (avg 82s wasted then discarded), provider_generation_failed ×1, retrieval_gap_or_conflict ×1, source_only_no_api ×1; success latency avg 13.1s / p90 25.2s. Headroom classes for E-3: truncation waste (rag.ts:4265 self-heal insufficient live), late evidence-gap detection, p90 latency, thin CI answer coverage. Next: E-2 baseline dispatch (answer_case_limit=44 + answer_quality_eval=true, est $3-8 of user-authorized ≤$20 Phase E envelope) after this merges.", - "checks": "check:github-actions PASS; check:ci-scope PASS; check:gate-manifest PASS; prettier clean; no provider calls this PR (workflow change only); RAG impact: none — retrieval steps untouched" + "scope": "Phase E kickoff (user-approved with budget): eval-canary gains opt-in `answer_quality_eval` dispatch input running the 30-case eval:answer-quality fixture (5 quality metrics + per-intent targeting) \u2014 the instrument was previously never run in CI. Dispatch-only, default-off, informational (exit 0, no --targeting-floor): scheduled runs and existing dispatch shapes byte-identical; gates stay owned by eval:quality. Follows the #1003 input-only precedent.", + "outcome": "E-1 recon (all $0/read-only) recorded here: canary answer gate samples only 8 of 44 eval:quality cases (ANSWER_CASE_LIMIT default); eval:quality --provider-mode offline is a real $0 harness (provider deleted, deterministic source-only path) usable as an E-3 regression guard; live 30-day answer telemetry (34 answer-path rows): 25 full answers, misses = evidence_gap \u00d74 (avg 26s spent before gap), provider_incomplete_max_output_tokens \u00d72 (avg 82s wasted then discarded), provider_generation_failed \u00d71, retrieval_gap_or_conflict \u00d71, source_only_no_api \u00d71; success latency avg 13.1s / p90 25.2s. Headroom classes for E-3: truncation waste (rag.ts:4265 self-heal insufficient live), late evidence-gap detection, p90 latency, thin CI answer coverage. Next: E-2 baseline dispatch (answer_case_limit=44 + answer_quality_eval=true, est $3-8 of user-authorized \u2264$20 Phase E envelope) after this merges.", + "checks": "check:github-actions PASS; check:ci-scope PASS; check:gate-manifest PASS; prettier clean; no provider calls this PR (workflow change only); RAG impact: none \u2014 retrieval steps untouched" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted; PR #1001: A-PR-2 measurement-floor completion)", "head": "3d8f798 + 5b664f8 + e58c827", - "scope": "First provenance-stamped snapshot regeneration from a live canary artifact + alias tiering docs + fixture-length pin + lithium doc-gate — Phase A of ADDENDUM 4 functionally complete", - "outcome": "Artifact chain: user-authorized paid dispatch (canary #53, run 29763761133, 36/36 green, doc_recall 1.0 / content_recall 1.0 — first perfect content recall, ciwa alias confirmed live; mrr@10 0.8644, irrelevant@10 0.1083) emitted the first eval-canary-output artifact (51787 bytes, sha256 5af5b802… verified byte-identical after user transfer into the sandbox — this container cannot download run artifacts). Work: (1) two-tier alias documentation — investigation of the governance-review P3 showed src/lib/eval-document-matching.ts is a deliberately WIDER captured-case tier (e.g. \"Clozapine GP Shared Care\"); bulk-merge would loosen golden ground truth, so both files now carry cross-referencing do-not-merge headers instead; (2) snapshot case count pinned to live golden fixture length (regeneration instructions in failure message) — closes the coarse-floor P3; (3) snapshot regenerated via the alias-aware builder with --source-run-id provenance: agitation-im-po-options 0→5 graded positives (EMHS alias working on real data), flowchart-next-step confirmed sole zero-positive case; generatedAt promoted to validator-REQUIRED (closes the hand-edit P3); two stale data pins updated (missing-positives 2→1; broad_summary defaults-equality pin dropped — defaults' provenance was the retired snapshot, fresh recommendations are Phase B input); (4) artifact-grounded punctuation audit: 7 joined-token occurrences in top-5 previews — 3 ciwa-ar (alias-covered, incl. line-broken \"ciwa- ar\"), 4 ORDINARY-PROSE punctuation (\"treatment,\" / \"mood,\" / \"(opioid\" / \"ptsd.[35]\") — matcher word-boundary change proposed as its OWN reviewed follow-up per plan (systemic class, not bundled); (5) lithium-therapy-monitoring was the ONLY ungated case (rr@10 hardcoded 0.00 = measurement noise): expectedDocumentSubstrings [\"Lithium\"] added from live evidence (deliberately broad across the corpus's multiple legitimate lithium guidelines), snapshot rebuilt in lockstep from the same artifact, measured mrr@10 +~0.028 from de-noising. Deferred with reasons: NEW-query fixture cases (saturated-tie shapes, captured rag_query_misses) need live validation before they may gate — unlocked by Phase D-1 branch-eval dispatch or a dedicated validation dispatch; real ordering headroom for Phase B = flowchart 0.20, alcohol-ciwa 0.25, patient-safety 0.33, opioid 0.33, all text_fast_path.", - "checks": "Targeted vitest 76/76 ×3 (after each stage); npm run test 3019 passed / 1 known container-only pdf-budget artifact; prettier clean; freshness gate ACTIVE and green; no provider calls beyond the user-authorized dispatch (~$1-2, ADDENDUM 4 spend now ~$1-2 of ≤$10)" + "scope": "First provenance-stamped snapshot regeneration from a live canary artifact + alias tiering docs + fixture-length pin + lithium doc-gate \u2014 Phase A of ADDENDUM 4 functionally complete", + "outcome": "Artifact chain: user-authorized paid dispatch (canary #53, run 29763761133, 36/36 green, doc_recall 1.0 / content_recall 1.0 \u2014 first perfect content recall, ciwa alias confirmed live; mrr@10 0.8644, irrelevant@10 0.1083) emitted the first eval-canary-output artifact (51787 bytes, sha256 5af5b802\u2026 verified byte-identical after user transfer into the sandbox \u2014 this container cannot download run artifacts). Work: (1) two-tier alias documentation \u2014 investigation of the governance-review P3 showed src/lib/eval-document-matching.ts is a deliberately WIDER captured-case tier (e.g. \"Clozapine GP Shared Care\"); bulk-merge would loosen golden ground truth, so both files now carry cross-referencing do-not-merge headers instead; (2) snapshot case count pinned to live golden fixture length (regeneration instructions in failure message) \u2014 closes the coarse-floor P3; (3) snapshot regenerated via the alias-aware builder with --source-run-id provenance: agitation-im-po-options 0\u21925 graded positives (EMHS alias working on real data), flowchart-next-step confirmed sole zero-positive case; generatedAt promoted to validator-REQUIRED (closes the hand-edit P3); two stale data pins updated (missing-positives 2\u21921; broad_summary defaults-equality pin dropped \u2014 defaults' provenance was the retired snapshot, fresh recommendations are Phase B input); (4) artifact-grounded punctuation audit: 7 joined-token occurrences in top-5 previews \u2014 3 ciwa-ar (alias-covered, incl. line-broken \"ciwa- ar\"), 4 ORDINARY-PROSE punctuation (\"treatment,\" / \"mood,\" / \"(opioid\" / \"ptsd.[35]\") \u2014 matcher word-boundary change proposed as its OWN reviewed follow-up per plan (systemic class, not bundled); (5) lithium-therapy-monitoring was the ONLY ungated case (rr@10 hardcoded 0.00 = measurement noise): expectedDocumentSubstrings [\"Lithium\"] added from live evidence (deliberately broad across the corpus's multiple legitimate lithium guidelines), snapshot rebuilt in lockstep from the same artifact, measured mrr@10 +~0.028 from de-noising. Deferred with reasons: NEW-query fixture cases (saturated-tie shapes, captured rag_query_misses) need live validation before they may gate \u2014 unlocked by Phase D-1 branch-eval dispatch or a dedicated validation dispatch; real ordering headroom for Phase B = flowchart 0.20, alcohol-ciwa 0.25, patient-safety 0.33, opioid 0.33, all text_fast_path.", + "checks": "Targeted vitest 76/76 \u00d73 (after each stage); npm run test 3019 passed / 1 known container-only pdf-budget artifact; prettier clean; freshness gate ACTIVE and green; no provider calls beyond the user-authorized dispatch (~$1-2, ADDENDUM 4 spend now ~$1-2 of \u2264$10)" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted; PR: #901 rerank regression closeout)", "head": "fd5dcd1582e1c7aa8bf92ff097575e0c68aa930d", "scope": "#901 rerank regression: baseline re-eval + offline guard net + saturated-tie fix", - "outcome": "Baseline eval-canary dispatch on remediated main b3ae061 (run 29731533081) PASSED — golden retrieval 36/36 + answer-quality green, confirming #913-#926 closed the live 4/36 regression (July 19 failing run tested the raw #901 state; fixes landed 1-8h after it, never re-evaled until now). Residual defect found by new offline repro and fixed: with byte-identical imputed fast-path primaries, selection's clamped keys tie exactly and the chunk-id fallback decides, which secondStageScore's position adjustment launders into releaseRankScore (buried the CIWA answer doc in repro); fix = contentRankScore carried on RetrievalCandidate as tie-break between clamped rerankScore and chunk id, never added to scores. Amended #901's own never-live-validated saturated-tie pin to content-rank-then-id. Guards: tests/rag-fast-path-ordering.test.ts (4 end-to-end eval-shape repros) + ranking-tuning gates (4 golden-mapped hard negatives at production weights + full-snapshot high-risk). Fixture aliases NOT changed (Step C not triggered — identity cases pass live).", + "outcome": "Baseline eval-canary dispatch on remediated main b3ae061 (run 29731533081) PASSED \u2014 golden retrieval 36/36 + answer-quality green, confirming #913-#926 closed the live 4/36 regression (July 19 failing run tested the raw #901 state; fixes landed 1-8h after it, never re-evaled until now). Residual defect found by new offline repro and fixed: with byte-identical imputed fast-path primaries, selection's clamped keys tie exactly and the chunk-id fallback decides, which secondStageScore's position adjustment launders into releaseRankScore (buried the CIWA answer doc in repro); fix = contentRankScore carried on RetrievalCandidate as tie-break between clamped rerankScore and chunk id, never added to scores. Amended #901's own never-live-validated saturated-tie pin to content-rank-then-id. Guards: tests/rag-fast-path-ordering.test.ts (4 end-to-end eval-shape repros) + ranking-tuning gates (4 golden-mapped hard negatives at production weights + full-snapshot high-risk). Fixture aliases NOT changed (Step C not triggered \u2014 identity cases pass live).", "checks": "Targeted 4-suite vitest 37/37; npm run test 2981 passed (sole fail = container-only pdf-extraction-budget artifact); verify:cheap green through all 18 pre-test checks incl. lint+typecheck; check:production-readiness PASS on substantive checks (2 FAILs = documented missing-secret class in this container); build + client-bundle scan + check:rag:fixtures PASS" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted; PR: B-PR-1 canary dispatch inputs)", "head": "see PR head", - "scope": "eval-canary.yml workflow_dispatch gains rag_ranking_config (staged Phase B weight evals, loud malformed-JSON validation to prevent silent fallback corrupting pair comparisons) + ref (Phase D-1 pre-merge branch evals) — schedule runs unaffected (empty inputs = today's behavior)", - "outcome": "Tuner (offline, $0) on the A-PR-2 regenerated snapshot recommends 3 constrained per-class improvements (document_lookup titleSectionRelevance→0.9; table_threshold clinicalEvidence→0.95; comparison hybridRelevance→0.95 with proxy mrr 0.833→1.0), all with recall non-regression + zero high-risk hard-negative failures; medication_dose_risk + broad_summary stay neutral. Staged config JSON banked for the live pair; baseline = canary #53 re-gated (mrr@10 ≈0.8922 after lithium de-noising). Targets per approved plan: mrr@10 ≥0.90, irrelevant@10 ≤0.08, zero case regressions. Budget: user raised cap to ≤$20 (spent ≈$1-2). Security note: ref input runs branch code with eval secrets — dispatch requires repo write access (sole trusted collaborator), documented in PR risk.", + "scope": "eval-canary.yml workflow_dispatch gains rag_ranking_config (staged Phase B weight evals, loud malformed-JSON validation to prevent silent fallback corrupting pair comparisons) + ref (Phase D-1 pre-merge branch evals) \u2014 schedule runs unaffected (empty inputs = today's behavior)", + "outcome": "Tuner (offline, $0) on the A-PR-2 regenerated snapshot recommends 3 constrained per-class improvements (document_lookup titleSectionRelevance\u21920.9; table_threshold clinicalEvidence\u21920.95; comparison hybridRelevance\u21920.95 with proxy mrr 0.833\u21921.0), all with recall non-regression + zero high-risk hard-negative failures; medication_dose_risk + broad_summary stay neutral. Staged config JSON banked for the live pair; baseline = canary #53 re-gated (mrr@10 \u22480.8922 after lithium de-noising). Targets per approved plan: mrr@10 \u22650.90, irrelevant@10 \u22640.08, zero case regressions. Budget: user raised cap to \u2264$20 (spent \u2248$1-2). Security note: ref input runs branch code with eval secrets \u2014 dispatch requires repo write access (sole trusted collaborator), documented in PR risk.", "checks": "check:github-actions PASS; check:ci-scope PASS; prettier clean; no provider calls (workflow change only)" }, { @@ -20538,63 +20537,63 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted; PR: ci.yml concurrency)", "head": "79aaacf04e64f753c480dd957a81ac9be6acbb43", "scope": "CI workflow concurrency: stop main churn cancelling dispatch/schedule runs", - "outcome": "One-line group expression: workflow_dispatch/schedule events now get a per-run concurrency group (github.run_id) while push/PR keep the shared ref group with cancel-in-progress — fixes the release-browser-matrix livelock (cancelled twice on 2026-07-19/20 by main merges mid-run; the weekly Sunday 18:00 UTC scheduled run was subject to the same cancellation). release-browser-matrix is not a required branch-protection check; pin/scope checkers do not constrain the concurrency block. Accepted side effect: deliberate runs can overlap push runs. Rollback: plain revert.", + "outcome": "One-line group expression: workflow_dispatch/schedule events now get a per-run concurrency group (github.run_id) while push/PR keep the shared ref group with cancel-in-progress \u2014 fixes the release-browser-matrix livelock (cancelled twice on 2026-07-19/20 by main merges mid-run; the weekly Sunday 18:00 UTC scheduled run was subject to the same cancellation). release-browser-matrix is not a required branch-protection check; pin/scope checkers do not constrain the concurrency block. Accepted side effect: deliberate runs can overlap push runs. Rollback: plain revert.", "checks": "check:github-actions PASS; check:ci-scope PASS; format:check PASS (repo files; local-only .claude/settings.local.json warning is gitignored)" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted; PR: coverage tie-break follow-up)", "head": "57ec880b306a8e2b31c5f20dacc47256fc93b4e2", - "scope": "Post-merge live-eval finding on #982 + corrective fix: saturated-tie key rankScore → query-term coverage", - "outcome": "Post-#982 golden dispatch (eval-canary run #50, 29735004222, main b9057f0 + deps) came back 35/36: the three verifiable July-19 failures (lithium-therapy-monitoring, clozapine-anc-threshold, patient-safety-plan-include) all PASS live, but alcohol-ciwa-threshold flipped pass→FAIL vs the same-morning pre-#982 run #49 (29731533081, 36/36) — failing top-3 ordered by descending rankScore (1.85/1.75/1.53, all finalScore-saturated, releaseRankScore 1.09/1.086/1.07), i.e. #982's tie-break let generic clinicalSignalBoost stacking outvote the ciwa/score/threshold-bearing chunk; #982 is the only retrieval-path delta in the window. Fix: contentRankScore → contentCoverageScore sourced from lexicalCoverageScore (query-term coverage, immune to boost stacking; ties still fall to chunk id); saturated-tie contract test re-pinned so coverage beats a HIGHER rankScore (discriminating — old key fails it); fast-path CIWA guard gains the run-#50 screening-chunk shape + content-term assertion. Live validation: tonight's 18:00 UTC scheduled canary (dispatch cap 2/2 spent ≈$2-4). Separately: ci.yml dispatch 4012 survived 30+ min of main churn under #979's per-run concurrency group (fix working); duplicate dispatch 4017 cancelled.", + "scope": "Post-merge live-eval finding on #982 + corrective fix: saturated-tie key rankScore \u2192 query-term coverage", + "outcome": "Post-#982 golden dispatch (eval-canary run #50, 29735004222, main b9057f0 + deps) came back 35/36: the three verifiable July-19 failures (lithium-therapy-monitoring, clozapine-anc-threshold, patient-safety-plan-include) all PASS live, but alcohol-ciwa-threshold flipped pass\u2192FAIL vs the same-morning pre-#982 run #49 (29731533081, 36/36) \u2014 failing top-3 ordered by descending rankScore (1.85/1.75/1.53, all finalScore-saturated, releaseRankScore 1.09/1.086/1.07), i.e. #982's tie-break let generic clinicalSignalBoost stacking outvote the ciwa/score/threshold-bearing chunk; #982 is the only retrieval-path delta in the window. Fix: contentRankScore \u2192 contentCoverageScore sourced from lexicalCoverageScore (query-term coverage, immune to boost stacking; ties still fall to chunk id); saturated-tie contract test re-pinned so coverage beats a HIGHER rankScore (discriminating \u2014 old key fails it); fast-path CIWA guard gains the run-#50 screening-chunk shape + content-term assertion. Live validation: tonight's 18:00 UTC scheduled canary (dispatch cap 2/2 spent \u2248$2-4). Separately: ci.yml dispatch 4012 survived 30+ min of main churn under #979's per-run concurrency group (fix working); duplicate dispatch 4017 cancelled.", "checks": "Targeted vitest 38/38; npm run test 3012 passed / 1 known container-only pdf-budget artifact; verify:cheap green to the same artifact; build + client-bundle scan + check:rag:fixtures PASS; check:production-readiness expected missing-secret FAILs only (no secrets in container)" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted; PR: eval measurement floor, ADDENDUM 4 A-PR-1)", "head": "81ab9696da4b330ca0b2e5519891a9942f90421b", - "scope": "Measurement floor for evidence-gated ranking tuning: canary artifact emission, alias-aware snapshot builder, snapshot provenance/freshness — no ranking behavior change", - "outcome": "Closes the three gaps blocking safe tuning (Phase B): (1) eval-canary's golden step now writes the per-case JSON artifact (--json-out decoupled from --json so the tee'd log keeps the human-readable lines the failure-issue analyzer parses) and uploads .local/eval-canary/ via pinned upload-artifact (30-day retention, include-hidden-files for the dot-dir, contents = same class as the already-public step logs: titles/telemetry/220-char previews of the all-public corpus) — snapshot regeneration stops costing a paid dispatch; (2) clinicalDocumentAliases/clinicalContentAliases moved verbatim to shared scripts/lib/clinical-aliases.ts and the snapshot builder grades documentMatch/contentMatch through them (discriminating tests: EMHS agitation title and spelled-out \"absolute neutrophil count\" grade as hits only via aliases — raw labelMatches pinned false), ending tuner ground truth disagreeing with the live gates; (3) snapshots carry generatedAt + optional sourceRunId, validator accepts them, exactly-36 relaxed to at-least-36 (floor still rejects truncated artifacts; sourceCaseCount + per-case candidate minimums unchanged), and a 30-day freshness test (activates on first regeneration) blocks silent corpus drift. Builder smoke-verified end-to-end on a synthetic 36-case artifact (alias grading + provenance stamped + validator green). Static hyphen audit of all 36 cases' terms: no currently-blocked term (canary #52 = 36/36); residual risk classes documented for the A-PR-2 artifact-grounded pass — punctuation-joined tokens (IM/PO, schizo-affective, post-natal) and inert stem entries (obsess/compuls/hyperactiv/impuls can never match whole-token) that currently ride on whole-word OR-alternates.", - "checks": "Targeted vitest 52/52 (ranking-tuning + eval-retrieval + eval-quality); npm run test 3019 passed / 1 known container-only pdf-budget artifact; lint + typecheck clean; check:github-actions + check:ci-scope PASS; prettier clean; check:production-readiness expected missing-secret FAILs only (demo-mode container); no provider calls — live validation = tonight's scheduled canary emits the first artifact at $0" + "scope": "Measurement floor for evidence-gated ranking tuning: canary artifact emission, alias-aware snapshot builder, snapshot provenance/freshness \u2014 no ranking behavior change", + "outcome": "Closes the three gaps blocking safe tuning (Phase B): (1) eval-canary's golden step now writes the per-case JSON artifact (--json-out decoupled from --json so the tee'd log keeps the human-readable lines the failure-issue analyzer parses) and uploads .local/eval-canary/ via pinned upload-artifact (30-day retention, include-hidden-files for the dot-dir, contents = same class as the already-public step logs: titles/telemetry/220-char previews of the all-public corpus) \u2014 snapshot regeneration stops costing a paid dispatch; (2) clinicalDocumentAliases/clinicalContentAliases moved verbatim to shared scripts/lib/clinical-aliases.ts and the snapshot builder grades documentMatch/contentMatch through them (discriminating tests: EMHS agitation title and spelled-out \"absolute neutrophil count\" grade as hits only via aliases \u2014 raw labelMatches pinned false), ending tuner ground truth disagreeing with the live gates; (3) snapshots carry generatedAt + optional sourceRunId, validator accepts them, exactly-36 relaxed to at-least-36 (floor still rejects truncated artifacts; sourceCaseCount + per-case candidate minimums unchanged), and a 30-day freshness test (activates on first regeneration) blocks silent corpus drift. Builder smoke-verified end-to-end on a synthetic 36-case artifact (alias grading + provenance stamped + validator green). Static hyphen audit of all 36 cases' terms: no currently-blocked term (canary #52 = 36/36); residual risk classes documented for the A-PR-2 artifact-grounded pass \u2014 punctuation-joined tokens (IM/PO, schizo-affective, post-natal) and inert stem entries (obsess/compuls/hyperactiv/impuls can never match whole-token) that currently ride on whole-word OR-alternates.", + "checks": "Targeted vitest 52/52 (ranking-tuning + eval-retrieval + eval-quality); npm run test 3019 passed / 1 known container-only pdf-budget artifact; lint + typecheck clean; check:github-actions + check:ci-scope PASS; prettier clean; check:production-readiness expected missing-secret FAILs only (demo-mode container); no provider calls \u2014 live validation = tonight's scheduled canary emits the first artifact at $0" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted; PR: matrix-remainder fixes)", "head": "ec070ccb20b9a067216e64e8399d9cd795027024", "scope": "Run-4012 remainder: 7 root-caused fixes (SW navigation hijack, WebKit focus/forced-colors/stale-style, Firefox tab order, CIWA alias, helper extraction)", - "outcome": "Agent-diagnosed with probe evidence: (1) production-build PWA worker registers in EVERY matrix test (pwa-lifecycle.tsx:287 NODE_ENV gate), clients.claim()s the page and serves all navigations — Chromium probe proved SW-served reloads bypass page.route entirely (routeSawNav=[]); Playwright-Firefox wedges on its only two reloads (ui-smoke 2206/2932, both deterministic) → playwright.config.ts serviceWorkers:'block' + ui-pwa 'allow' opt-in (offline/CacheStorage journey verified passing locally under the opt-in). (2) Mode-menu dismissal relied solely on wrapper focusout; WebKit Tab navigation can move focus nowhere (links excluded) or wrap into the menu → keydown Tab-close in handleModeTriggerKeyDown (agent verified no test depends on old forward-Tab behavior). (3) WebKit has no forced-colors implementation → capability skip on the token-remap test. (4) WebKit stale :disabled computed style feeds axe a phantom 1.93 contrast for the re-enabled Previous button (blend arithmetic exact: 0.4×#475467+0.6×#fff=#b5bbc2) → toBeEnabled+opacity-1 pin before the scan, failure-at-pin = direct proof. (5) Firefox includes scrollable containers in tab order (sheet body scrollHeight 1125 vs 707 measured) → conditional step-over. (6) canary #50/#51 CIWA failure root cause: whitespace-delimited textContainsClinicalTerm can never match hyphenated 'CIWA-Ar' though the dosing-table region ranks top-5 → clinicalContentAliases ciwa:[ciwa, ciwa-ar] (plan-authorized fixture-alias route; content substance unchanged). (7) tests/helpers/zero-touch.ts shared helper replaces six #995 inline stubs (CodeRabbit follow-up). NOT claimed: ui-stress 409 overflow, ui-tools 2087 navigation race, webkit answer-flow subset — next matrix run (post-merge dispatch) measures these vs the 28-failure baseline; ui-smoke 2932 webkit-side is a distinct mock-data class deliberately deferred pending that run.", - "checks": "Targeted vitest 25/25 (eval-retrieval + search-command-surface); npm run test 3012 passed / 1 known container pdf-budget artifact; verify:cheap green to same artifact; build + client-bundle scan PASS; prettier/eslint/typecheck clean; chromium ui-pwa under new SW config: offline/CacheStorage privacy journey PASS, installability = known container in-incognito artifact; UI verification not run locally beyond that: chromium ui suites carry documented container artifacts — hosted ui-critical/ui-advisory + next matrix authoritative" + "outcome": "Agent-diagnosed with probe evidence: (1) production-build PWA worker registers in EVERY matrix test (pwa-lifecycle.tsx:287 NODE_ENV gate), clients.claim()s the page and serves all navigations \u2014 Chromium probe proved SW-served reloads bypass page.route entirely (routeSawNav=[]); Playwright-Firefox wedges on its only two reloads (ui-smoke 2206/2932, both deterministic) \u2192 playwright.config.ts serviceWorkers:'block' + ui-pwa 'allow' opt-in (offline/CacheStorage journey verified passing locally under the opt-in). (2) Mode-menu dismissal relied solely on wrapper focusout; WebKit Tab navigation can move focus nowhere (links excluded) or wrap into the menu \u2192 keydown Tab-close in handleModeTriggerKeyDown (agent verified no test depends on old forward-Tab behavior). (3) WebKit has no forced-colors implementation \u2192 capability skip on the token-remap test. (4) WebKit stale :disabled computed style feeds axe a phantom 1.93 contrast for the re-enabled Previous button (blend arithmetic exact: 0.4\u00d7#475467+0.6\u00d7#fff=#b5bbc2) \u2192 toBeEnabled+opacity-1 pin before the scan, failure-at-pin = direct proof. (5) Firefox includes scrollable containers in tab order (sheet body scrollHeight 1125 vs 707 measured) \u2192 conditional step-over. (6) canary #50/#51 CIWA failure root cause: whitespace-delimited textContainsClinicalTerm can never match hyphenated 'CIWA-Ar' though the dosing-table region ranks top-5 \u2192 clinicalContentAliases ciwa:[ciwa, ciwa-ar] (plan-authorized fixture-alias route; content substance unchanged). (7) tests/helpers/zero-touch.ts shared helper replaces six #995 inline stubs (CodeRabbit follow-up). NOT claimed: ui-stress 409 overflow, ui-tools 2087 navigation race, webkit answer-flow subset \u2014 next matrix run (post-merge dispatch) measures these vs the 28-failure baseline; ui-smoke 2932 webkit-side is a distinct mock-data class deliberately deferred pending that run.", + "checks": "Targeted vitest 25/25 (eval-retrieval + search-command-surface); npm run test 3012 passed / 1 known container pdf-budget artifact; verify:cheap green to same artifact; build + client-bundle scan PASS; prettier/eslint/typecheck clean; chromium ui-pwa under new SW config: offline/CacheStorage privacy journey PASS, installability = known container in-incognito artifact; UI verification not run locally beyond that: chromium ui suites carry documented container artifacts \u2014 hosted ui-critical/ui-advisory + next matrix authoritative" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted; PR: Phase C saturation-tail primaries)", "head": "7572c7f", - "scope": "ADDENDUM 4 Phase C (user-authorized): per-candidate discriminative primaries for saturated fast-path ties — design-agent planned (consumer map + dead-band envelope proof), red-proven, tie-conservation guarded", - "outcome": "Mechanism: min(text_rank,1) collapses all tr≥1 candidates to byte-identical imputed primaries; ordering fell to chunk id at release. Fix: saturationTailUnit (pure, monotone, SET-INDEPENDENT — rejected per-query min-max + rank-tier designs for set-dependence/#118 authority risk; rejected full-range log rescale for moving sub-knee values across the 0.62-0.82 gate ladder) scales the excess into DEAD cap bands only: S2 table-fact similarity (0.92, 0.94) with hybrid byte-identical (gates/triggers/selection provably unchanged; similarity = the release tie-break key), S1 lexical-chunk hybrid (0.48, 0.5) behind the truthful-contract signature (sub-0.5 bars hold). Sub-knee byte-identical (fixtures now DERIVE from the helper; 0.45→0.755/0.795 pinned). Discriminating test verified RED on old formulas (2 fail: discriminating + envelope) → green with tail; equal-tr tie-conservation pins the #987 coverage comparator; second-stage-engaged pools documented out of scope (position-derived releaseRankScore sorts first there) — matches live evidence that non-engaged pools (patient-safety, opioid, flowchart) are where id-order decided. S3/S4 = C-PR-2 candidates, evidence-gated on the post-merge canary vs #54 baseline (doc/content recall MUST stay 1.0, zero per-case regressions; success signal = rr lift on the headroom cases). Rollback: single revert (helpers + 2 expression sites + 1 map call; no schema/config/cache surface).", + "scope": "ADDENDUM 4 Phase C (user-authorized): per-candidate discriminative primaries for saturated fast-path ties \u2014 design-agent planned (consumer map + dead-band envelope proof), red-proven, tie-conservation guarded", + "outcome": "Mechanism: min(text_rank,1) collapses all tr\u22651 candidates to byte-identical imputed primaries; ordering fell to chunk id at release. Fix: saturationTailUnit (pure, monotone, SET-INDEPENDENT \u2014 rejected per-query min-max + rank-tier designs for set-dependence/#118 authority risk; rejected full-range log rescale for moving sub-knee values across the 0.62-0.82 gate ladder) scales the excess into DEAD cap bands only: S2 table-fact similarity (0.92, 0.94) with hybrid byte-identical (gates/triggers/selection provably unchanged; similarity = the release tie-break key), S1 lexical-chunk hybrid (0.48, 0.5) behind the truthful-contract signature (sub-0.5 bars hold). Sub-knee byte-identical (fixtures now DERIVE from the helper; 0.45\u21920.755/0.795 pinned). Discriminating test verified RED on old formulas (2 fail: discriminating + envelope) \u2192 green with tail; equal-tr tie-conservation pins the #987 coverage comparator; second-stage-engaged pools documented out of scope (position-derived releaseRankScore sorts first there) \u2014 matches live evidence that non-engaged pools (patient-safety, opioid, flowchart) are where id-order decided. S3/S4 = C-PR-2 candidates, evidence-gated on the post-merge canary vs #54 baseline (doc/content recall MUST stay 1.0, zero per-case regressions; success signal = rr lift on the headroom cases). Rollback: single revert (helpers + 2 expression sites + 1 map call; no schema/config/cache surface).", "checks": "Targeted vitest 121/121 (fast-path 11/11 incl. 6 new, retrieval-selection, rag-routing, rag-answer-fallback, ranking-tuning, second-stage); npm run test 3025 passed / 1 known container pdf-budget artifact; lint + typecheck + prettier clean; red-proof executed and recorded; live validation = post-merge canary dispatch (~$1-2)" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted; PR: WebKit matrix diagnosis)", "head": "caa298972846ef52d472bfbff98c90fc26481ed8", - "scope": "First completed release-browser-matrix in weeks (run 4012, main b9057f0, 38 min uncancelled under #979) — full triage of 28 failures + fix for the dominant cluster", - "outcome": "Run 4012: 716 passed / 28 failed (25 webkit, 3 firefox) / 4 skipped. Dominant cluster (root-caused, FIXED here): all 8 ui-universal-search webkit failures share one signature — typeahead content never enters the DOM — because commandDropdownCanDisplay (added 42a3e3c 2026-07-17, AFTER the last completed matrix; never ran on WebKit until 4012) requires fine-pointer OR zero-touch; headless browsers fail the (hover:hover)+(pointer:fine) query (proven by the zero-touch escape existing for CI at all), Chromium/Firefox pass via maxTouchPoints===0, and Playwright's Linux WebKit build advertises phantom touch points — flunking both branches and disabling useUniversalSearch entirely. Fix: beforeEach addInitScript in ui-universal-search/ui-smoke/ui-tools specs stubbing Navigator.prototype.maxTouchPoints to the runner's true 0 (inert on Chromium/Firefox; product gate + tests/search-command-surface.test.ts pins untouched). Local chromium runs of ui-universal-search fail 16/20 IDENTICALLY on unmodified main (container artifact — hosted CI chromium green in 4012 is authoritative; verified by stash/run/pop baseline). Expected delta next matrix: ≥8 webkit failures clear; candidates ui-tools:1244 + several ui-smoke answer-flow cases (same surface). NOT yet root-caused (triaged remainder, hosted-matrix-only reproduction): webkit ui-stress overflow 330/409 (360px overflow at mobile), webkit ui-accessibility 195/252 (focus dismissal; forced-colors labels), webkit ui-formulation 132, webkit ui-smoke copy-table/retry/recovery/recent-searches/source-only/differential-context/viewer-hydration/document-questions, webkit ui-tools 2087 (goto interrupted by ?q= navigation), webkit ui-universal-search 183 strict-mode duplicate options (fallback-surface rendering; likely clears with the gate fix), firefox ui-smoke 946/2206/2932 (@critical document search fails on BOTH firefox and webkit — cross-browser, highest-priority remainder).", - "checks": "prettier PASS; eslint PASS; typecheck PASS; chromium stash-baseline no-delta (16 fail pre AND post — container artifact); webkit validation lands via tonight's 18:00 UTC scheduled matrix" + "scope": "First completed release-browser-matrix in weeks (run 4012, main b9057f0, 38 min uncancelled under #979) \u2014 full triage of 28 failures + fix for the dominant cluster", + "outcome": "Run 4012: 716 passed / 28 failed (25 webkit, 3 firefox) / 4 skipped. Dominant cluster (root-caused, FIXED here): all 8 ui-universal-search webkit failures share one signature \u2014 typeahead content never enters the DOM \u2014 because commandDropdownCanDisplay (added 42a3e3c 2026-07-17, AFTER the last completed matrix; never ran on WebKit until 4012) requires fine-pointer OR zero-touch; headless browsers fail the (hover:hover)+(pointer:fine) query (proven by the zero-touch escape existing for CI at all), Chromium/Firefox pass via maxTouchPoints===0, and Playwright's Linux WebKit build advertises phantom touch points \u2014 flunking both branches and disabling useUniversalSearch entirely. Fix: beforeEach addInitScript in ui-universal-search/ui-smoke/ui-tools specs stubbing Navigator.prototype.maxTouchPoints to the runner's true 0 (inert on Chromium/Firefox; product gate + tests/search-command-surface.test.ts pins untouched). Local chromium runs of ui-universal-search fail 16/20 IDENTICALLY on unmodified main (container artifact \u2014 hosted CI chromium green in 4012 is authoritative; verified by stash/run/pop baseline). Expected delta next matrix: \u22658 webkit failures clear; candidates ui-tools:1244 + several ui-smoke answer-flow cases (same surface). NOT yet root-caused (triaged remainder, hosted-matrix-only reproduction): webkit ui-stress overflow 330/409 (360px overflow at mobile), webkit ui-accessibility 195/252 (focus dismissal; forced-colors labels), webkit ui-formulation 132, webkit ui-smoke copy-table/retry/recovery/recent-searches/source-only/differential-context/viewer-hydration/document-questions, webkit ui-tools 2087 (goto interrupted by ?q= navigation), webkit ui-universal-search 183 strict-mode duplicate options (fallback-surface rendering; likely clears with the gate fix), firefox ui-smoke 946/2206/2932 (@critical document search fails on BOTH firefox and webkit \u2014 cross-browser, highest-priority remainder).", + "checks": "prettier PASS; eslint PASS; typecheck PASS; chromium stash-baseline no-delta (16 fail pre AND post \u2014 container artifact); webkit validation lands via tonight's 18:00 UTC scheduled matrix" }, { "date": "2026-07-20", "ref": "claude/phone-scroll-fix (PR #993)", "head": "f0f4c42e7", "scope": "Phone scroll \"locks to bottom\" regression from #964 + all-pages phone scroll audit + guardrails", - "outcome": "Root cause: #964's phone mode-home dock made one hide-on-scroll event release ~180-260px of scroll geometry (header grid collapse + reserve-pad shrink) — more than a short mode home's remaining runway, so scrollTop clamps onto the new bottom and a 12px up-drag snaps it back (oscillation; measured 266→84px runway, 2 flips/gesture on /formulation @390×844). Invisible to all gates because the suite-wide reducedMotion:\"reduce\" disables the causal transitions. Fix: collapse-budget gate in computeScrollHideUpdate (hosts report the would-be geometry release via readChromeCollapseBudget; hide refused without runway to absorb it; budget-less consumers unchanged; bottom-clamp guard untouched). Bonus latent bug fixed: DocumentViewer's one-shot #main-content discovery could hold a detached node after shell remounts (viewer hide-on-scroll dead); observer now persists. ui-smoke bottom-hide scenario updated to the gate contract. New 18-test sweep tests/ui-phone-scroll.spec.ts (10 mode homes + 3 dashboard modes + 4 long routes, motion enabled, simulated PWA insets) verified to fail red pre-fix. Residual: real-device iOS momentum clamping is device-only — user PWA confirmation requested post-deploy.", + "outcome": "Root cause: #964's phone mode-home dock made one hide-on-scroll event release ~180-260px of scroll geometry (header grid collapse + reserve-pad shrink) \u2014 more than a short mode home's remaining runway, so scrollTop clamps onto the new bottom and a 12px up-drag snaps it back (oscillation; measured 266\u219284px runway, 2 flips/gesture on /formulation @390\u00d7844). Invisible to all gates because the suite-wide reducedMotion:\"reduce\" disables the causal transitions. Fix: collapse-budget gate in computeScrollHideUpdate (hosts report the would-be geometry release via readChromeCollapseBudget; hide refused without runway to absorb it; budget-less consumers unchanged; bottom-clamp guard untouched). Bonus latent bug fixed: DocumentViewer's one-shot #main-content discovery could hold a detached node after shell remounts (viewer hide-on-scroll dead); observer now persists. ui-smoke bottom-hide scenario updated to the gate contract. New 18-test sweep tests/ui-phone-scroll.spec.ts (10 mode homes + 3 dashboard modes + 4 long routes, motion enabled, simulated PWA insets) verified to fail red pre-fix. Residual: real-device iOS momentum clamping is device-only \u2014 user PWA confirmation requested post-deploy.", "checks": "vitest focused 24/24 + mobile-composer-reserve; verify:cheap 3020 green; ui-phone-scroll chromium 18/18 + webkit advisory 18/18; ui-formulation+ui-tools+ui-smoke 180/180; verify:ui 264/264; verify:pr-local green (format/build/bundle-scan/RAG fixtures). No provider calls." }, { "date": "2026-07-20", - "ref": "Credentialed release-gate checkpoint closeout (workflow_dispatch on main `7ec25d9`; user-authorized ≤$10, single dispatch each)", + "ref": "Credentialed release-gate checkpoint closeout (workflow_dispatch on main `7ec25d9`; user-authorized \u2264$10, single dispatch each)", "head": "7ec25d9675dea13635fa4a895af88c93da694a42", "scope": "Credentialed half of the release gate: CI dispatch + live eval canary", - "outcome": "CI dispatch: 9/10 jobs green (unit coverage, build, Chromium production journeys, migration replay on local Supabase emulator, production-readiness CI-safe, policy self-tests, static/safety/scope). `release-browser-matrix` (WebKit/Firefox) CANCELLED twice by main-churn: ci.yml `concurrency: CI-${ref}, cancel-in-progress: true` kills in-flight dispatch runs on every main push and this repo merges every few minutes — livelock confirmed at the 2-attempt cap; WebKit/iOS verification remains outstanding with three human options (quiet-window dispatch, the weekly scheduled run, or a one-line dedicated concurrency group for the matrix job — operational-risk change, not applied). Eval canary: golden retrieval eval FAILED 4/36 (document_recall@5 0.944, ndcg@10 0.923, force_embedding_failure_count 0, no 429s — vector layer healthy, NOT the documented vector-ptsd transient class); the July 17 dispatch PASSED this step pre-#901, so the regression window implicates #901's deterministic semantic reranking (lithium-therapy-monitoring shows three unrelated documents with byte-identical rerank scores burying the lithium guideline; two other failures add fixture-vs-corpus identity components; answer-quality subset — the July 17 failure — never ran). NO canary re-run per plan (deterministic, not transient); retrieval is clinical-path and deferred to a human decision. Provider spend ≈ $1–2 (one canary run's embeddings); matrix/CI runs $0.", + "outcome": "CI dispatch: 9/10 jobs green (unit coverage, build, Chromium production journeys, migration replay on local Supabase emulator, production-readiness CI-safe, policy self-tests, static/safety/scope). `release-browser-matrix` (WebKit/Firefox) CANCELLED twice by main-churn: ci.yml `concurrency: CI-${ref}, cancel-in-progress: true` kills in-flight dispatch runs on every main push and this repo merges every few minutes \u2014 livelock confirmed at the 2-attempt cap; WebKit/iOS verification remains outstanding with three human options (quiet-window dispatch, the weekly scheduled run, or a one-line dedicated concurrency group for the matrix job \u2014 operational-risk change, not applied). Eval canary: golden retrieval eval FAILED 4/36 (document_recall@5 0.944, ndcg@10 0.923, force_embedding_failure_count 0, no 429s \u2014 vector layer healthy, NOT the documented vector-ptsd transient class); the July 17 dispatch PASSED this step pre-#901, so the regression window implicates #901's deterministic semantic reranking (lithium-therapy-monitoring shows three unrelated documents with byte-identical rerank scores burying the lithium guideline; two other failures add fixture-vs-corpus identity components; answer-quality subset \u2014 the July 17 failure \u2014 never ran). NO canary re-run per plan (deterministic, not transient); retrieval is clinical-path and deferred to a human decision. Provider spend \u2248 $1\u20132 (one canary run's embeddings); matrix/CI runs $0.", "checks": "actions_run_trigger dispatches + rerun_failed_jobs (attempt 2); job-level conclusions and log excerpts from runs 29675875530 (both attempts), 29675878737 (July 19 canary), and 29567502452 (July 17 baseline). No local provider calls; secrets never left GitHub Actions." }, { @@ -20618,7 +20617,7 @@ "ref": "origin/main PWA-surface review, window `ef042ca..e128384` (44+ commits; explicit user request) + phone install-sheet redesign (this branch, content commit d8d8c4a)", "head": "e1283846647b20cd49ca6ae6920a7c76f2b945d7", "scope": "PWA-version review of new progress + install-notification design elevation", - "outcome": "Sweep verdict (agent-verified): only #905/#897 (this program's own work) touched PWA surfaces in the window — sw.js CACHE_VERSION `2026-07-18-v1` and its offline.html binding, manifest (7 icons incl. monochrome; screenshots deliberately absent), icons route, kill-switch, and next.config headers all unchanged, so the privacy contract holds by construction. Geometric risk from five composer/dock-space reworks (#933 mobile-composer-reserve, #932, #930, #922, #899) probed live at 390×844: the non-install notice stack keeps correct clearance at rest (offline card bottom 744/844 with the 5.5rem gutter) and the stack's offset is now a custom property (`--pwa-notice-bottom-gap`) for one-line re-anchoring if composer geometry moves again. Redesign: install prompt + iOS hint present as a native bottom sheet on phones (full-bleed, flush bottom, grip bar matching #935's sheet language, real app icon identity via /icons/icon-192, Free/no-store meta row, two accent step chips for Share→Add to Home Screen as aria-hidden reinforcement of the unchanged accessible sentence); ≥640px keeps the #905 card/toast placements; region names, button names, and test-locked sentences unchanged.", + "outcome": "Sweep verdict (agent-verified): only #905/#897 (this program's own work) touched PWA surfaces in the window \u2014 sw.js CACHE_VERSION `2026-07-18-v1` and its offline.html binding, manifest (7 icons incl. monochrome; screenshots deliberately absent), icons route, kill-switch, and next.config headers all unchanged, so the privacy contract holds by construction. Geometric risk from five composer/dock-space reworks (#933 mobile-composer-reserve, #932, #930, #922, #899) probed live at 390\u00d7844: the non-install notice stack keeps correct clearance at rest (offline card bottom 744/844 with the 5.5rem gutter) and the stack's offset is now a custom property (`--pwa-notice-bottom-gap`) for one-line re-anchoring if composer geometry moves again. Redesign: install prompt + iOS hint present as a native bottom sheet on phones (full-bleed, flush bottom, grip bar matching #935's sheet language, real app icon identity via /icons/icon-192, Free/no-store meta row, two accent step chips for Share\u2192Add to Home Screen as aria-hidden reinforcement of the unchanged accessible sentence); \u2265640px keeps the #905 card/toast placements; region names, button names, and test-locked sentences unchanged.", "checks": "Focused vitest 56/56 across the four PWA suites; `verify:cheap` 2971/2975 (sole fail = known container-only pdf-extraction-budget artifact); `test:e2e:pwa` privacy/offline green (installability fail = known container `in-incognito` artifact); `verify:ui` 243 passed/2 failed (the two long-baselined container artifacts); production build + client-bundle secret scan + bundle budget within tolerance (1303.4 vs 1278.6 KiB baseline; sheet adds ~0 JS); visual evidence at 390 light/dark/iOS-hint + 768 + 1440 with bounding-box math (full-bleed flush-bottom on phone; card/toast intact above). No provider-backed checks run." }, { @@ -20655,7 +20654,7 @@ }, { "date": "2026-07-19", - "ref": "`origin/main` through PR #903 plus fixed 48-hour PR snapshot (`#689`–`#902`)", + "ref": "`origin/main` through PR #903 plus fixed 48-hour PR snapshot (`#689`\u2013`#902`)", "head": "4034d2e60ebb6616130ff17bf3cb69368f36f8f6", "scope": "whole-repository, all-lens regression and PR-activity review", "outcome": "Changes requested. No P0. Confirmed five P1 defects: stale publication approvals are not bound to reviewed document state; invalid supplied credentials can become anonymous uploads; pooled duplicate uploads expose another uploader's metadata; readiness is fail-open for database usability errors; and settings promise clinical tailoring/alerts with no consumers. Eighteen P2 findings cover semantic rerank effectiveness/privacy, summary prompt trust, PDF resource limits, cancellation, auth-state loss, public storage-path exposure, query validation, provider-boundary/CI/test gaps, factsheet/Therapy behavior, Therapy startup cost, and the PR #903 ledger's incorrect claim that PR #901 has zero unresolved threads. GitHub GraphQL still reports two current unresolved P2 threads on merged PR #901.", @@ -20682,7 +20681,7 @@ "ref": "claude/audit-recent-changes-kde66i (audit-remediation follow-up to the ef042cacd audit row)", "head": "see PR head", "scope": "remediation of the three 2026-07-19 audit findings", - "outcome": "Fixed all three findings from the 24-hour merged-window audit. (1) Inert settings honesty (P2): every preference the app does not yet consume — jurisdiction, population, answer style, landing, both home-content toggles, compact citations, and all three notification toggles — now renders an explicit \"Saved for later — not active yet\" marker in `settings-dialog.tsx`; the functional appearance/density/motion rows stay unmarked. Wiring the preferences into answer generation was deliberately NOT done here (clinical-behavior change requiring governance review); the new dom test documents the contract for flipping a control live. (2) Auth offline resolution (P2/P3): `resolveInitialAuthState` gains `verificationUnavailable`, set from `isAuthRetryableFetchError(getUser().error)`, so an unreachable auth server keeps the stored session signed in while a reachable server that rejects the token still resolves signed_out; server-side bearer validation is unchanged. (3) `/medications` redirect (P3): now preserves the sanitized q/focus/run search context with the same allowlist as the root legacy-mode redirect.", + "outcome": "Fixed all three findings from the 24-hour merged-window audit. (1) Inert settings honesty (P2): every preference the app does not yet consume \u2014 jurisdiction, population, answer style, landing, both home-content toggles, compact citations, and all three notification toggles \u2014 now renders an explicit \"Saved for later \u2014 not active yet\" marker in `settings-dialog.tsx`; the functional appearance/density/motion rows stay unmarked. Wiring the preferences into answer generation was deliberately NOT done here (clinical-behavior change requiring governance review); the new dom test documents the contract for flipping a control live. (2) Auth offline resolution (P2/P3): `resolveInitialAuthState` gains `verificationUnavailable`, set from `isAuthRetryableFetchError(getUser().error)`, so an unreachable auth server keeps the stored session signed in while a reachable server that rejects the token still resolves signed_out; server-side bearer validation is unchanged. (3) `/medications` redirect (P3): now preserves the sanitized q/focus/run search context with the same allowlist as the root legacy-mode redirect.", "checks": "Focused Vitest 30/30 across `settings-inert-preferences.dom` (new), `private-client-auth` (3 new cases), `audit-navigation-auth-regressions` (query-preservation case), `app-preferences`, and `site-map`. Full `verify:cheap` run recorded on the PR. No OpenAI, Supabase, deployment, or provider-backed check ran." }, { @@ -20690,15 +20689,15 @@ "ref": "claude/audit-recent-changes-kde66i (preference wiring + session-start hook follow-up to the #906 remediation)", "head": "see PR head", "scope": "wiring the wireable inert preferences live and fixing the stale-node_modules session-start gap", - "outcome": "Wired three of the seven remaining inert preferences into real behavior and removed their \"Saved for later\" markers: (1) Default landing view — `GlobalSearchShellClient` applies a one-shot `router.replace` to the saved landing mode (`search`→documents, `browse`→tools via `landingModeForPreference`) on a bare \"/\" load only; explicit mode/query/run params always win, and the dashboard's existing URL-sync effect performs the switch. (2) Recent searches on home — `AnswerEmptyState` now gates its recent-query chips on `showRecentOnHome`. (3) Compact citations — the answer source capsule drops its text label to icon+count when `compactCitations` is on, with the \"No direct source found\" warning explicitly exempted so compact mode can never hide a missing-source signal. Still marked inactive with reasons documented in the test contract: jurisdiction/population/answer-style (wiring them into answer generation is provider-eval-gated per the confirmation boundary), saved-protocols-on-home (no protocols module exists), and the three notification toggles (no delivery infrastructure). Separately, `.claude/hooks/session-start.sh` now stamps the `package-lock.json` sha256 into `node_modules/.session-start-lock-hash` after `npm ci` and reinstalls when the lockfile no longer matches, closing the stale-container gap that faked a typecheck regression during the 24h audit.", - "checks": "New `tests/answer-preferences.dom.test.tsx` (recents gate on/off, compact capsule display incl. the missing-source exemption, landing mapping) and the updated `settings-inert-preferences.dom` contract (3 rows moved inert→functional) pass with `app-preferences` and `private-client-auth`: 26/26 focused. Full typecheck, scoped zero-warning ESLint, and the full Vitest suite recorded on the PR; `bash -n` on the hook. `check:production-readiness` not run: no secrets in this container (documented demo-mode expectation) and no answer-generation, retrieval, or source-governance logic changed — the capsule change is presentational with the missing-source warning locked by test. No OpenAI, Supabase, deployment, or provider-backed check ran." + "outcome": "Wired three of the seven remaining inert preferences into real behavior and removed their \"Saved for later\" markers: (1) Default landing view \u2014 `GlobalSearchShellClient` applies a one-shot `router.replace` to the saved landing mode (`search`\u2192documents, `browse`\u2192tools via `landingModeForPreference`) on a bare \"/\" load only; explicit mode/query/run params always win, and the dashboard's existing URL-sync effect performs the switch. (2) Recent searches on home \u2014 `AnswerEmptyState` now gates its recent-query chips on `showRecentOnHome`. (3) Compact citations \u2014 the answer source capsule drops its text label to icon+count when `compactCitations` is on, with the \"No direct source found\" warning explicitly exempted so compact mode can never hide a missing-source signal. Still marked inactive with reasons documented in the test contract: jurisdiction/population/answer-style (wiring them into answer generation is provider-eval-gated per the confirmation boundary), saved-protocols-on-home (no protocols module exists), and the three notification toggles (no delivery infrastructure). Separately, `.claude/hooks/session-start.sh` now stamps the `package-lock.json` sha256 into `node_modules/.session-start-lock-hash` after `npm ci` and reinstalls when the lockfile no longer matches, closing the stale-container gap that faked a typecheck regression during the 24h audit.", + "checks": "New `tests/answer-preferences.dom.test.tsx` (recents gate on/off, compact capsule display incl. the missing-source exemption, landing mapping) and the updated `settings-inert-preferences.dom` contract (3 rows moved inert\u2192functional) pass with `app-preferences` and `private-client-auth`: 26/26 focused. Full typecheck, scoped zero-warning ESLint, and the full Vitest suite recorded on the PR; `bash -n` on the hook. `check:production-readiness` not run: no secrets in this container (documented demo-mode expectation) and no answer-generation, retrieval, or source-governance logic changed \u2014 the capsule change is presentational with the missing-source warning locked by test. No OpenAI, Supabase, deployment, or provider-backed check ran." }, { "date": "2026-07-19", "ref": "claude/clinical-kb-pwa-review-asi3wb (PR #905; commits b2afe66 visuals + 6531178 policy + this ledger follow-up)", "head": "6531178c1a3427dfd58c4bfcf8e29020c5731179", "scope": "PWA install/update notice redesign (all breakpoints) + review-follow-up policy fix", - "outcome": "Redesigned the five PWA notices (install, update, iOS hint, offline, restored) as glass lux cards: per-type semantic icon tiles, heading-ink titles, corner dismiss buttons, reduced-motion-safe 280ms entrance. Deliberate placement per screen size: phones keep the bottom card above the fixed composer (thumb zone, safe areas); ≥640px floats a 25rem card bottom-right; ≥1280px moves the stack to a top-right toast under the header (same 4.25rem+safe-area offset constant as the mode-menu popover) with the animation direction flipped. Copy, roles, and button names unchanged. Plus the outline-aware pr-policy section parser fix from the same-session review (see the review row above).", + "outcome": "Redesigned the five PWA notices (install, update, iOS hint, offline, restored) as glass lux cards: per-type semantic icon tiles, heading-ink titles, corner dismiss buttons, reduced-motion-safe 280ms entrance. Deliberate placement per screen size: phones keep the bottom card above the fixed composer (thumb zone, safe areas); \u2265640px floats a 25rem card bottom-right; \u22651280px moves the stack to a top-right toast under the header (same 4.25rem+safe-area offset constant as the mode-menu popover) with the animation direction flipped. Copy, roles, and button names unchanged. Plus the outline-aware pr-policy section parser fix from the same-session review (see the review row above).", "checks": "Focused vitest pwa-lifecycle.dom 9/9 + pwa-manifest 8/8; `check:pr-policy` self-test green incl. new sub-heading case; `verify:cheap` 2828/2831 (sole fail = known container-only pdf-extraction-budget artifact); `test:e2e:pwa` privacy/offline green (installability fail = known container `in-incognito` artifact); `verify:ui` 236 passed/2 failed (the two long-baselined container artifacts); production build + client-bundle secret scan + bundle budget within tolerance (1293.4 vs 1278.6 KiB baseline); visual evidence at 390/768/1440 light+dark+offline in session scratchpad. Dev caveat recorded: Turbopack persistent `.next` cache served stale globals.css across restarts twice; fixed by setting the cache aside. No provider-backed checks run." }, { @@ -20722,7 +20721,7 @@ "ref": "cursor/hide-favourites-guest-mode-a26d (PR #934)", "head": "04192653", "scope": "Final Favourites total guest-blackout review + merge readiness", - "outcome": "No P0/P1. Fixed residual P2s: rankToolRecords now fails closed by default; mode/chip filters stop double-ORing demoMode; gated deep-link mode chrome falls back to Answer; MasterSearchHeader mode-menu DOM tests added. Guest discovery closed for mode menu, sidebar, cross-mode chips, Tools Saved, universal tools ranking, also-matches, prefetch. Intentional residual: direct /favourites signup gate; mockup routes. PR body appears overwritten by unrelated Sync PR policy content — agent posted corrective comment (403 on body edit).", + "outcome": "No P0/P1. Fixed residual P2s: rankToolRecords now fails closed by default; mode/chip filters stop double-ORing demoMode; gated deep-link mode chrome falls back to Answer; MasterSearchHeader mode-menu DOM tests added. Guest discovery closed for mode menu, sidebar, cross-mode chips, Tools Saved, universal tools ranking, also-matches, prefetch. Intentional residual: direct /favourites signup gate; mockup routes. PR body appears overwritten by unrelated Sync PR policy content \u2014 agent posted corrective comment (403 on body edit).", "checks": "Focused Vitest 37/37; verify:cheap green; verify:pr-local green (build + client-secret scan + RAG fixtures); browser guest Tools/sidebar/favourites proof earlier. No OpenAI/Supabase writes." }, { @@ -20783,18 +20782,18 @@ }, { "date": "2026-07-19", - "ref": "origin/main 24-hour merged window (d1937d78e..ef042cacd, ~30 PRs incl. #853/#859/#861/#865/#868/#871–#874/#879/#885–#888/#890–#894/#896)", + "ref": "origin/main 24-hour merged window (d1937d78e..ef042cacd, ~30 PRs incl. #853/#859/#861/#865/#868/#871\u2013#874/#879/#885\u2013#888/#890\u2013#894/#896)", "head": "ef042cacd", "scope": "integrated post-merge regression audit of the full 24h window (code review + design/performance/defect angles)", - "outcome": "No P0/P1 regression found at the merged tip. One confirmed P2: the new settings surface (`use-app-preferences.ts` + `settings-dialog.tsx`) presents jurisdiction, population, answer-style, landing, home-content, compact-citations, and all notification preferences as live controls, but no consumer reads them — only density/motion (html attributes + globals.css) and theme are functional; a clinician selecting \"Conservative\" answer style reasonably but wrongly believes generation changed. One plausible P2/P3: `AuthProvider.initializeSession` now requires a live `getUser()` round-trip, so a transient network failure on load resolves a valid stored session to signed_out (INITIAL_SESSION replay is also skipped); the deliberate stale/tampered-token defense does not distinguish retryable network errors. One P3: `/medications` legacy redirect drops the query string while `/applications` and `/differentials/presentations` preserve theirs. Cleared after inspection: worker image-placement dedupe (key symmetric on both sides), title-word purge/scope migration (matches its replayed review), RPC-layer-only cancellation consolidation (intentional per PR #861), services route-chunk fix intact with no other heavy client value-imports (type-only imports verified), forced-colors ButtonFace/ButtonText flip, codex-autofix/pr-policy workflow changes conform to AGENTS.md (pin retained, rename-aware routing, workflow_sha checkout), audit-metadata allowlist exhaustive over the closed AuditAction union, answer-stream merged abort signals. Environment note (not a repo defect): the session-start hook skips `npm install` when node_modules exists, so this window's dependency bumps left the container stale and `verify:cheap` failed at typecheck until `npm ci`; the hook should compare a lockfile hash.", - "checks": "`npm ci` then typecheck clean and full Vitest 2828 passed / 1 failed / 2 skipped — the sole failure is the long-baselined container-only `tests/pdf-extraction-budget.test.ts` artifact (hosted-CI-green through #826/#835/#872/#890). First `verify:cheap` run passed every static guard (runtime, actions-pin, ci-scope, ci-triage, pr-policy, sitemap, brand, type-scale, icon-scale, function-grants, owner-scope, lint) before the stale-deps typecheck stop. No OpenAI, Supabase, deployment, or provider-backed check ran." + "outcome": "No P0/P1 regression found at the merged tip. One confirmed P2: the new settings surface (`use-app-preferences.ts` + `settings-dialog.tsx`) presents jurisdiction, population, answer-style, landing, home-content, compact-citations, and all notification preferences as live controls, but no consumer reads them \u2014 only density/motion (html attributes + globals.css) and theme are functional; a clinician selecting \"Conservative\" answer style reasonably but wrongly believes generation changed. One plausible P2/P3: `AuthProvider.initializeSession` now requires a live `getUser()` round-trip, so a transient network failure on load resolves a valid stored session to signed_out (INITIAL_SESSION replay is also skipped); the deliberate stale/tampered-token defense does not distinguish retryable network errors. One P3: `/medications` legacy redirect drops the query string while `/applications` and `/differentials/presentations` preserve theirs. Cleared after inspection: worker image-placement dedupe (key symmetric on both sides), title-word purge/scope migration (matches its replayed review), RPC-layer-only cancellation consolidation (intentional per PR #861), services route-chunk fix intact with no other heavy client value-imports (type-only imports verified), forced-colors ButtonFace/ButtonText flip, codex-autofix/pr-policy workflow changes conform to AGENTS.md (pin retained, rename-aware routing, workflow_sha checkout), audit-metadata allowlist exhaustive over the closed AuditAction union, answer-stream merged abort signals. Environment note (not a repo defect): the session-start hook skips `npm install` when node_modules exists, so this window's dependency bumps left the container stale and `verify:cheap` failed at typecheck until `npm ci`; the hook should compare a lockfile hash.", + "checks": "`npm ci` then typecheck clean and full Vitest 2828 passed / 1 failed / 2 skipped \u2014 the sole failure is the long-baselined container-only `tests/pdf-extraction-budget.test.ts` artifact (hosted-CI-green through #826/#835/#872/#890). First `verify:cheap` run passed every static guard (runtime, actions-pin, ci-scope, ci-triage, pr-policy, sitemap, brand, type-scale, icon-scale, function-grants, owner-scope, lint) before the stale-deps typecheck stop. No OpenAI, Supabase, deployment, or provider-backed check ran." }, { "date": "2026-07-19", "ref": "origin/main foreign merges post-#896 landing (541da7b #871 remediation + f4557ca #892 policy parsing; explicit user review request)", "head": "ef042ca6a34d33862936e77e4b71068978382c1e", "scope": "Bug review of recent main changes (diff-review protocol)", - "outcome": "One P2 confirmed and fixed in PR #905: #892's widened heading matcher ended a required PR-body section at ANY next heading, so `###` sub-structure inside `## Verification` truncated the section and false-rejected valid bodies (fail-closed; repo template unaffected; repro via direct evaluatePullRequestPolicy probe old-vs-new). No P0/P1. Cleared after verification: `src/lib/client-env.ts` (no env leakage; production demote-to-demo removal deliberate and fail-safe — upload gating still locked via canUsePrivateApis), applications/medications redirect routes (fixed targets, 307+HEAD alias, no open-redirect/header-injection), test infra (no weakened assertions; route-coverage spec added to all projects), and the three biggest #871 UI diffs read inline (ClinicalDashboard upload tablist roving-tabindex + hydration-safe useSyncExternalStore role switch; visual-evidence unavailable-source rows became real non-interactive elements; favourites library demo-gates prototype items with sound menu keyboard nav). Residual (report-only): pr-policy `section()` remains fence-unaware (headings inside fenced code can satisfy required-section checks — pre-existing class, author-controlled attestation surface); dev-only Turbopack persistent-cache staleness served an old globals.css compile across restarts twice this session (fixed by setting `.next` aside).", + "outcome": "One P2 confirmed and fixed in PR #905: #892's widened heading matcher ended a required PR-body section at ANY next heading, so `###` sub-structure inside `## Verification` truncated the section and false-rejected valid bodies (fail-closed; repo template unaffected; repro via direct evaluatePullRequestPolicy probe old-vs-new). No P0/P1. Cleared after verification: `src/lib/client-env.ts` (no env leakage; production demote-to-demo removal deliberate and fail-safe \u2014 upload gating still locked via canUsePrivateApis), applications/medications redirect routes (fixed targets, 307+HEAD alias, no open-redirect/header-injection), test infra (no weakened assertions; route-coverage spec added to all projects), and the three biggest #871 UI diffs read inline (ClinicalDashboard upload tablist roving-tabindex + hydration-safe useSyncExternalStore role switch; visual-evidence unavailable-source rows became real non-interactive elements; favourites library demo-gates prototype items with sound menu keyboard nav). Residual (report-only): pr-policy `section()` remains fence-unaware (headings inside fenced code can satisfy required-section checks \u2014 pre-existing class, author-controlled attestation surface); dev-only Turbopack persistent-cache staleness served an old globals.css compile across restarts twice this session (fixed by setting `.next` aside).", "checks": "Reviewer fan-out: general lane completed with concrete probes (pr-policy self-test, node repro on old parser from f4557ca^, adversarial body probes); UI lane agent lost to session limit and re-done inline on the three biggest diffs, leaning on the merged tree's green gates (verify:ui 236-passed run in this session covers #871's own new specs). No provider-backed checks run." }, { @@ -20802,7 +20801,7 @@ "ref": "PR #935 / `cursor/mobile-mode-menu-sheet-efee`", "head": "87d4a479cd320220c91eba5c91e253e843dcc98f", "scope": "final Mode phone-sheet review + merge-readiness", - "outcome": "No remaining high-confidence P0/P1. Fixed residual P2 Sheet backdrop drag-dismiss (gesture must start on dimmed area). Phone ≤639px Mode menu uses bottom Sheet; desktop absolute dropdown/keyboard/blur contracts preserved. Python PDF extractor resolves python/python3 and process-group kills reliably. Clinical governance: UI + fail-closed extractor binary resolution only; no answer/source/privacy surface change. Safe to merge after hosted required checks green on this HEAD.", + "outcome": "No remaining high-confidence P0/P1. Fixed residual P2 Sheet backdrop drag-dismiss (gesture must start on dimmed area). Phone \u2264639px Mode menu uses bottom Sheet; desktop absolute dropdown/keyboard/blur contracts preserved. Python PDF extractor resolves python/python3 and process-group kills reliably. Clinical governance: UI + fail-closed extractor binary resolution only; no answer/source/privacy surface change. Safe to merge after hosted required checks green on this HEAD.", "checks": "`verify:cheap` 2954 passed; Mode Playwright 5/5 (phone sheet/backdrop/desktop/keyboard/a11y); `check:production-readiness:ci` READY; prettier format check fixed for CI Static; no OpenAI/live Supabase writes; full `verify:ui`/`verify:release` not required beyond Mode proofs." }, { @@ -20810,7 +20809,7 @@ "ref": "PR #938 / `cursor/fix-differentials-results-top-d760`", "head": "2df3181859345339d777ac814908b3095cea36fd", "scope": "ModeHomeMain contentAlign fix for differentials mobile clipping", - "outcome": "No high-confidence P0–P2. Fix correctly introduces exclusive `contentAlign` (`center` | `start` | `startOnPhone`), migrates therapy/formulation/specifiers off broken className justify overrides, top-aligns differentials results via `autoRunSearch`, and guards with static + Playwright fold assertions. Residual: DSM/forms/services still default-center; justify-strip leaves variant prefixes; Playwright `0.55*vh` upper bound may flake if header band grows; Chip compact overrides still dual-utility via `cn()`.", + "outcome": "No high-confidence P0\u2013P2. Fix correctly introduces exclusive `contentAlign` (`center` | `start` | `startOnPhone`), migrates therapy/formulation/specifiers off broken className justify overrides, top-aligns differentials results via `autoRunSearch`, and guards with static + Playwright fold assertions. Residual: DSM/forms/services still default-center; justify-strip leaves variant prefixes; Playwright `0.55*vh` upper bound may flake if header band grows; Chip compact overrides still dual-utility via `cn()`.", "checks": "Static diff vs `origin/main`; inventory of all `ModeHomeMain` call sites; justify-strip regex probe; `npx vitest run tests/mode-home-main-align.test.ts` 4/4. Not run: Playwright/`verify:ui` (browser), `verify:cheap`/`verify:pr-local`, provider-backed checks." }, { @@ -20818,7 +20817,7 @@ "ref": "PR #938 / `cursor/fix-differentials-results-top-d760`", "head": "3a775d4fd9a44e97388c0041cb421f06265a7721", "scope": "fresh final review (user-requested) + main sync (#937)", - "outcome": "No high-confidence P0–P2. Product delta unchanged vs prior merge-ready head; #933 reserve + #938 contentAlign remain complementary. Merged `origin/main` (#937) cleanly. Follow-up: dropped `PR_POLICY_BODY.md` when syncing #942 so this PR does not reintroduce the stale template; live PR description already correct. Residual: required human approving review.", + "outcome": "No high-confidence P0\u2013P2. Product delta unchanged vs prior merge-ready head; #933 reserve + #938 contentAlign remain complementary. Merged `origin/main` (#937) cleanly. Follow-up: dropped `PR_POLICY_BODY.md` when syncing #942 so this PR does not reintroduce the stale template; live PR description already correct. Residual: required human approving review.", "checks": "Local: align+composer-reserve Vitest 9/9; focused Chromium overlap+fold+compare 14/14. Hosted CI green on prior tip." }, { @@ -20826,7 +20825,7 @@ "ref": "PR #938 / `cursor/fix-differentials-results-top-d760`", "head": "74c370d81342dd729398dc2b40ba3158ea30f1db", "scope": "follow-up review + residual polish (policy body, align API, UI flake)", - "outcome": "Prior residuals closed: `PR_POLICY_BODY.md` rewritten for #938 (Sync PR policy body was overwriting with stale #932 text); `withoutJustifyUtilities` strips prefixed utilities; Chip uses exclusive `density` type scale; DSM/forms/services use `startOnPhone`; Best Answer fold bound uses header+240px; `ui-overlap` waits for a single `header#search`. No remaining high-confidence P0–P2 in the ModeHomeMain/differentials mobile scope.", + "outcome": "Prior residuals closed: `PR_POLICY_BODY.md` rewritten for #938 (Sync PR policy body was overwriting with stale #932 text); `withoutJustifyUtilities` strips prefixed utilities; Chip uses exclusive `density` type scale; DSM/forms/services use `startOnPhone`; Best Answer fold bound uses header+240px; `ui-overlap` waits for a single `header#search`. No remaining high-confidence P0\u2013P2 in the ModeHomeMain/differentials mobile scope.", "checks": "`npx vitest run tests/mode-home-main-align.test.ts` 5/5; Prettier on touched files. Playwright focused rerun and hosted Production UI expected after push." }, { @@ -20834,7 +20833,7 @@ "ref": "PR #938 / `cursor/fix-differentials-results-top-d760`", "head": "b62d414ca9001fbc1ac0d50b315450e107751d67", "scope": "merge-readiness after policy + hosted UI", - "outcome": "No remaining high-confidence P0–P2. PR description sync + `verify:ui` evidence keep PR policy green; hosted Production UI / PR required green on exact head.", + "outcome": "No remaining high-confidence P0\u2013P2. PR description sync + `verify:ui` evidence keep PR policy green; hosted Production UI / PR required green on exact head.", "checks": "Local: align Vitest 5/5; ui-overlap 12/12; differentials fold Playwright 1/1. Hosted: Production UI, Advisory UI, Static, Unit, Build, PR policy, PR required, Sync PR policy body all pass." }, { @@ -20842,7 +20841,7 @@ "ref": "PR #938 / `cursor/fix-differentials-results-top-d760`", "head": "e177b5e877aa2f834b3a601fa37679fa3e77b0e3", "scope": "merge main (#933) + post-merge revalidation", - "outcome": "Merged `origin/main` (Safari edge-to-edge #933) with ledger conflict resolved by keeping both review rows. No product conflicts; `contentAlign`, Chip density, and Best Answer fold asserts intact. No new P0–P2. Still blocked only by required human approving review; squash auto-merge remains enabled.", + "outcome": "Merged `origin/main` (Safari edge-to-edge #933) with ledger conflict resolved by keeping both review rows. No product conflicts; `contentAlign`, Chip density, and Best Answer fold asserts intact. No new P0\u2013P2. Still blocked only by required human approving review; squash auto-merge remains enabled.", "checks": "Local after merge: align+composer-reserve Vitest 9/9; focused Chromium dock-hide + fold + compare-dock 3/3. Hosted on merge head: Production UI, PR required, Unit, Static, Build, PR policy all SUCCESS." }, { @@ -20850,7 +20849,7 @@ "ref": "PR #938 / `cursor/fix-differentials-results-top-d760`", "head": "efe472fac3489473e2465da2d92980508c20fd81", "scope": "merge main (#934 favourites) + #941 sync", - "outcome": "Merged favourites guest-gate (#934) then Specifiers results UI (#941). Product conflicts none: kept `contentAlign=\"startOnPhone\"` on Specifiers home while taking #941 results chrome. `ui-overlap` gotoHome wait conflict resolved with settled single-header short-circuit. No new P0–P2. Residual: human approving review required for squash auto-merge.", + "outcome": "Merged favourites guest-gate (#934) then Specifiers results UI (#941). Product conflicts none: kept `contentAlign=\"startOnPhone\"` on Specifiers home while taking #941 results chrome. `ui-overlap` gotoHome wait conflict resolved with settled single-header short-circuit. No new P0\u2013P2. Residual: human approving review required for squash auto-merge.", "checks": "Local: align Vitest; favourites+app-modes+tools 42 tests; Chromium ui-overlap+ui-tools 95/95; verify:cheap unit stage green. Hosted CI green on pre-#941 tip; re-running after this merge." }, { @@ -20858,7 +20857,7 @@ "ref": "PR #938 / `cursor/fix-differentials-results-top-d760`", "head": "f6682cc08eb0fcc0b8dd170d5c9358b3fedc0c0d", "scope": "final meticulous review + safe-merge handoff", - "outcome": "No high-confidence P0–P2. Forms/services now centre when unseeded/loading and use `startOnPhone` only when seeded (avoids sparse empty homes). CodeRabbit risk-line comment dispositioned as stale #932 body confusion. Residual: branch protection still requires a human approving review before squash auto-merge can land.", + "outcome": "No high-confidence P0\u2013P2. Forms/services now centre when unseeded/loading and use `startOnPhone` only when seeded (avoids sparse empty homes). CodeRabbit risk-line comment dispositioned as stale #932 body confusion. Residual: branch protection still requires a human approving review before squash auto-merge can land.", "checks": "Local: align Vitest 5/5; focused Chromium overlap+fold 13/13; verify:cheap/pr-local unit stages 2953/2955 with only known container `pdf-extraction-budget` Python ENOENT failures; format/lint/typecheck/RAG fixtures pass; local `next build` blocked by running ensure server (hosted Build green). Hosted exact-head: Production UI, PR required, Unit, Static, Build, PR policy all SUCCESS. Enabled squash `--auto` merge." }, { @@ -20874,8 +20873,8 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (Phase 3, PR #872, final reviewed head ba46c1581a3c4e87d5d5989f3eb77483c9aa8aa5)", "head": "ba46c1581a3c4e87d5d5989f3eb77483c9aa8aa5", "scope": "PWA offline-page design upgrade (plan Phase 3)", - "outcome": "Rebuilt the `public/offline.html` visual shell on mirrored Clinical White / Aegean Graphite tokens (each value annotated with its source token): pure-white canvas, aligned text/border/hover values, system UI font stack, and the clinical-accent focus ring replacing the off-contract amber. Privacy copy, structure, forced-colors behavior, safe-area insets, and target sizes unchanged. `CACHE_VERSION` bumped to the new unique `2026-07-18-v1` with the offline.html sha256 pairing updated — the Phase 1 binding guard exercised for real and enforced the paired move. A transient typecheck failure from stale `.next/dev` route types (cross-branch dev-server state) self-resolved after server regeneration; nothing was deleted.", - "checks": "Focused Vitest 55/55 including the binding guard on the new pairing. `verify:cheap` 2778 passed/1 failed and `verify:pr-local` unit stage identical — the lone failure is the known container-only `pdf-extraction-budget` artifact (clean-main baselined; hosted CI green on #826/#835). `test:e2e:pwa`: the cold-offline journey rendered and asserted the redesigned page through the new-version worker; sole installability error remains the container `in-incognito` artifact. `verify:ui` 219 passed/2 failed — the same two clean-main-baselined container artifacts, no new failures. Build/bundle stages deferred to the blocking hosted CI Build job. No provider-backed checks run." + "outcome": "Rebuilt the `public/offline.html` visual shell on mirrored Clinical White / Aegean Graphite tokens (each value annotated with its source token): pure-white canvas, aligned text/border/hover values, system UI font stack, and the clinical-accent focus ring replacing the off-contract amber. Privacy copy, structure, forced-colors behavior, safe-area insets, and target sizes unchanged. `CACHE_VERSION` bumped to the new unique `2026-07-18-v1` with the offline.html sha256 pairing updated \u2014 the Phase 1 binding guard exercised for real and enforced the paired move. A transient typecheck failure from stale `.next/dev` route types (cross-branch dev-server state) self-resolved after server regeneration; nothing was deleted.", + "checks": "Focused Vitest 55/55 including the binding guard on the new pairing. `verify:cheap` 2778 passed/1 failed and `verify:pr-local` unit stage identical \u2014 the lone failure is the known container-only `pdf-extraction-budget` artifact (clean-main baselined; hosted CI green on #826/#835). `test:e2e:pwa`: the cold-offline journey rendered and asserted the redesigned page through the new-version worker; sole installability error remains the container `in-incognito` artifact. `verify:ui` 219 passed/2 failed \u2014 the same two clean-main-baselined container artifacts, no new failures. Build/bundle stages deferred to the blocking hosted CI Build job. No provider-backed checks run." }, { "date": "2026-07-18", @@ -20891,14 +20890,14 @@ "head": "d46f381ac27b53b1bd5ac0ef77962fbd48cf3aa7", "scope": "PWA manifest and install-UX polish (plan Phase 2)", "outcome": "Implemented Phase 2 of the PWA plan with cache semantics untouched: `launch_handler` navigate-existing/auto and `display_override` standalone/minimal-ui in `manifest.ts`; `monochrome-192/512` icon variants rendered as a white alpha-only silhouette from the shared brand mark via `BRAND_MONOCHROME`; a one-time iOS/iPadOS Add to Home Screen hint in `pwa-lifecycle.tsx` (30-day dismissal key, never in standalone, timer-deferred eligibility for the set-state-in-effect lint rule). Docs Installability section updated; manifest screenshots remain deferred per the production-capture precondition. Phase 2 re-scout confirmed zero upstream drift before implementation.", - "checks": "Focused Vitest 55/55. `verify:cheap` 2773 passed/1 failed and `verify:pr-local` unit stage identical — the lone failure is the known container-only `pdf-extraction-budget` artifact (clean-main baselined; hosted CI green on #826). `test:e2e:pwa`: privacy journey passed; icon probes validated both new monochrome PNGs; sole installability error remains the container `in-incognito` artifact. `verify:ui` 219 passed/2 failed — exactly the two clean-main-baselined container artifacts, no new failures. `format:check` clean. Build/bundle stages deferred to the blocking hosted CI Build job on PR #835. No provider-backed checks run." + "checks": "Focused Vitest 55/55. `verify:cheap` 2773 passed/1 failed and `verify:pr-local` unit stage identical \u2014 the lone failure is the known container-only `pdf-extraction-budget` artifact (clean-main baselined; hosted CI green on #826). `test:e2e:pwa`: privacy journey passed; icon probes validated both new monochrome PNGs; sole installability error remains the container `in-incognito` artifact. `verify:ui` 219 passed/2 failed \u2014 exactly the two clean-main-baselined container artifacts, no new failures. `format:check` clean. Build/bundle stages deferred to the blocking hosted CI Build job on PR #835. No provider-backed checks run." }, { "date": "2026-07-18", - "ref": "claude/clinical-kb-pwa-review-asi3wb (PR #890, plan Phase 4; single-batch implementation+ledger commit — Phase 3 landed as squash 44a4c511bc1381168474794d6f89273564659ead)", + "ref": "claude/clinical-kb-pwa-review-asi3wb (PR #890, plan Phase 4; single-batch implementation+ledger commit \u2014 Phase 3 landed as squash 44a4c511bc1381168474794d6f89273564659ead)", "head": "ceabc04d75fd0cea2a120d504418d44edd704bfb", "scope": "App-wide performance pass: audit-then-fix + budget ratchet (plan Phase 4)", - "outcome": "Audit on post-#872 main: enforced gzip budget +3.13% over the 1,363,382-byte baseline; analyzer treemap showed pdfjs-dist (123 KB) and cross-mode-differentials data (121 KB) already correctly lazy, and disproved the suspected forms-catalog dashboard leak (type-only import). Confirmed one real defect: the 143-line `/services` client home page value-imported `defaultServiceSlug` from `@/lib/services`, compiling the ~915 KB services snapshot (~100 KB gzip) into its route chunk. Fixed by computing the slug in the server page (`src/app/services/page.tsx`) and passing it as a prop; the client component builds its task cards from the prop. Measured result: budget swung from +3.13% to −3.97%; baseline ratcheted down 1,363,382 → 1,309,286 bytes gzip so CI locks the win. pdfjs/differentials/#718 paths deliberately untouched per audit rules. Two transient `.next/dev` generated-type corruptions from the long-lived dev server were resolved by stopping the server and setting the generated dir aside (reversible); nothing hand-deleted.", + "outcome": "Audit on post-#872 main: enforced gzip budget +3.13% over the 1,363,382-byte baseline; analyzer treemap showed pdfjs-dist (123 KB) and cross-mode-differentials data (121 KB) already correctly lazy, and disproved the suspected forms-catalog dashboard leak (type-only import). Confirmed one real defect: the 143-line `/services` client home page value-imported `defaultServiceSlug` from `@/lib/services`, compiling the ~915 KB services snapshot (~100 KB gzip) into its route chunk. Fixed by computing the slug in the server page (`src/app/services/page.tsx`) and passing it as a prop; the client component builds its task cards from the prop. Measured result: budget swung from +3.13% to \u22123.97%; baseline ratcheted down 1,363,382 \u2192 1,309,286 bytes gzip so CI locks the win. pdfjs/differentials/#718 paths deliberately untouched per audit rules. Two transient `.next/dev` generated-type corruptions from the long-lived dev server were resolved by stopping the server and setting the generated dir aside (reversible); nothing hand-deleted.", "checks": "Build + `check:bundle-budget --json` before/after (artifacts in session scratchpad); `check:bundle-budget -- --update` for the ratchet; `npm run test` 2789 passed/1 failed (known container-only `pdf-extraction-budget` artifact, hosted-CI-green through #826/#835/#872); `verify:cheap` green to the same artifact; `verify:ui` 219 passed/2 failed (the two long-established container artifacts; ui-tools spec covering the services surface passed); `verify:pr-local` unit stage identical; typecheck/lint/format clean. Lighthouse not run (dev-server churn; bundle evidence sufficed for this fix set). No provider-backed checks run." }, { @@ -20906,7 +20905,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (PR #896, plan Phase 5; content commit + this ledger follow-up)", "head": "a6c2b4e92374e9002fb00c547eb5677d01ce538c", "scope": "Design-polish sweep: audit-then-fix (plan Phase 5, final phase)", - "outcome": "Audit on post-#890 main: three strict design guards clean; full re-run of the 07-token-adoption-audit grep method shows all July 3 debt resolved (M1–M3 done, L4 reduced to the deliberate theme-aware `ring-white/N dark:ring-white/10` glass idiom, L5/L7 gone; production hex all legitimate print/brand/console/comment classes); 43-capture live sweep across 15 routes × desktop/phone + 320px spots + dark/reduced-motion/forced-colors spots found 0 overflow and 0 console errors. Three defects found and fixed: (1) forced-colors solid-button labels rendered as blank Canvas-on-Canvas backplate boxes (axe-invisible) — command controls flattened to the native HCM ButtonFace/ButtonText pairing and accent glyph tokens flipped to ButtonText inside the existing forced-colors block, regression-locked by a new ui-accessibility test; (2) tools desktop 6-up quick-action rail truncated card titles at 1440×1000 — card metrics tightened, all six titles verified unclipped; (3) privacy page rendered \"systemand\" from a JSX newline-adjacent-to-tag drop — explicit space, locked by a privacy-ui assertion. Dated July 18 run appended to docs/redesign/07-token-adoption-audit.md (archived design-qa.md not resurrected).", + "outcome": "Audit on post-#890 main: three strict design guards clean; full re-run of the 07-token-adoption-audit grep method shows all July 3 debt resolved (M1\u2013M3 done, L4 reduced to the deliberate theme-aware `ring-white/N dark:ring-white/10` glass idiom, L5/L7 gone; production hex all legitimate print/brand/console/comment classes); 43-capture live sweep across 15 routes \u00d7 desktop/phone + 320px spots + dark/reduced-motion/forced-colors spots found 0 overflow and 0 console errors. Three defects found and fixed: (1) forced-colors solid-button labels rendered as blank Canvas-on-Canvas backplate boxes (axe-invisible) \u2014 command controls flattened to the native HCM ButtonFace/ButtonText pairing and accent glyph tokens flipped to ButtonText inside the existing forced-colors block, regression-locked by a new ui-accessibility test; (2) tools desktop 6-up quick-action rail truncated card titles at 1440\u00d71000 \u2014 card metrics tightened, all six titles verified unclipped; (3) privacy page rendered \"systemand\" from a JSX newline-adjacent-to-tag drop \u2014 explicit space, locked by a privacy-ui assertion. Dated July 18 run appended to docs/redesign/07-token-adoption-audit.md (archived design-qa.md not resurrected).", "checks": "Guards + focused vitest 14/14; `verify:cheap` chain green to the known container-only pdf-extraction-budget artifact (2806/2809); `verify:ui` 220 passed/2 failed (the two long-baselined container artifacts, hosted-CI-green through #826/#835/#872/#890); `test:e2e:accessibility` 8/8 incl. the new forced-colors token test; production build + client-bundle secret scan passed; `check:bundle-budget` within tolerance vs the Phase 4 ratchet (1290.6 vs 1278.6 KiB baseline); `verify:pr-local` runtime/format/lint/typecheck/build/rag-fixtures green with the same sole unit-suite artifact. `verify:release` not run (provider-backed; awaits explicit confirmation). No provider-backed checks run." }, { @@ -20954,7 +20953,7 @@ "ref": "PR #861 / codex/design-audit-main-safe-20260720-final", "head": "d8c1916ac (functional head 593d5aa00 + current-main merge)", "scope": "design-audit/search cancellation merge review", - "outcome": "Fixed unsupported Forms pathway claims, propagated cancellation through every retrieval RPC, removed duplicate favourites “Also matches” results, and resolved all four review threads. Merged as `3b2dd9ef76ff1c8c099fc1972065628d23b853b1`; exact `origin/main` commit and tree content were verified after merge.", + "outcome": "Fixed unsupported Forms pathway claims, propagated cancellation through every retrieval RPC, removed duplicate favourites \u201cAlso matches\u201d results, and resolved all four review threads. Merged as `3b2dd9ef76ff1c8c099fc1972065628d23b853b1`; exact `origin/main` commit and tree content were verified after merge.", "checks": "Exact-head hosted Static PR checks, Unit coverage, Build, Safety and config checks, Production UI, Advisory UI, Migration replay, PR required, PR policy, Semgrep, Gitleaks, and GitGuardian checks passed. No Supabase, OpenAI, or other product-provider call ran." }, { @@ -20983,7 +20982,7 @@ }, { "date": "2026-07-18", - "ref": "PR batch screenshot queue → #808 / cursor/pr-queue-land-bfe7", + "ref": "PR batch screenshot queue \u2192 #808 / cursor/pr-queue-land-bfe7", "head": "3b54a785c7c6073024b6bae0182b6a9321154595", "scope": "open-PR review + merge babysit", "outcome": "Consolidated unique remaining work from screenshot PRs onto current main via #808 (Also matches placement, factsheets, audit metadata minimize with numeric storageRemoved, answer-progress UI gate, global-error role=alert). Superseded already-landed #800/#799/#801/#802 (via #798/#804). Closed conflicted/failing design-audit duplicates #789/#790/#803/#806/#807/#788 and older duplicates #748/#749/#751 without replaying Production UI regressions.", @@ -20991,23 +20990,23 @@ }, { "date": "2026-07-18", - "ref": "PR batch screenshot queue → #808/#812/#814", + "ref": "PR batch screenshot queue \u2192 #808/#812/#814", "head": "44555ab9e414f615981eb444f46a62333c28ec18", "scope": "open-PR review + merge babysit", - "outcome": "Screenshot PRs #784–#789 closed as superseded. Unique residual work landed via #808 and #812. Design-audit/Playwright stack landed via #814 after Production UI fixes (Clinical Guide H1, service mocks, reduced-motion dock asserts), presentations empty-query fallback, and CodeRabbit thread resolution (RightRail remount, IS DISTINCT FROM, no-op dropped trigram migration). #783 already merged. Communication #17 inaccessible from this token.", + "outcome": "Screenshot PRs #784\u2013#789 closed as superseded. Unique residual work landed via #808 and #812. Design-audit/Playwright stack landed via #814 after Production UI fixes (Clinical Guide H1, service mocks, reduced-motion dock asserts), presentations empty-query fallback, and CodeRabbit thread resolution (RightRail remount, IS DISTINCT FROM, no-op dropped trigram migration). #783 already merged. Communication #17 inaccessible from this token.", "checks": "Hosted #808/#812/#814 required checks green including Production UI; migration replay green on #814. No OpenAI/live Supabase writes." }, { "date": "2026-07-18", - "ref": "PR batch screenshot queue → #853 / cursor/pr-queue-land-3084", + "ref": "PR batch screenshot queue \u2192 #853 / cursor/pr-queue-land-3084", "head": "11ec0122f (tip of cursor/pr-queue-land-3084)", "scope": "open-PR review + merge babysit", - "outcome": "Reviewed screenshot PRs #833/#837/#845–#852 + Communication #19. #852/#848 already merged. Closed superseded/unsafe: #833/#837 (empty vs main), #845 (clinical-search over-expand; fixed in #853), #846/#847/#849 (Production UI red design-audit dupes), #850 (CONFLICTING), #851 (schema-test regressions), #726 (CONFLICTING CodeRabbit UTG). Unique safe fix landed in #853: agitation chart expansion without bare table/management over-trigger. Communication #19 inaccessible (repo not resolvable).", + "outcome": "Reviewed screenshot PRs #833/#837/#845\u2013#852 + Communication #19. #852/#848 already merged. Closed superseded/unsafe: #833/#837 (empty vs main), #845 (clinical-search over-expand; fixed in #853), #846/#847/#849 (Production UI red design-audit dupes), #850 (CONFLICTING), #851 (schema-test regressions), #726 (CONFLICTING CodeRabbit UTG). Unique safe fix landed in #853: agitation chart expansion without bare table/management over-trigger. Communication #19 inaccessible (repo not resolvable).", "checks": "Focused Vitest clinical-search 42/42. Local verify:cheap unit suite hit pre-existing pdf-extraction-budget failures also on main (2 tests). Hosted #853 required checks green (Static/Unit/Build/PR required/policy/Semgrep/Gitleaks/GitGuardian). Squash-merged to main. Also closed follow-on dupes #854 (same failing tip as #851) and #855 (Clinical KB H1 reverts #814 Clinical Guide contract; Static/PR policy red). Communication #19 inaccessible. No OpenAI/live Supabase writes." }, { "date": "2026-07-18", - "ref": "PR batch screenshot queue → #883–#888 / #891", + "ref": "PR batch screenshot queue \u2192 #883\u2013#888 / #891", "head": "8b0a600209 (main tip after #887)", "scope": "open-PR review + merge babysit", "outcome": "Reviewed and land-safe-merged screenshot PRs. Merged #888 (worker placement dedupe), #891 (PR policy `github.workflow_sha` checkout superseding incorrect #884 `base.sha`), #886 (mobile differentials FAB), #885 (Compare selected href; closed duplicate #883/#882), #887 (Therapy mode-home align + nested-main landmark fix). Closed superseded #884/#883/#882/#881/#877/#875. Fixed PR-policy bodies (Clinical KB governance checkbox), resolved Codex/CodeRabbit threads, Prettier on therapy landmark files, and re-synced branches through main between merges. No high-confidence residual P0-P1 on landed heads.", @@ -21298,8 +21297,8 @@ "ref": "HEAD detached 570e6ba56 + WIP tree", "head": "570e6ba56ae60bea56a32801b9cc96c5a8dfde4f", "scope": "thorough multi-lens review: WIP RAG/schema + clinical design/UI + architecture/bug-hunt", - "outcome": "Changes requested: no P0. Confirmed P1s in WIP — registryCorpusDetailHref typecheck break; ChunkLoadCache error/null poisoning across parallel hydrations; registry cleanup `::uuid` cast abort; corrector GIN unused by query path; new table-facts trgm index expression mismatch vs trgm_matches. Design: production clinical shell stays token/a11y-aligned; favourites nav multi-gradient bars and mockup hex drift fight clinical density. Residual: concurrent cache race, SECURITY DEFINER revoke gaps, schema/migration lifecycle drift, accidental pnpm-lock.yaml.", - "checks": "`npm run typecheck` (red: registry link callers + stale .next apps types); static SQL/expr/diff review; architecture + bug-hunt agents; design-system grep (tokens, reduced-motion, forced-colors). Not run: vitest, verify:*, ensure/browser screenshots, live Supabase/OpenAI. frontend-ui-reviewer subagent blocked by usage limit — design pass done inline." + "outcome": "Changes requested: no P0. Confirmed P1s in WIP \u2014 registryCorpusDetailHref typecheck break; ChunkLoadCache error/null poisoning across parallel hydrations; registry cleanup `::uuid` cast abort; corrector GIN unused by query path; new table-facts trgm index expression mismatch vs trgm_matches. Design: production clinical shell stays token/a11y-aligned; favourites nav multi-gradient bars and mockup hex drift fight clinical density. Residual: concurrent cache race, SECURITY DEFINER revoke gaps, schema/migration lifecycle drift, accidental pnpm-lock.yaml.", + "checks": "`npm run typecheck` (red: registry link callers + stale .next apps types); static SQL/expr/diff review; architecture + bug-hunt agents; design-system grep (tokens, reduced-motion, forced-colors). Not run: vitest, verify:*, ensure/browser screenshots, live Supabase/OpenAI. frontend-ui-reviewer subagent blocked by usage limit \u2014 design pass done inline." }, { "date": "2026-07-15", @@ -21402,7 +21401,7 @@ "ref": "claude/codebase-review-ade6ed", "head": "a96b8ffafb88da22f667b41edf01b215866dde32", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21442,7 +21441,7 @@ "ref": "claude/document-page-redesign-7dd487", "head": "c2cfd57b4e7ec602d96e7f042eb60ff0b10a9e8e", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21450,7 +21449,7 @@ "ref": "claude/document-viewer-redesign-55b68b", "head": "0dbd83c73d2783cbe8e8d00bf04c9947a33518fc", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21482,7 +21481,7 @@ "ref": "claude/medication-alerts-database-cb8o83", "head": "a0ca895015df8ebe6ae57fa8a811a1fbb240e623", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21506,7 +21505,7 @@ "ref": "claude/perf-r2-bundle-hygiene", "head": "95ce39f7715caeadc8197c35c2c41500183a715e", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion (user decision): redundant perf-r2 duplicate; unmerged batch-endpoint work preserved in retained claude/perf-r2-plan-cache-migration. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion (user decision): redundant perf-r2 duplicate; unmerged batch-endpoint work preserved in retained claude/perf-r2-plan-cache-migration. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21514,7 +21513,7 @@ "ref": "claude/perf-r2-hot-path", "head": "843dcf8d287950b2ddf86a121701dfbb95ac86c0", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion (user decision): redundant perf-r2 duplicate; unmerged batch-endpoint work preserved in retained claude/perf-r2-plan-cache-migration. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion (user decision): redundant perf-r2 duplicate; unmerged batch-endpoint work preserved in retained claude/perf-r2-plan-cache-migration. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21522,7 +21521,7 @@ "ref": "claude/perf-r2-network-caching", "head": "424ae6b045d9ec38443292a1569de4b04d6a295d", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion (user decision): redundant perf-r2 duplicate; unmerged batch-endpoint work preserved in retained claude/perf-r2-plan-cache-migration. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion (user decision): redundant perf-r2 duplicate; unmerged batch-endpoint work preserved in retained claude/perf-r2-plan-cache-migration. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21530,7 +21529,7 @@ "ref": "claude/perf-r2-payload-trim", "head": "5a6ce71153198c746fab96859d5895374ac05bb9", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion (user decision): redundant perf-r2 duplicate; unmerged batch-endpoint work preserved in retained claude/perf-r2-plan-cache-migration. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion (user decision): redundant perf-r2 duplicate; unmerged batch-endpoint work preserved in retained claude/perf-r2-plan-cache-migration. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21546,7 +21545,7 @@ "ref": "claude/pr-672-specifiers-formulation-3n123f", "head": "059398c962711f57e5f9ee7c6b4783066cd6718f", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21642,7 +21641,7 @@ "ref": "claude/site-performance-speed-61d154", "head": "cb0bcf35498385bca1180462c8ab79b6f8293708", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion (user decision): redundant perf-r2 duplicate; unmerged batch-endpoint work preserved in retained claude/perf-r2-plan-cache-migration. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion (user decision): redundant perf-r2 duplicate; unmerged batch-endpoint work preserved in retained claude/perf-r2-plan-cache-migration. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21658,7 +21657,7 @@ "ref": "claude/therapy-compass-pages-rz0m5l", "head": "5a89a521add5a02dc4f6dd640b393c5bdd690183", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21690,7 +21689,7 @@ "ref": "codex/dsm-diagnosis-mode", "head": "f6cda83ca6aed3a24d999ef4ccd38bff167d4788", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21706,7 +21705,7 @@ "ref": "codex/dsm-main-integration-20260714", "head": "9e013894b2e45d6be39af1ef4593a14604886476", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21754,7 +21753,7 @@ "ref": "codex/formulation-workspace", "head": "ce6baa31ffe9647d736a18e95f9d95a95bda313c", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21786,7 +21785,7 @@ "ref": "codex/live-migration-history-alignment", "head": "c9853c7acdc80e3c33354c3b1a32e5df2682f521", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21794,7 +21793,7 @@ "ref": "codex/offline-retrieval-signal-followup", "head": "ef448e212d12c1cadbeb3ea053ca6639e6f0ada4", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21826,7 +21825,7 @@ "ref": "codex/please-thoroughly-review-this-repo", "head": "47e850ee93dd5281c792eb60618f98ba2e972b8e", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21842,7 +21841,7 @@ "ref": "codex/rag-canary-recovery", "head": "d6bd7fa7c0b9b29e9b7eddfd28e0478e042a0455", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21898,7 +21897,7 @@ "ref": "codex/release-blocker-remediation", "head": "8a7ec72b22bff98b8d4b31d533ae9a0738dee071", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21914,7 +21913,7 @@ "ref": "codex/repository-review-remediation", "head": "29c598cd2db4fc9c00ed56f60e8ef2adb969cccf", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21938,7 +21937,7 @@ "ref": "codex/universal-search-domain-exclusions", "head": "6b2c4ffbc81b9a35746ee2fa8795c73a2f65d4fc", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21954,7 +21953,7 @@ "ref": "codex/universal-search-mode-ranking", "head": "6a0c37f8e3b4b23fa52c49fec28dcbc8d635b80f", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21962,7 +21961,7 @@ "ref": "copilot/29199485110", "head": "4e09b838bda6a774f067b8e13717af2103502857", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21970,7 +21969,7 @@ "ref": "copilot/29202241308-fix-database-issue", "head": "29db1aa1b29a812bf4c7eb7af5ea33371f086157", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21978,7 +21977,7 @@ "ref": "copilot/database-ci-setup", "head": "45fa392a24987e4b596d80fc81528912e62d95c9", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21986,7 +21985,7 @@ "ref": "copilot/fix", "head": "060b2cd9c0cb38fa0cb0521ce3f67ead13a9ab87", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21994,7 +21993,7 @@ "ref": "copilot/fix-961c247e-5acb-45db-b4ed-62fcf97681cd", "head": "b6097f0fbf19f82527ea95a385efb2ca7b8ec794", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22002,7 +22001,7 @@ "ref": "copilot/fix-accessibility-test-timeouts", "head": "17e11e45835510d2a43b8ea6fdfeed10df11e0d7", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22010,7 +22009,7 @@ "ref": "copilot/fix-again", "head": "0b2d29a143926279b327ff302c2de3d5fe0edbc5", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22018,7 +22017,7 @@ "ref": "copilot/fix-another-one", "head": "f1864308e0b287bb83b2a13daca4c3aa2ab95a3e", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22026,7 +22025,7 @@ "ref": "copilot/fix-barriers", "head": "8711ee2b15c3b9a1a0e8444ba2ee799d6c5e6ab7", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22034,7 +22033,7 @@ "ref": "copilot/fix-ci-error", "head": "e6e735d2668f7383acc45bdb7cc7dc183e7a73a8", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22042,7 +22041,7 @@ "ref": "copilot/fix-ci-issue", "head": "a95b282433e6b01bdd6444eb9b2de9148daf2363", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22050,7 +22049,7 @@ "ref": "copilot/fix-ci-issues", "head": "5f1c6f64a544705df9df970e09da3b85f0d90efa", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22058,7 +22057,7 @@ "ref": "copilot/fix-ci-test-to-pass", "head": "660e5789f56a0a54f68616392fb456e1ad10e48c", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22066,7 +22065,7 @@ "ref": "copilot/fix-database-action-error", "head": "7ff6c547e55100d7dfff912530e006f0a5ee70a2", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22074,7 +22073,7 @@ "ref": "copilot/fix-database-action-issue", "head": "b367aeb084a60fc46d3e4e8d3b318491a1530ac6", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22082,7 +22081,7 @@ "ref": "copilot/fix-database-action-run-issues", "head": "de36fd3ef8aa101e75a22fab8ff15940bb241e00", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22090,7 +22089,7 @@ "ref": "copilot/fix-database-actions", "head": "50cf0744df83708405d0bd215e22f19dc1f27815", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22098,7 +22097,7 @@ "ref": "copilot/fix-failing-ci", "head": "d248707d09f62bb153d0eece69b4f7f4e8aeb7dc", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22106,7 +22105,7 @@ "ref": "copilot/fix-failing-ci-again", "head": "28dacd7f19320bcbf2b03e5e40c7e97fc46a80cd", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22114,7 +22113,7 @@ "ref": "copilot/fix-failing-ci-another-one", "head": "59207b23fe88a23b0e2f3a6d7f1a288e0cca5132", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22122,7 +22121,7 @@ "ref": "copilot/fix-failing-ci-one-more-time", "head": "00b61456b3f4fd528b24476865fde3b046b105ea", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22130,7 +22129,7 @@ "ref": "copilot/fix-failing-ci-test", "head": "1de23d35e534c33cf444bc5e81e60c7384e8d072", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22138,7 +22137,7 @@ "ref": "copilot/fix-failing-ci-yet-again", "head": "8f2928b9dc925ac9ccc31e413ab422d2ffa77118", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22146,7 +22145,7 @@ "ref": "copilot/fix-issue-in-database-action", "head": "82c0e87224880ccbeee39f4101e98cf29683f74f", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22154,7 +22153,7 @@ "ref": "copilot/fix-issue-with-database-connection", "head": "67f5bb2744939922ceb280fab8785ee0259b26f2", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22162,7 +22161,7 @@ "ref": "copilot/fix-one-more-time", "head": "2682cbade791fc07f09d23fa11908eead223d3c7", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22170,7 +22169,7 @@ "ref": "copilot/fix-please-work", "head": "2f55346e72555500d17a08be02e6b649daa1a7cc", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22178,7 +22177,7 @@ "ref": "copilot/fix-yet-again", "head": "c57bc8af5570a5fc69fa0f804f67cfa98df76b89", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22186,7 +22185,7 @@ "ref": "copilot/rerun-all-ci-again", "head": "4615e39557112515cc9e4938fb5dd397f19ff70d", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22202,7 +22201,7 @@ "ref": "cursor/fix-pr654-ci-53b4", "head": "9f880853ea7d268186d982f4623b71f46e77d3dc", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22218,7 +22217,7 @@ "ref": "fix/accessibility-remaining-findings", "head": "9f880853ea7d268186d982f4623b71f46e77d3dc", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22234,15 +22233,15 @@ "ref": "HEAD (detached) 570e6ba56ae60bea56a32801b9cc96c5a8dfde4f", "head": "570e6ba56ae60bea56a32801b9cc96c5a8dfde4f", "scope": "clinical governance + RAG full-repo audit (source governance/citations, answer verification/clinical safety, privacy/query-privacy/private-search-scope, generation failure modes/degradation, retrieval/ranking/selection, ingestion/OCR index quality)", - "outcome": "No high-confidence P0/P1. Fail-closed governance chokepoint (`buildGovernedAnswerClientResponse`) applies to both `/api/answer` and `/api/answer/stream`; numeric/quote/citation verification, prompt-injection neutralization, owner-scope tenancy, and query/answer redaction all conservative. Two P3 observations: (1) `secondStageScore` demotion penalties can be floored away by `Math.max(hybrid_score, boosted)` at the tail of the list (rag.ts:663); (2) `outdatedPenalty` default-ON uses governance metadata to weight ranking (eval-gated, demotion-only) — in tension with the \"no governance weighting\" principle but conservative. D4/D5 (#649) levers verified default-OFF with tests.", + "outcome": "No high-confidence P0/P1. Fail-closed governance chokepoint (`buildGovernedAnswerClientResponse`) applies to both `/api/answer` and `/api/answer/stream`; numeric/quote/citation verification, prompt-injection neutralization, owner-scope tenancy, and query/answer redaction all conservative. Two P3 observations: (1) `secondStageScore` demotion penalties can be floored away by `Math.max(hybrid_score, boosted)` at the tail of the list (rag.ts:663); (2) `outdatedPenalty` default-ON uses governance metadata to weight ranking (eval-gated, demotion-only) \u2014 in tension with the \"no governance weighting\" principle but conservative. D4/D5 (#649) levers verified default-OFF with tests.", "checks": "Pure review, no mutations except this ledger append. Offline: focused Vitest governance/verification/privacy/scope suites 79/79 + 98/98 passed. Provider-backed (Supabase/OpenAI), browser, release, and live retrieval-quality checks not run (confirmation boundary)." }, { "date": "2026-07-14", "ref": "HEAD (detached) 570e6ba56ae60bea56a32801b9cc96c5a8dfde4f", "head": "570e6ba56ae60bea56a32801b9cc96c5a8dfde4f", - "scope": "frontend/UI/accessibility audit — global-search-shell, master-search-header, composer, answer surfaces, document viewer, clinical dashboard modules; design-token usage, reduced-motion/forced-colors, icon aria, focus traps, composer/header placement", - "outcome": "No P0. P2: (1) `aria-describedby`+`aria-hidden=\"true\"` conflict in `mode-action-popup.tsx:622,651` makes menu descriptions invisible to AT; (2) ~25 dynamic `` render sites missing `aria-hidden` across dashboard modules — ESLint `require-lucide-icon-aria` rule gap for LucideIcon-typed variables; (3) Mode menu (`role=\"menu\"` in header) does not close on Tab — keyboard users can Tab away from an open menu without dismissing it; (4) No live region on streaming `NaturalLanguageAnswer` — screen reader users not notified of incremental answer content. P3: (5) `--surface-glass`/`--panel-gloss` not remapped in `@media (forced-colors: active)` block — image-lightbox and PDF toolbar control bars could become invisible in high-contrast; (6) `bg-black/45` on Sheet backdrop instead of `var(--overlay-backdrop)` token; (7) `active:scale-[0.99]` on action-popup buttons without `motion-safe:` — still fires as a visual jump under reduced-motion; (8) Microsoft/Google brand hex squares not `forced-color-adjust:none` — lose brand identity in high-contrast mode.", + "scope": "frontend/UI/accessibility audit \u2014 global-search-shell, master-search-header, composer, answer surfaces, document viewer, clinical dashboard modules; design-token usage, reduced-motion/forced-colors, icon aria, focus traps, composer/header placement", + "outcome": "No P0. P2: (1) `aria-describedby`+`aria-hidden=\"true\"` conflict in `mode-action-popup.tsx:622,651` makes menu descriptions invisible to AT; (2) ~25 dynamic `` render sites missing `aria-hidden` across dashboard modules \u2014 ESLint `require-lucide-icon-aria` rule gap for LucideIcon-typed variables; (3) Mode menu (`role=\"menu\"` in header) does not close on Tab \u2014 keyboard users can Tab away from an open menu without dismissing it; (4) No live region on streaming `NaturalLanguageAnswer` \u2014 screen reader users not notified of incremental answer content. P3: (5) `--surface-glass`/`--panel-gloss` not remapped in `@media (forced-colors: active)` block \u2014 image-lightbox and PDF toolbar control bars could become invisible in high-contrast; (6) `bg-black/45` on Sheet backdrop instead of `var(--overlay-backdrop)` token; (7) `active:scale-[0.99]` on action-popup buttons without `motion-safe:` \u2014 still fires as a visual jump under reduced-motion; (8) Microsoft/Google brand hex squares not `forced-color-adjust:none` \u2014 lose brand identity in high-contrast mode.", "checks": "Pure static review, no mutations. Files read: `master-search-header.tsx`, `global-search-shell.tsx`, `globals.css`, `sheet.tsx`, `mode-action-popup.tsx`, `image-lightbox.tsx`, `answer-content.tsx`, `ClinicalDashboard.tsx` (partial), `use-dismissable-layer.ts`, `layout.tsx`, `eslint-rules/require-lucide-icon-aria.mjs`, `ui-accessibility.spec.ts`, `process-hardening.md`. Browser/live checks not run (confirmation boundary)." }, { @@ -22250,7 +22249,7 @@ "ref": "HEAD (detached) 570e6ba56ae60bea56a32801b9cc96c5a8dfde4f", "head": "570e6ba56ae60bea56a32801b9cc96c5a8dfde4f", "scope": "full repo-structure audit (broken imports, dead files, redundant config, module dependency, structural debt)", - "outcome": "No P0/P1. P2: `RAG_TEXT_WEAK_OR_RELAXATION=true` in `.env.example` contradicts `default(\"false\")` in `env.ts` (process-hardening hardened this to off); `reindex-eval-gate.ts` (488 lines) has no production importer — test-only orphan; `bundle-budget.json` still has `enforce: false` + `totalGzipBytes: null` after first production build window passed. P3: `client-env.ts` duplicates `isLocalNoAuthMode`/`publicUploadsEnabled` from `env.ts` using raw `process.env` (intentional server-only split, but divergent implementations); `OPENAI_PRICE_*`, `SPEND_ALERT_DAILY_USD` env vars undocumented in `.env.example`; `rag.ts` → extracted-module architecture still has acknowledged runtime back-edges in `rag-extractive-answer` but no import cycles detected by `architecture-boundaries.test.ts`; several `mockup`-named component files not removed from `src/components/` (production use gated via `mockupsEnabled()`).", + "outcome": "No P0/P1. P2: `RAG_TEXT_WEAK_OR_RELAXATION=true` in `.env.example` contradicts `default(\"false\")` in `env.ts` (process-hardening hardened this to off); `reindex-eval-gate.ts` (488 lines) has no production importer \u2014 test-only orphan; `bundle-budget.json` still has `enforce: false` + `totalGzipBytes: null` after first production build window passed. P3: `client-env.ts` duplicates `isLocalNoAuthMode`/`publicUploadsEnabled` from `env.ts` using raw `process.env` (intentional server-only split, but divergent implementations); `OPENAI_PRICE_*`, `SPEND_ALERT_DAILY_USD` env vars undocumented in `.env.example`; `rag.ts` \u2192 extracted-module architecture still has acknowledged runtime back-edges in `rag-extractive-answer` but no import cycles detected by `architecture-boundaries.test.ts`; several `mockup`-named component files not removed from `src/components/` (production use gated via `mockupsEnabled()`).", "checks": "`npm run verify:cheap` green (2,290 passed/2 skipped, 0 lint errors, typecheck clean, sitemap aligned, type-scale 0 hits, runtime Node 24/npm 11). `npm run check:env-parity` clean. `npm run docs:check-scripts` passed 266 refs. Architecture-boundaries suite (no cycles, server modules isolated, scripts not imported). Provider-backed (Supabase/OpenAI), browser, release, and live-eval checks not run (confirmation boundary)." }, { @@ -22258,7 +22257,7 @@ "ref": "HEAD (detached) 570e6ba56ae60bea56a32801b9cc96c5a8dfde4f", "head": "570e6ba56ae60bea56a32801b9cc96c5a8dfde4f", "scope": "RAG retrieval/ranking/selection/answer-generation audit (fresh scoped pass; PR #649 D4/D5 governance levers safe-by-default focus, token/effort waste, provider routing)", - "outcome": "No P0/P1. Both #649 levers verified safe-by-default and fail-safe: D4 `unknownCurrentnessPenalty` default 0 (no-op, clamped non-negative, activated only via `RAG_RANKING_CONFIG`); D5 `NEXT_PUBLIC_RAG_TRUST_CAP_ALL_CLAIMS` unset=false (only tightens display trust high→medium, never exposes more; `NEXT_PUBLIC` correct as `buildAnswerRenderModel` runs client-side in `ClinicalDashboard.tsx`). Reasoning-effort defaults correct (`OPENAI_STRONG_REASONING_EFFORT`=medium, fast=low; `strongReasoningEffortForQueryClass` never raises, caps routine at medium, keeps dose/threshold at configured). Provider mode default `auto`. P3 (reaffirmed): (1) `Math.max(hybrid_score, boosted)` floor at rag.ts:663 can nullify demotion penalties (outdated/unknown/poor/lowIndex) at the list tail, making D4 partly inert when activated; (2) `document_status` defaults to `\"unknown\"` (source-metadata.ts:34) for unenriched docs, so activating D4 penalizes the corpus-wide fallback status, not a curated signal — same mechanism that dropped selection doc-recall@5 1.0→0.76 (retrieval-selection.ts:340) — eval gate is the safeguard.", + "outcome": "No P0/P1. Both #649 levers verified safe-by-default and fail-safe: D4 `unknownCurrentnessPenalty` default 0 (no-op, clamped non-negative, activated only via `RAG_RANKING_CONFIG`); D5 `NEXT_PUBLIC_RAG_TRUST_CAP_ALL_CLAIMS` unset=false (only tightens display trust high\u2192medium, never exposes more; `NEXT_PUBLIC` correct as `buildAnswerRenderModel` runs client-side in `ClinicalDashboard.tsx`). Reasoning-effort defaults correct (`OPENAI_STRONG_REASONING_EFFORT`=medium, fast=low; `strongReasoningEffortForQueryClass` never raises, caps routine at medium, keeps dose/threshold at configured). Provider mode default `auto`. P3 (reaffirmed): (1) `Math.max(hybrid_score, boosted)` floor at rag.ts:663 can nullify demotion penalties (outdated/unknown/poor/lowIndex) at the list tail, making D4 partly inert when activated; (2) `document_status` defaults to `\"unknown\"` (source-metadata.ts:34) for unenriched docs, so activating D4 penalizes the corpus-wide fallback status, not a curated signal \u2014 same mechanism that dropped selection doc-recall@5 1.0\u21920.76 (retrieval-selection.ts:340) \u2014 eval gate is the safeguard.", "checks": "Pure review, no mutations except this ledger append. Offline focused Vitest: answer-render-policy + ranking-config + answer-responsiveness-gate 54/54 passed. Provider-backed (Supabase/OpenAI), `eval:retrieval:quality`, browser, and release checks not run (confirmation boundary)." }, { @@ -22610,8 +22609,8 @@ "ref": "PR #655 / codex/release-blocker-remediation", "head": "3ed3a7a2df37d7d15143ab7606e5748ac7ecca09 + reviewed follow-up diff", "scope": "offline dose-route latency follow-up", - "outcome": "The next isolated timeout was a short IM/PO agitation question receiving the same blanket ten-term AND expansion. Agitation dose/route retrieval now keeps only the dose and route signals present in the question; the exact case retrieves its expected source and five citations in 1.54 seconds without a model. All remaining RAG cases 23–44 passed individually, so no further deadline crash remains.", - "checks": "Focused clinical-search/retrieval Vitest 111/111; scoped ESLint; Prettier; `git diff --check`; live provider-free case 22 passed; live provider-free cases 23–44 passed individually." + "outcome": "The next isolated timeout was a short IM/PO agitation question receiving the same blanket ten-term AND expansion. Agitation dose/route retrieval now keeps only the dose and route signals present in the question; the exact case retrieves its expected source and five citations in 1.54 seconds without a model. All remaining RAG cases 23\u201344 passed individually, so no further deadline crash remains.", + "checks": "Focused clinical-search/retrieval Vitest 111/111; scoped ESLint; Prettier; `git diff --check`; live provider-free case 22 passed; live provider-free cases 23\u201344 passed individually." }, { "date": "2026-07-14", @@ -24218,8 +24217,8 @@ "ref": "main (PR #570 squash, glass header)", "head": "cc6bfc1c80902ca3c91e5ba2ebe78a80f3fd9e14", "scope": "post-merge review: CSS/visual/a11y/perf + logic/regression", - "outcome": "No P0/P1. P2s confirmed and fixed in follow-up: build pipeline dropped ALL hand-authored backdrop-filter declarations (manual -webkit- duplicates confused Lightning CSS — header scrim, bottom dock, and composer pill were tint-only in every engine); scrim retuned to carry the bar's frost alone (header backdrop-root removed) with masks fading to true zero; private-scope alert made sticky inside main (was scroll-away in non-answer modes); scroll-hide reporter reset on breakpoint-gate change; non-forced fallback backgrounds layered to preserve the utility-wins contract.", - "checks": "Ran custom Playwright probe (`node scratchpad/probe-blur.mjs`, Chromium 390x844): baseline showed `getComputedStyle(.edge-glass-header-backdrop).backdropFilter === \"none\"` on all three passes, after fix `blur(14px)/blur(20px)/blur(26px)` — passed; Ran `node scripts/run-playwright.mjs tests/ui-smoke.spec.ts --project=chromium -g \"glass header|collapse hide|private-scope alert|phone (short|long) answer stays\"`: 6/6 passed; Ran `node scripts/run-playwright.mjs tests/ui-smoke.spec.ts --project=chromium` (full file): 71 passed, 4 failed (pre-existing `/privacy` heading test, fails identically on clean main); Ran `npm run verify:cheap`: exit 0 (1935 unit tests passed); Ran `npm run format:check`: passed; Not run: WebKit/Safari real-device check (no WebKit runner in this environment — served client chunk verified to pair `-webkit-backdrop-filter` with each declaration for Safari <= 17)" + "outcome": "No P0/P1. P2s confirmed and fixed in follow-up: build pipeline dropped ALL hand-authored backdrop-filter declarations (manual -webkit- duplicates confused Lightning CSS \u2014 header scrim, bottom dock, and composer pill were tint-only in every engine); scrim retuned to carry the bar's frost alone (header backdrop-root removed) with masks fading to true zero; private-scope alert made sticky inside main (was scroll-away in non-answer modes); scroll-hide reporter reset on breakpoint-gate change; non-forced fallback backgrounds layered to preserve the utility-wins contract.", + "checks": "Ran custom Playwright probe (`node scratchpad/probe-blur.mjs`, Chromium 390x844): baseline showed `getComputedStyle(.edge-glass-header-backdrop).backdropFilter === \"none\"` on all three passes, after fix `blur(14px)/blur(20px)/blur(26px)` \u2014 passed; Ran `node scripts/run-playwright.mjs tests/ui-smoke.spec.ts --project=chromium -g \"glass header|collapse hide|private-scope alert|phone (short|long) answer stays\"`: 6/6 passed; Ran `node scripts/run-playwright.mjs tests/ui-smoke.spec.ts --project=chromium` (full file): 71 passed, 4 failed (pre-existing `/privacy` heading test, fails identically on clean main); Ran `npm run verify:cheap`: exit 0 (1935 unit tests passed); Ran `npm run format:check`: passed; Not run: WebKit/Safari real-device check (no WebKit runner in this environment \u2014 served client chunk verified to pair `-webkit-backdrop-filter` with each declaration for Safari <= 17)" }, { "date": "2026-07-13", @@ -25402,7 +25401,7 @@ "ref": "claude/mobile-search-bar-fix (PR #456)", "head": "b73196c2e2e4a536804cdcdb50879c29e2c582c5", "scope": "PR required-testing review", - "outcome": "All 4 Advisory UI regression failures confirmed PR-caused via A/B against pre-merge main (01f2cee0d): the 640px mode-home query moved the phone composer out of the hero, contradicting the design tests; residual ≥640px vanish remained when the slot never mounts. PR merged (b32c17b34) before the rework landed; follow-up fix shipped on `claude/mode-home-composer-hero-fix` (0px hero query restored, portal-outcome inline fallback, new `@critical` composer-presence test). Also found: main CI red on every push — missing `RAG_QUERY_HASH_SECRET` secret fails the deployment boot smoke and skips `release-browser-matrix`; owner adding the secret.", + "outcome": "All 4 Advisory UI regression failures confirmed PR-caused via A/B against pre-merge main (01f2cee0d): the 640px mode-home query moved the phone composer out of the hero, contradicting the design tests; residual \u2265640px vanish remained when the slot never mounts. PR merged (b32c17b34) before the rework landed; follow-up fix shipped on `claude/mode-home-composer-hero-fix` (0px hero query restored, portal-outcome inline fallback, new `@critical` composer-presence test). Also found: main CI red on every push \u2014 missing `RAG_QUERY_HASH_SECRET` secret fails the deployment boot smoke and skips `release-browser-matrix`; owner adding the secret.", "checks": "Local chromium A/B (PR head 4/5 fail vs baseline product-pass); rework targeted run 6/6 pass incl. new `@critical`; `npm run typecheck`; `npm run lint`; focused Prettier check" }, { @@ -25631,8 +25630,8 @@ } ], "counts": { - "records": 2661, - "refs": 1626 + "records": 2657, + "refs": 1623 } } } diff --git a/docs/codebase-index.md b/docs/codebase-index.md index dacecbf9f0..e4d8ed9ceb 100644 --- a/docs/codebase-index.md +++ b/docs/codebase-index.md @@ -64,7 +64,8 @@ Smaller top-level directories that are easy to miss: - **PWA:** `docs/pwa.md` — install assets, privacy-first service worker/offline shell, lifecycle, security, and verification - **Home:** `src/app/(search-app)/page.tsx` — dashboard rendered by shell - **Dashboard:** `src/components/ClinicalDashboard.tsx` + `src/components/clinical-dashboard/` -- **Modes (15):** `src/lib/app-modes.ts` — answer, documents, services, forms, favourites, differentials, DSM-5 diagnosis, specifiers, formulation, prescribing, tools, calculators, Therapy, Factsheets, Dictionary +- **Modes (16):** `src/lib/app-modes.ts` — answer, documents, services, forms, favourites, differentials, DSM-5 diagnosis, specifiers, formulation, prescribing, tools, calculators, Therapy, Factsheets, Dictionary, Sources + - **Sources catalogue:** `/sources` provides a read-only, quality-banded catalogue with Topics, Publishers, Method and source-detail traceability; `/dictionary/sources` redirects into its Dictionary-filtered view. - **Therapy review disclosure.** Therapy was `devOnly` while its 205-record catalogue awaited qualified-clinician sign-off. That hid the mode from production navigation, 404'd `/therapy-compass` in the route layout, and made `therapyRecordsForEnvironment` filter every record out — so all 205 detail/brief/sheet routes and every universal-search therapy hit 404'd for real users while working locally. The owner's decision (2026-08-19) replaced the gate with disclosure: reachability is no longer conditioned on review status anywhere, and the caveat is stated instead — catalogue-wide by `TherapyReviewNotice` above the Therapy home hero (counts from the generated `THERAPY_CATALOGUE_SUMMARY.needsReviewCount`, kept in step by the index generator's check mode), and per record by the `reviewStatus` badge on every card, detail page, brief, sheet, comparison, pathway, and universal-search result. `therapyNeedsReview` survives as the label source only. Pinned by `tests/app-modes.test.ts` (reachability), `tests/therapy-review-regressions.test.ts` (the notice and the per-record badges), and `tests/therapy-pr-unblocking-contract.test.ts` (the retired `PLAYWRIGHT_OFFLINE_MODE` bypass that existed only to reach the gated route). ### Product pages (`src/app/`) @@ -89,7 +90,8 @@ Smaller top-level directories that are easy to miss: | `/dsm`, `/dsm/search`, `/dsm/compare`, `/dsm/diagnoses/[slug]` | `src/app/(search-app)/dsm/` | | `/documents/search`, `/source`, `/evidence`, `/[id]` | `src/app/(search-app)/documents/` | | `/factsheets`, `/factsheets/search`, `/factsheets/topics`, `/factsheets/[slug]` | `src/app/(search-app)/factsheets/` | -| `/dictionary`, Terms (`/search`, one catalogue — `/browse` redirects to it), Topics, Definition, Compare, Sources | `src/app/(search-app)/dictionary/` | +| `/dictionary`, Terms (`/search`, one catalogue — `/browse` redirects to it), Topics, Definition, Compare | `src/app/(search-app)/dictionary/` | +| `/sources`, `/sources/topics`, `/sources/publishers`, `/sources/method`, `/sources/[sourceId]` | `src/app/(search-app)/sources/` | | `/favourites` | `src/app/(search-app)/favourites/page.tsx` | | `/forms`, `/forms/[slug]` | `src/app/(search-app)/forms/` | | `/medications`, `/medications/[slug]` | `src/app/(search-app)/medications/` | @@ -166,11 +168,12 @@ domain-extracted directory; imported as `@/lib/rag/rag*`). Other modules below r ### Source governance and metadata -| Module | Role | -| ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | -| `source-metadata.ts`, `source-governance.ts`, `source-text-sanitizer.ts` | Source provenance and governance | -| `documents/` (`is-public-document.ts`), `document-label-governance.ts`, `document-tags.ts`, `document-organization.ts` | Labels, organization, and public boundary checks | -| `table-review.ts`, `accessible-table-normalization.ts` | Table facts | +| Module | Role | +| ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | +| `source-metadata.ts`, `source-governance.ts`, `source-text-sanitizer.ts` | Source provenance and governance | +| `sources/` | Client-safe catalogue contracts, deterministic ratings, provider adapters and loader | +| `documents/` (`is-public-document.ts`), `document-label-governance.ts`, `document-tags.ts`, `document-organization.ts` | Labels, organization, and public boundary checks | +| `table-review.ts`, `accessible-table-normalization.ts` | Table facts | ### Supabase, auth, env @@ -707,7 +710,7 @@ terminology: `docs/care-plan-context.md`; build history and rulings: `docs/care- One shared composer (`master-search-header.tsx`) serves every mode. Placement: -- **Mode homes**: all 15 modes use the one shared home at `/?mode=` (including Answer at `/`), while four routes still own a functional home of their own — `/medications` (the Prescribing workspace, with dose/safety/monitoring checks), `/favourites` (a hub), `/tools` (a launcher) and `/documents` (dashboard-owned: browse, recent documents and the document-search empty state). None of those four is a duplicate of the shared home; each is its mode’s only functional surface. Composer inline in the hero via the `mode-home-composer-slot` portal, on phone and tablet+ alike. The other ten modes were consolidated onto the shared home: `/services`, `/forms`, `/differentials`, `/dsm`, `/specifiers`, `/formulation`, `/calculators`, `/factsheets`, `/dictionary` and `/therapy-compass` are now `redirect()` stubs (`src/lib/consolidated-mode-home-redirect.ts`, resolved in `src/proxy.ts` so they emit a real 307 rather than a streamed meta-refresh). Calculators and Dictionary are full modes in this inventory, not route aliases. Their per-mode copy is `sharedHomePresentation` in `src/lib/ui-copy.ts`. (`/applications` is a redirect to `/tools`, not a mode or composer surface.) +- **Mode homes**: all 16 modes use the one shared home at `/?mode=` (including Answer at `/`), while five routes still own a functional home of their own — `/medications` (the Prescribing workspace, with dose/safety/monitoring checks), `/favourites` (a hub), `/tools` (a launcher), `/documents` (dashboard-owned: browse, recent documents and the document-search empty state) and `/sources` (the source catalogue). None of those five is a duplicate of the shared home; each is its mode’s only functional surface. Composer inline in the hero via the `mode-home-composer-slot` portal, on phone and tablet+ alike. The other ten modes were consolidated onto the shared home: `/services`, `/forms`, `/differentials`, `/dsm`, `/specifiers`, `/formulation`, `/calculators`, `/factsheets`, `/dictionary` and `/therapy-compass` are now `redirect()` stubs (`src/lib/consolidated-mode-home-redirect.ts`, resolved in `src/proxy.ts` so they emit a real 307 rather than a streamed meta-refresh). Calculators and Dictionary are full modes in this inventory, not route aliases. Their per-mode copy is `sharedHomePresentation` in `src/lib/ui-copy.ts`. (`/applications` is a redirect to `/tools`, not a mode or composer surface.) - **Information (detail) pages**: catalogue/record routes under each mode (`/services/[slug]`, `/forms/[slug]`, `/medications/[slug]`, `/specifiers/[slug]`, `/formulation/[slug]`, `/factsheets/[slug]`, `/dictionary/[slug]`, `/dictionary/topics/[slug]`, `/therapy-compass/[slug]`, `/dsm/diagnoses/[slug]`, …). Route detection: `src/lib/information-pages.ts` (`isInformationPage`). Shared outer chrome: `src/components/information-page-shell.tsx` (`InformationPageShell`, breadcrumbs, optional footer). Specifier/formulation mode shells re-export that primitive. Intentional opt-outs: document viewer and the differentials presentation workflow. - **Result and detail views**: fixed bottom dock on phone (compact variant on submitted searches), sticky top from `sm` up. - **Results routing**: each consolidated mode owns its submitted searches at `/search` (`/services/search` → `ServicesNavigatorPage`, `/forms/search` → `FormsSearchResultsPage`, `/differentials/search` → `DifferentialsHome` results view, `/formulation/search` → local mechanism results, and the same shape for dsm, dictionary, factsheets, specifiers, calculators, therapy-compass and documents). That split is not cosmetic: the bare path redirects to the shared home, so routing a submitted query back at it would loop — `consolidatedModeHomeModeIds` drives both halves from one list, and `tests/consolidated-mode-home-redirect.test.ts` pins the no-loop property. `/favourites` and `/tools` keep filtering in place on their own routes. Answer, Documents, and Prescribing submitted searches render inside `ClinicalDashboard` — intentional, since they need retrieval/answer state. Bare `/?mode=` always renders the shared home with that mode preselected; only a submitted deep link (`q` plus `run=1`) resolves onward to the mode's own search surface. diff --git a/docs/design-system/ADOPTION.md b/docs/design-system/ADOPTION.md index 6089a34754..f1e97ca86a 100644 --- a/docs/design-system/ADOPTION.md +++ b/docs/design-system/ADOPTION.md @@ -357,12 +357,12 @@ product exclusions; the only route-only dispositions are the documented legacy-r surfaces. Shared shell/component roots carry their own explicit `shared-shell` disposition. Registered public components: 55 -Declared product roots: 84 +Declared product roots: 89 Roots with a literal `.ckb-v2` opt-in: 1 -Roots inheriting `.ckb-v2` from the global ``: 83 +Roots inheriting `.ckb-v2` from the global ``: 88 Production surfaces observed under v2: 15/15 Dynamic `ckb-v2` constructions: 0 -Declared production page routes: 76/76 +Declared production page routes: 81/81 Source observation and contract declaration are independent. A literal `ckb-v2` on the global `` makes every production surface inherit v2, but it does not approve that adoption. The Proof column summarizes each surface's dark, forced-colours, 320px, print and browser declarations; exact statuses and evidence paths live in the manifest. @@ -371,7 +371,7 @@ Observed v2 under a compatibility declaration fails closed. A declared v2 shell | Surface | Disposition | Routes | Roots | Declared shell | Observed shell (mount) | Proof | Baseline | | ---------------------------------- | --------------- | -----: | ----: | -------------- | -------------------------- | -------------- | -------------- | | `root-shell-and-settings` | shared-shell | 3 | 6 | v2 | v2 (inherited-global-root) | passed | not-committed | -| `catalogues-forms-and-info` | owned | 24 | 24 | v2 | v2 (inherited-global-root) | passed | not-committed | +| `catalogues-forms-and-info` | owned | 29 | 29 | v2 | v2 (inherited-global-root) | passed | not-committed | | `differentials` | owned | 7 | 7 | v2 | v2 (inherited-global-root) | passed | not-committed | | `formulation` | owned | 6 | 6 | v2 | v2 (inherited-global-root) | passed | not-committed | | `specifiers` | owned | 6 | 6 | v2 | v2 (inherited-global-root) | passed | not-committed | diff --git a/docs/design-system/adoption-contract.json b/docs/design-system/adoption-contract.json index e7d060e2df..33d904e6a5 100644 --- a/docs/design-system/adoption-contract.json +++ b/docs/design-system/adoption-contract.json @@ -141,7 +141,12 @@ "src/app/(search-app)/medications/[slug]/page.tsx", "src/app/(search-app)/services/[slug]/page.tsx", "src/app/(search-app)/services/page.tsx", - "src/app/(search-app)/services/search/page.tsx" + "src/app/(search-app)/services/search/page.tsx", + "src/app/(search-app)/sources/[sourceId]/page.tsx", + "src/app/(search-app)/sources/method/page.tsx", + "src/app/(search-app)/sources/page.tsx", + "src/app/(search-app)/sources/publishers/page.tsx", + "src/app/(search-app)/sources/topics/page.tsx" ], "routeRoots": true, "roots": [], @@ -166,7 +171,7 @@ }, "browser": { "status": "passed", - "evidence": ["tests/ui-visual-baseline.spec.ts"] + "evidence": ["tests/ui-sources.spec.ts", "tests/ui-visual-baseline.spec.ts"] } }, "baseline": { diff --git a/docs/design-system/adoption-manifest.json b/docs/design-system/adoption-manifest.json index cd5dff0fd3..0727b77ca0 100644 --- a/docs/design-system/adoption-manifest.json +++ b/docs/design-system/adoption-manifest.json @@ -2418,7 +2418,12 @@ "src/app/(search-app)/medications/[slug]/page.tsx", "src/app/(search-app)/services/[slug]/page.tsx", "src/app/(search-app)/services/page.tsx", - "src/app/(search-app)/services/search/page.tsx" + "src/app/(search-app)/services/search/page.tsx", + "src/app/(search-app)/sources/[sourceId]/page.tsx", + "src/app/(search-app)/sources/method/page.tsx", + "src/app/(search-app)/sources/page.tsx", + "src/app/(search-app)/sources/publishers/page.tsx", + "src/app/(search-app)/sources/topics/page.tsx" ], "routeRoots": true, "proofApplicability": "required", @@ -2432,7 +2437,7 @@ "proof": { "browser": { "status": "passed", - "evidence": ["tests/ui-visual-baseline.spec.ts"] + "evidence": ["tests/ui-sources.spec.ts", "tests/ui-visual-baseline.spec.ts"] }, "compact320": { "status": "passed", @@ -2697,6 +2702,56 @@ "dynamicCkbV2": false, "v2MountMode": "inherited-global-root", "sanctionedPatternsPresent": ["ModeHome"] + }, + { + "file": "src/app/(search-app)/sources/[sourceId]/page.tsx", + "exists": true, + "imports": [], + "importedFamilies": [], + "literalCkbV2": false, + "dynamicCkbV2": false, + "v2MountMode": "inherited-global-root", + "sanctionedPatternsPresent": ["DetailPage"] + }, + { + "file": "src/app/(search-app)/sources/method/page.tsx", + "exists": true, + "imports": [], + "importedFamilies": [], + "literalCkbV2": false, + "dynamicCkbV2": false, + "v2MountMode": "inherited-global-root", + "sanctionedPatternsPresent": [] + }, + { + "file": "src/app/(search-app)/sources/page.tsx", + "exists": true, + "imports": [], + "importedFamilies": [], + "literalCkbV2": false, + "dynamicCkbV2": false, + "v2MountMode": "inherited-global-root", + "sanctionedPatternsPresent": [] + }, + { + "file": "src/app/(search-app)/sources/publishers/page.tsx", + "exists": true, + "imports": [], + "importedFamilies": [], + "literalCkbV2": false, + "dynamicCkbV2": false, + "v2MountMode": "inherited-global-root", + "sanctionedPatternsPresent": [] + }, + { + "file": "src/app/(search-app)/sources/topics/page.tsx", + "exists": true, + "imports": [], + "importedFamilies": [], + "literalCkbV2": false, + "dynamicCkbV2": false, + "v2MountMode": "inherited-global-root", + "sanctionedPatternsPresent": [] } ] }, @@ -3942,6 +3997,11 @@ "src/app/(search-app)/services/[slug]/page.tsx", "src/app/(search-app)/services/page.tsx", "src/app/(search-app)/services/search/page.tsx", + "src/app/(search-app)/sources/[sourceId]/page.tsx", + "src/app/(search-app)/sources/method/page.tsx", + "src/app/(search-app)/sources/page.tsx", + "src/app/(search-app)/sources/publishers/page.tsx", + "src/app/(search-app)/sources/topics/page.tsx", "src/app/(search-app)/specifiers/[slug]/page.tsx", "src/app/(search-app)/specifiers/builder/page.tsx", "src/app/(search-app)/specifiers/compare/page.tsx", @@ -4020,6 +4080,11 @@ "src/app/(search-app)/services/[slug]/page.tsx", "src/app/(search-app)/services/page.tsx", "src/app/(search-app)/services/search/page.tsx", + "src/app/(search-app)/sources/[sourceId]/page.tsx", + "src/app/(search-app)/sources/method/page.tsx", + "src/app/(search-app)/sources/page.tsx", + "src/app/(search-app)/sources/publishers/page.tsx", + "src/app/(search-app)/sources/topics/page.tsx", "src/app/(search-app)/specifiers/[slug]/page.tsx", "src/app/(search-app)/specifiers/builder/page.tsx", "src/app/(search-app)/specifiers/compare/page.tsx", @@ -4056,7 +4121,7 @@ }, "adoption": { "literalCkbV2RootCount": 1, - "inheritedCkbV2RootCount": 83, + "inheritedCkbV2RootCount": 88, "dynamicCkbV2RootCount": 0, "v2MountedSurfaceCount": 15, "declaredV2SurfaceCount": 15 @@ -4065,8 +4130,8 @@ "registeredComponentCount": 55, "previewCount": 55, "productImportedComponentCount": 39, - "rootCount": 84, - "productionRouteCount": 76, - "nextUiEntryCount": 136 + "rootCount": 89, + "productionRouteCount": 81, + "nextUiEntryCount": 142 } } diff --git a/docs/scripts-index.md b/docs/scripts-index.md index f8e6e3bf0c..b141994388 100644 --- a/docs/scripts-index.md +++ b/docs/scripts-index.md @@ -1,6 +1,6 @@ # Scripts index -Curated map of `scripts/` (282 files) and the `package.json` script surface (283 entries), +Curated map of `scripts/` (283 files) and the `package.json` script surface (284 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. `npm run docs:update` refreshes the exact counts above. diff --git a/docs/site-map.md b/docs/site-map.md index 978f9901b6..2cb4078ed8 100644 --- a/docs/site-map.md +++ b/docs/site-map.md @@ -21,7 +21,7 @@ This file is generated by `npm run docs:update` (or `npm run sitemap:update` dir - `/dictionary/browse` - Compatibility redirect to `/dictionary/search`, which is now the whole catalogue; the query string is carried across. Source: `src/app/(search-app)/dictionary/browse/page.tsx`. - `/dictionary/compare` - Side-by-side clinical term definition and nuance comparison. Source: `src/app/(search-app)/dictionary/compare/page.tsx`. - `/dictionary/search` - The clinical term and abbreviation catalogue: an empty query lists everything, a typed query narrows the same list. Source: `src/app/(search-app)/dictionary/search/page.tsx`. -- `/dictionary/sources` - Clinical dictionary governance, references, and source catalogue. Source: `src/app/(search-app)/dictionary/sources/page.tsx`. +- `/dictionary/sources` - Query-preserving compatibility redirect to `/sources?usedBy=dictionary`; incoming catalogue filters are retained and application usage is set to Dictionary. Source: `src/app/(search-app)/dictionary/sources/page.tsx`. - `/dictionary/topics` - Clinical dictionary topic category index. Source: `src/app/(search-app)/dictionary/topics/page.tsx`. - `/differentials` - Compatibility redirect to the shared home at `/?mode=differentials`; a submitted `?q=…&run=1` forwards to `/differentials/search`. Source: `src/app/(search-app)/differentials/page.tsx`. - `/differentials/compare` - Compare queue: empty state or selected diagnosis ids (Search edit links preserve ids); Open comparison launches a catalogue presentation workflow or an ad-hoc workspace (`workspace=1`). Source: `src/app/(search-app)/differentials/compare/page.tsx`. @@ -53,6 +53,11 @@ This file is generated by `npm run docs:update` (or `npm run sitemap:update` dir - `/safety-plan` - Patient safety plan generator (Stanley-Brown six steps) — a Tools-page clinical tool. Source: `src/app/safety-plan/page.tsx`. - `/services` - Compatibility redirect to the shared home at `/?mode=services`; a submitted `?q=…&run=1` forwards to `/services/search`. Source: `src/app/(search-app)/services/page.tsx`. - `/services/search` - Route discovered from app directory Source: `src/app/(search-app)/services/search/page.tsx`. +- `/sources` - Route discovered from app directory Source: `src/app/(search-app)/sources/page.tsx`. +- `/sources/[sourceId]` - Route discovered from app directory Source: `src/app/(search-app)/sources/[sourceId]/page.tsx`. +- `/sources/method` - Route discovered from app directory Source: `src/app/(search-app)/sources/method/page.tsx`. +- `/sources/publishers` - Route discovered from app directory Source: `src/app/(search-app)/sources/publishers/page.tsx`. +- `/sources/topics` - Route discovered from app directory Source: `src/app/(search-app)/sources/topics/page.tsx`. - `/specifiers` - Compatibility redirect to the shared home at `/?mode=specifiers`; a submitted `?q=…&run=1` forwards to `/specifiers/search`. Source: `src/app/(search-app)/specifiers/page.tsx`. - `/specifiers/builder` - Structured diagnostic wording builder. Source: `src/app/(search-app)/specifiers/builder/page.tsx`. - `/specifiers/compare` - Side-by-side psychiatric specifier comparison. Source: `src/app/(search-app)/specifiers/compare/page.tsx`. @@ -85,26 +90,28 @@ This file is generated by `npm run docs:update` (or `npm run sitemap:update` dir - `/therapy-compass` - Therapy mode. Search kind: `therapies`. Query example: `/therapy-compass/search?q=behavioural+activation&focus=1&run=1`. - `/factsheets` - Factsheets mode. Search kind: `tools`. Query example: `/factsheets/search?q=sertraline&focus=1&run=1`. - `/dictionary` - Dictionary mode. Search kind: `tools`. Query example: `/dictionary/search?q=mental+state+examination&focus=1&run=1`. +- `/sources` - Sources mode. Search kind: `tools`. Query example: `/sources?q=RANZCP&focus=1&run=1`. ## Mode page index -| Mode | Home page | Search/results page | Information/detail pages | -| --------------- | ------------------------ | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Answer | `/?mode=answer` | `/?mode=answer&q=example+question&focus=1&run=1` | Answer, citations, evidence, and source panels render inside the root dashboard shell. | -| Documents | `/documents` | `/documents/search?mode=documents&q=lithium+monitoring&focus=1&run=1` | `/documents/search` live results and `/documents/[id]` canonical viewer; `/documents/source*` are compatibility redirects. | -| Services | `/?mode=services` | `/services/search?q=13YARN&focus=1&run=1` | `/services/[slug]` service record pages. | -| Forms | `/?mode=forms` | `/forms/search?q=transport+forms&focus=1&run=1` | `/forms/[slug]` form record pages. | -| Favourites | `/favourites` | `/favourites?q=clozapine+set&focus=1&run=1` | Saved set and saved item detail render inside the favourites page surface. | -| Differentials | `/?mode=differentials` | `/differentials/search?q=acute+confusion&focus=1&run=1` | `/differentials/diagnoses`, `/differentials/diagnoses/[slug]`, `/differentials/presentations`, `/differentials/presentations/[slug]`, and `/differentials/compare`. | -| DSM-5 Diagnosis | `/?mode=dsm` | `/dsm/search?q=major+depressive+disorder&focus=1&run=1` | `/dsm/diagnoses/[slug]`, `/dsm/compare`, and `/dsm/diagnoses/[slug]/differentials`. | -| Specifiers | `/?mode=specifiers` | `/specifiers/search?q=depressed+but+racing+thoughts&focus=1&run=1` | `/specifiers/[slug]`, `/specifiers/builder`, `/specifiers/compare`, and `/specifiers/map`. | -| Formulation | `/?mode=formulation` | `/formulation/search?q=I+keep+going+over+it&focus=1&run=1` | `/formulation/[slug]`, `/formulation/builder`, `/formulation/compare`, and `/formulation/map`. | -| Medication | `/medications` | `/?mode=prescribing&q=acamprosate+renal+dose&focus=1&run=1` | `/medications/[slug]`; submitted searches resolve to `/?mode=prescribing&q=…&run=1`. | -| Tools | `/tools` | `/tools?q=medications&focus=1&run=1` | Canonical all-tools results directory at `/tools`; the universal mode picker opens it directly. `/?mode=tools` remains a dashboard-mode alias. | -| Calculators | `/?mode=calculators` | `/calculators/search?q=PHQ-9&focus=1&run=1` | `/calculators/search` is the browsable calculator catalogue and scored-results surface; an empty query lists every calculator. | -| Factsheets | `/?mode=factsheets` | `/factsheets/search?q=sertraline&focus=1&run=1` | `/factsheets/search` is the query-and-filter surface; `/factsheets/topics` organises the library by category; `/factsheets/[slug]` records. | -| Dictionary | `/?mode=dictionary` | `/dictionary/search?q=MSE&focus=1&run=1` | `/dictionary/search` is one catalogue for both searching and browsing; `/dictionary/browse` redirects to it. Also `/topics`, `/topics/[slug]`, `/compare`, `/sources` and `/dictionary/[slug]` records. | -| Therapy Compass | `/?mode=therapy-compass` | `/therapy-compass/search?q=CBT&focus=1&run=1` | Keeps a home of its own at `/therapy-compass`; `/search` (query-free browse), `/recommend`, `/compare`, `/pathways`, `/review`, and `/[slug]` records with `/brief` and `/sheet` outputs. | +| Mode | Home page | Search/results page | Information/detail pages | +| --------------- | ------------------------ | --------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Answer | `/?mode=answer` | `/?mode=answer&q=example+question&focus=1&run=1` | Answer, citations, evidence, and source panels render inside the root dashboard shell. | +| Documents | `/documents` | `/documents/search?mode=documents&q=lithium+monitoring&focus=1&run=1` | `/documents/search` live results and `/documents/[id]` canonical viewer; `/documents/source*` are compatibility redirects. | +| Services | `/?mode=services` | `/services/search?q=13YARN&focus=1&run=1` | `/services/[slug]` service record pages. | +| Forms | `/?mode=forms` | `/forms/search?q=transport+forms&focus=1&run=1` | `/forms/[slug]` form record pages. | +| Favourites | `/favourites` | `/favourites?q=clozapine+set&focus=1&run=1` | Saved set and saved item detail render inside the favourites page surface. | +| Differentials | `/?mode=differentials` | `/differentials/search?q=acute+confusion&focus=1&run=1` | `/differentials/diagnoses`, `/differentials/diagnoses/[slug]`, `/differentials/presentations`, `/differentials/presentations/[slug]`, and `/differentials/compare`. | +| DSM-5 Diagnosis | `/?mode=dsm` | `/dsm/search?q=major+depressive+disorder&focus=1&run=1` | `/dsm/diagnoses/[slug]`, `/dsm/compare`, and `/dsm/diagnoses/[slug]/differentials`. | +| Specifiers | `/?mode=specifiers` | `/specifiers/search?q=depressed+but+racing+thoughts&focus=1&run=1` | `/specifiers/[slug]`, `/specifiers/builder`, `/specifiers/compare`, and `/specifiers/map`. | +| Formulation | `/?mode=formulation` | `/formulation/search?q=I+keep+going+over+it&focus=1&run=1` | `/formulation/[slug]`, `/formulation/builder`, `/formulation/compare`, and `/formulation/map`. | +| Medication | `/medications` | `/?mode=prescribing&q=acamprosate+renal+dose&focus=1&run=1` | `/medications/[slug]`; submitted searches resolve to `/?mode=prescribing&q=…&run=1`. | +| Tools | `/tools` | `/tools?q=medications&focus=1&run=1` | Canonical all-tools results directory at `/tools`; the universal mode picker opens it directly. `/?mode=tools` remains a dashboard-mode alias. | +| Calculators | `/?mode=calculators` | `/calculators/search?q=PHQ-9&focus=1&run=1` | `/calculators/search` is the browsable calculator catalogue and scored-results surface; an empty query lists every calculator. | +| Factsheets | `/?mode=factsheets` | `/factsheets/search?q=sertraline&focus=1&run=1` | `/factsheets/search` is the query-and-filter surface; `/factsheets/topics` organises the library by category; `/factsheets/[slug]` records. | +| Dictionary | `/?mode=dictionary` | `/dictionary/search?q=MSE&focus=1&run=1` | `/dictionary/search` is one catalogue for both searching and browsing; `/dictionary/browse` redirects to it. Also `/topics`, `/topics/[slug]`, `/compare` and `/dictionary/[slug]` records; `/dictionary/sources` redirects to Sources. | +| Sources | `/sources` | `/sources?q=RANZCP&focus=1&run=1` | `/sources/topics`, `/sources/publishers`, `/sources/method`, and `/sources/[sourceId]` traceability records. | +| Therapy Compass | `/?mode=therapy-compass` | `/therapy-compass/search?q=CBT&focus=1&run=1` | Keeps a home of its own at `/therapy-compass`; `/search` (query-free browse), `/recommend`, `/compare`, `/pathways`, `/review`, and `/[slug]` records with `/brief` and `/sheet` outputs. | ## Documents flow index @@ -1363,6 +1370,7 @@ This file is generated by `npm run docs:update` (or `npm run sitemap:update` dir - `/calculators` - Redirects to `/?mode=calculators`. Source: `src/app/(search-app)/calculators/page.tsx`. - `/dictionary` - Redirects to `/?mode=dictionary`. Source: `src/app/(search-app)/dictionary/page.tsx`. - `/dictionary/browse` - Redirects to `/dictionary/search`. Source: `src/app/(search-app)/dictionary/browse/page.tsx`. +- `/dictionary/sources` - Redirects to `/sources?usedBy=dictionary`. Source: `src/app/(search-app)/dictionary/sources/page.tsx`. - `/differentials` - Redirects to `/?mode=differentials`. Source: `src/app/(search-app)/differentials/page.tsx`. - `/documents/source` - Redirects to `/documents/[id]`. Source: `src/app/(search-app)/documents/source/page.tsx`. - `/documents/source/evidence` - Redirects to `/documents/[id]`. Source: `src/app/(search-app)/documents/source/evidence/page.tsx`. diff --git a/docs/superpowers/plans/2026-09-01-sources-mode.md b/docs/superpowers/plans/2026-09-01-sources-mode.md new file mode 100644 index 0000000000..8f8ca2d134 --- /dev/null +++ b/docs/superpowers/plans/2026-09-01-sources-mode.md @@ -0,0 +1,1032 @@ +# Sources Mode Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Build a read-only `/sources` application mode that automatically catalogues, organises, rates, ranks and traces every structured academic or clinical source used by production content, while preserving private-document access boundaries and leaving RAG behaviour unchanged. + +**Architecture:** Treat Sources as a server-assembled projection over existing source owners. Pure catalogue code normalises references, reuses existing authority and metadata governance, partitions incompatible identities, deduplicates compatible citations, applies a deterministic presentation-only rating and produces client-safe entries. Registered repository providers and a separately scoped Supabase document loader feed that core; route components render the same canonical entries as Catalogue, Topics, Publishers, Method and detail views. + +**Tech Stack:** Next.js App Router, React, TypeScript, Supabase/Postgres through the existing server/admin clients and owner/public query scope, Tailwind CSS, Vitest/Testing Library, Playwright and the repository's existing source-governance utilities. + +**Spec:** `docs/superpowers/specs/2026-09-01-sources-mode-design.md` + +**Estimated build time:** 7–10 engineering hours with subagent-driven development, including task-level TDD, two-stage reviews and focused browser verification. Connected Supabase verification, production-readiness checks, deployment and PR work are outside this estimate and remain separately authorized. + +## Global Constraints + +- Catalogue academic and clinical information sources only; exclude developer documentation, tests, mockups, fixtures used only by tests, build references and incidental prose URLs. +- Keep this feature read-only: no source editor, database migration, new Supabase table, hosted write, ingestion job or synchronisation job. +- Do not change RAG retrieval, relevance scoring, prompts, citations, answer generation or provider evaluation. +- Reuse `ClinicalSourceMetadata`, `normalizeSourceMetadata()` and `classifySourceAuthority()`; do not introduce a second publisher-authority, jurisdiction, currentness or validation system. +- The catalogue score is organisational presentation only. Use the label **Accuracy assurance** and never claim that software has measured factual truth. +- Apply the exact weights from the spec: accuracy assurance 25, reliability 20, evidence quality 20, currency 15, Australian applicability 15 and traceability 5. +- Apply the exact bands from the spec: A 85–100, B 70–84, C 50–69, D below 50 or material uncertainty, plus Excluded before scoring. +- Prefer Australian material only within the bounded score. An Australian source never bypasses validation, identity, lifecycle or evidence-quality controls. +- Never infer publisher, jurisdiction, evidence type, version, approval or currentness from title, filename or free-text citation prose. +- Preserve free-text legacy references as provisional D-band identities; do not parse them into invented citations. +- Use only metadata from accessible documents. Never project document text, chunks, embeddings, summaries, answers, queries, user identifiers, patient data, storage paths or raw metadata to the browser. +- Public documents are visible only when `owner_id IS NULL` and `metadata.public_corpus = true`; authenticated callers additionally see their own UUID-scoped documents. +- Assemble and score on the server. Send only `ClinicalSourceCatalogueEntry` view data and availability status to client components. +- Reuse the shared search composer, `RegistryModeNav`, `InformationPageShell`, existing header-collapse ownership and responsive tokens. Do not add a second search bar or phone header. +- Use 48px minimum phone controls, textual band/warning labels, keyboard-operable controls, restrained live-region result counts, reduced-motion safety and forced-colours legibility. +- Run no live Supabase audit, provider evaluation, production-readiness command, migration, deployment, push or pull request without separate explicit authorization. +- Runtime floors remain Node `>=24.15.0 <25` and npm `11.x`; add no dependency. + +## File Structure + +| File | Responsibility | +| ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `src/lib/sources/catalogue-types.ts` | Client-safe catalogue inputs, entries, ratings, warnings, filters and provider contracts | +| `src/lib/sources/catalogue-core.ts` | HTTPS validation, deterministic identity, compatibility partitioning, deduplication, authority reuse, rating and default ordering | +| `src/lib/sources/catalogue-view.ts` | Client-safe filter parsing, filtering, sorting, counts, topic and publisher projections | +| `src/lib/sources/repository-providers.ts` | Registered adapters for every current production clinical source owner: Dictionary, Factsheets, Formulation, Therapy, Specifiers, Forms/MHA, Medication, Services, DSM and calculators | +| `src/lib/sources/document-source-loader.ts` | Server-only owner/public Supabase query and safe document-to-reference projection | +| `src/lib/sources/load-source-catalogue.ts` | Server-only merge of repository and accessible-document references with truthful availability state | +| `scripts/check-source-catalogue.ts` | Offline provider/coverage validation; failures versus review debt | +| `src/components/sources/sources-catalogue-client.tsx` | URL-backed filters, sort, counts, desktop rows and phone cards | +| `src/components/sources/sources-pages.tsx` | Shared shell plus Catalogue, Topics, Publishers, Method and detail renderers | +| `src/app/(search-app)/sources/**` | Sources mode routes and metadata | +| `tests/source-catalogue-core.test.ts` | Pure identity, deduplication, scoring and ordering contracts | +| `tests/source-catalogue-providers.test.ts` | Adapter inventory, automatic coverage and legacy-debt contracts | +| `tests/source-document-loader.test.ts` | Owner/public scoping, safe projection and unavailable-state contracts | +| `tests/sources-mode.dom.test.tsx` | Catalogue filtering, semantic labels, derived views and degraded-state DOM contracts | +| `tests/ui-sources.spec.ts` | Focused browser proof for routes, phone/desktop overflow, keyboard, reduced motion, forced colours and axe | + +--- + +### Task 1: Canonical catalogue, rating and view model + +**Files:** + +- Create: `src/lib/sources/catalogue-types.ts` +- Create: `src/lib/sources/catalogue-core.ts` +- Create: `src/lib/sources/catalogue-view.ts` +- Create: `tests/source-catalogue-core.test.ts` + +**Interfaces:** + +- Consumes: `ClinicalSourceMetadata` from `src/lib/types.ts`, `normalizeSourceMetadata(input: unknown)` from `src/lib/source-metadata.ts`, and `classifySourceAuthority(input: unknown)` from `src/lib/source-authority-registry.ts`. +- Produces: `ClinicalSourceReferenceInput`, `ClinicalSourceCatalogueEntry`, `ClinicalSourceRating`, `SourceCatalogueFilters`, `canonicalizeSourceReferences(inputs)`, `parseSourceCatalogueFilters(params)`, `filterAndSortSourceCatalogue(entries, filters)` and `deriveSourceCatalogueFacets(entries)`. + +- [ ] **Step 1: Write the failing core contract tests** + +Create `tests/source-catalogue-core.test.ts` with fixtures that prove the score is deterministic, Australian preference is bounded, material uncertainty forces D, exclusion runs before score, unsafe URLs never become links, compatible duplicates merge their usages, incompatible versions/publishers remain separate, and default ordering is band then score then Australian applicability then currency then title. + +```ts +import { describe, expect, it } from "vitest"; + +import { canonicalizeSourceReferences, rateClinicalSource } from "@/lib/sources/catalogue-core"; +import type { ClinicalSourceReferenceInput } from "@/lib/sources/catalogue-types"; + +function reference(overrides: Partial = {}): ClinicalSourceReferenceInput { + return { + sourceId: "akg-guideline", + documentId: null, + title: "Example clinical guideline", + aliases: [], + publisher: "Armadale Kalamunda Group", + publisherCode: "AKG", + canonicalUrl: "https://www.ahs.health.wa.gov.au/example", + datasetLocation: null, + version: "1", + publicationDate: "2025-01-01", + reviewDate: "2026-01-01", + expiryDate: null, + jurisdiction: "Australia/WA", + evidenceType: "guideline", + documentStatus: "current", + validationStatus: "approved", + contentMode: "link_only", + lifecycleStatus: "active", + supersedes: [], + supersededBy: [], + topics: ["governance"], + usage: { modeId: "dictionary", recordId: "mse", recordLabel: "Mental state examination", field: "definition" }, + referenceText: null, + ...overrides, + }; +} + +describe("clinical source catalogue", () => { + it("uses the published six weights and band thresholds", () => { + const rating = rateClinicalSource(reference()); + expect(rating.weights).toEqual({ + accuracyAssurance: 25, + reliability: 20, + evidenceQuality: 20, + currency: 15, + australianApplicability: 15, + traceability: 5, + }); + expect(rating.score).toBe(100); + expect(rating.band).toBe("A"); + }); + + it("forces incomplete future references into D without discarding them", () => { + const [entry] = canonicalizeSourceReferences([ + reference({ + sourceId: null, + publisher: null, + publisherCode: null, + canonicalUrl: null, + version: null, + publicationDate: null, + reviewDate: null, + jurisdiction: null, + evidenceType: "unknown", + validationStatus: "unknown", + referenceText: "Legacy prose citation", + }), + ]); + expect(entry.rating.band).toBe("D"); + expect(entry.warnings).toEqual(expect.arrayContaining(["ambiguous_identity", "verification_unknown"])); + }); + + it("runs lifecycle exclusion before the numeric score", () => { + expect(rateClinicalSource(reference({ lifecycleStatus: "excluded" })).band).toBe("excluded"); + }); + + it("keeps a substantially stronger international source above a weak Australian source", () => { + const entries = canonicalizeSourceReferences([ + reference({ + sourceId: "strong-int", + publisher: "World Health Organization", + publisherCode: "WHO", + jurisdiction: "International", + }), + reference({ + sourceId: "weak-au", + publisher: null, + publisherCode: null, + validationStatus: "unverified", + evidenceType: "other", + }), + ]); + expect(entries.map((entry) => entry.sourceId)).toEqual(["strong-int", "weak-au"]); + }); + + it("merges compatible aliases while retaining every usage", () => { + const entries = canonicalizeSourceReferences([ + reference(), + reference({ + usage: { modeId: "factsheets", recordId: "depression", recordLabel: "Depression", field: "sources" }, + }), + ]); + expect(entries).toHaveLength(1); + expect(entries[0].usedBy).toHaveLength(2); + }); + + it("does not merge conflicting versions or publishers", () => { + const entries = canonicalizeSourceReferences([ + reference(), + reference({ version: "2", publisher: "Different publisher", publisherCode: null }), + ]); + expect(entries).toHaveLength(2); + expect(entries.every((entry) => entry.warnings.includes("metadata_conflict"))).toBe(true); + }); + + it("removes unsafe outbound locations", () => { + const [entry] = canonicalizeSourceReferences([reference({ canonicalUrl: "javascript:alert(1)" })]); + expect(entry.canonicalLocation).toEqual({ kind: "none" }); + expect(entry.warnings).toContain("unsafe_location"); + }); +}); +``` + +- [ ] **Step 2: Run the core test to confirm the red state** + +Run: `node scripts/run-vitest.mjs run tests/source-catalogue-core.test.ts` + +Expected: FAIL because `@/lib/sources/catalogue-core` and `@/lib/sources/catalogue-types` do not exist. + +- [ ] **Step 3: Define the client-safe contracts** + +Create `src/lib/sources/catalogue-types.ts` with these exact public shapes. Keep raw document rows, raw metadata and identity keys out of `ClinicalSourceCatalogueEntry`. + +```ts +import type { AppModeId } from "@/lib/app-modes"; + +export type ClinicalSourceType = + | "guideline" + | "systematic_review" + | "primary_study" + | "standard" + | "legislation" + | "regulatory" + | "professional_reference" + | "consumer_reference" + | "uploaded_document" + | "dataset" + | "other" + | "unknown"; + +export type SourceGeographyScope = "wa" | "australian_national" | "australian_state" | "international" | "unknown"; +export type SourceLifecycleStatus = "active" | "inactive" | "excluded"; +export type SourceContentMode = "indexed_content" | "link_only" | "metadata_only"; +export type SourceQualityBand = "A" | "B" | "C" | "D" | "excluded"; +export type SourceCatalogueWarning = + | "ambiguous_identity" + | "metadata_conflict" + | "unsafe_location" + | "missing_publisher" + | "missing_version" + | "missing_dates" + | "unknown_jurisdiction" + | "unknown_evidence_type" + | "verification_unknown" + | "outdated" + | "superseded"; + +export type SourceUsage = { + modeId: AppModeId; + recordId: string; + recordLabel: string; + field: string; +}; + +export type SourceCanonicalLocation = + | { kind: "url"; href: string } + | { kind: "document"; documentId: string; href: string } + | { kind: "dataset"; label: string } + | { kind: "none" }; + +export type ClinicalSourceReferenceInput = { + sourceId: string | null; + documentId: string | null; + title: string | null; + aliases: string[]; + publisher: string | null; + publisherCode: string | null; + canonicalUrl: string | null; + datasetLocation: string | null; + version: string | null; + publicationDate: string | null; + reviewDate: string | null; + expiryDate: string | null; + jurisdiction: string | null; + evidenceType: ClinicalSourceType; + documentStatus: "current" | "review_due" | "outdated" | "unknown"; + validationStatus: "approved" | "locally_reviewed" | "unverified" | "unknown"; + contentMode: SourceContentMode; + lifecycleStatus: SourceLifecycleStatus; + supersedes: string[]; + supersededBy: string[]; + topics: string[]; + usage: SourceUsage; + referenceText: string | null; +}; + +export type ClinicalSourceRating = { + score: number; + band: SourceQualityBand; + dimensions: { + accuracyAssurance: number; + reliability: number; + evidenceQuality: number; + currency: number; + australianApplicability: number; + traceability: number; + }; + weights: typeof SOURCE_RATING_WEIGHTS; + reasons: string[]; +}; + +export const SOURCE_RATING_WEIGHTS = { + accuracyAssurance: 25, + reliability: 20, + evidenceQuality: 20, + currency: 15, + australianApplicability: 15, + traceability: 5, +} as const; + +export type ClinicalSourceCatalogueEntry = { + id: string; + sourceId: string | null; + title: string; + aliases: string[]; + version: string | null; + publisher: string | null; + publisherCode: string | null; + sourceType: ClinicalSourceType; + canonicalLocation: SourceCanonicalLocation; + geography: { scope: SourceGeographyScope; label: string }; + topics: string[]; + publicationDate: string | null; + reviewDate: string | null; + expiryDate: string | null; + documentStatus: ClinicalSourceReferenceInput["documentStatus"]; + validationStatus: ClinicalSourceReferenceInput["validationStatus"]; + contentMode: SourceContentMode; + lifecycleStatus: SourceLifecycleStatus; + supersedes: string[]; + supersededBy: string[]; + usedBy: SourceUsage[]; + rating: ClinicalSourceRating; + warnings: SourceCatalogueWarning[]; +}; + +export type SourceCatalogueFilters = { + q: string; + bands: SourceQualityBand[]; + jurisdictions: SourceGeographyScope[]; + sourceTypes: ClinicalSourceType[]; + publishers: string[]; + topics: string[]; + lifecycleStatuses: SourceLifecycleStatus[]; + documentStatuses: ClinicalSourceReferenceInput["documentStatus"][]; + validationStatuses: ClinicalSourceReferenceInput["validationStatus"][]; + usedBy: AppModeId[]; + sort: "quality" | "title" | "currency"; +}; +``` + +- [ ] **Step 4: Implement deterministic identity, compatibility partitioning, rating and ordering** + +Create `src/lib/sources/catalogue-core.ts`. Use SHA-256 only for the opaque route ID; never place the full provisional reference text in a URL or log. Preserve its safe upstream display label in the catalogue so legacy academic references are actually findable, but never source that label from raw Supabase metadata or document content. + +```ts +import { createHash } from "node:crypto"; + +import { classifySourceAuthority, normalizeSourceAuthorityText } from "@/lib/source-authority-registry"; +import { normalizeSourceMetadata } from "@/lib/source-metadata"; +import { + SOURCE_RATING_WEIGHTS, + type ClinicalSourceCatalogueEntry, + type ClinicalSourceReferenceInput, + type ClinicalSourceRating, + type SourceCatalogueWarning, + type SourceGeographyScope, +} from "@/lib/sources/catalogue-types"; + +function opaqueSourceId(identity: string) { + return `src_${createHash("sha256").update(identity).digest("hex").slice(0, 20)}`; +} + +function safeHttpsUrl(value: string | null) { + if (!value) return null; + try { + const url = new URL(value); + if (url.protocol !== "https:") return null; + url.hash = ""; + return url.toString(); + } catch { + return null; + } +} + +function baseIdentity(input: ClinicalSourceReferenceInput) { + if (input.documentId) return `document:${input.documentId}`; + if (input.sourceId) return `source:${input.sourceId.trim().toLowerCase()}`; + const url = safeHttpsUrl(input.canonicalUrl); + if (url) return `url:${url}|version:${input.version ?? "unknown"}`; + if (input.publisher && input.title) { + return `title:${normalizeSourceAuthorityText(input.publisher)}|${normalizeSourceAuthorityText(input.title)}|${input.version ?? "unknown"}`; + } + return `provisional:${normalizeSourceAuthorityText(input.referenceText ?? input.title ?? "unresolved")}`; +} + +function compatibilityKey(input: ClinicalSourceReferenceInput) { + return [input.publisher, input.publisherCode, input.jurisdiction, input.version] + .map((value) => normalizeSourceAuthorityText(value)) + .join("|"); +} +``` + +Implement the exact scoring tables below. `classifySourceAuthority()` supplies reliability and geographic scope; do not infer either from URLs or prose. + +```ts +const ACCURACY = { approved: 25, locally_reviewed: 20, unverified: 5, unknown: 0 } as const; +const EVIDENCE = { + guideline: 20, + standard: 20, + legislation: 20, + regulatory: 20, + systematic_review: 18, + primary_study: 14, + professional_reference: 12, + consumer_reference: 8, + uploaded_document: 6, + dataset: 6, + other: 4, + unknown: 0, +} as const; +const AUSTRALIAN = { wa: 15, australian_national: 13, australian_state: 11, international: 6, unknown: 0 } as const; + +// Reliability: recognised official 20, recognised trusted 16, +// unclassified publisher with traceable identity 8, otherwise 0. +// Currency: current 15, review_due 8, unknown 4, outdated 0. +// Traceability: one point each for stable identity, version, a date, +// canonical location and at least one usage; maximum 5. +// Material uncertainty is provisional identity, unsafe location, metadata +// conflict, or validationStatus unverified/unknown. It forces band D. +// lifecycleStatus excluded forces band excluded before numeric thresholds. +``` + +Export `rateClinicalSource(input)`, `canonicalizeSourceReferences(inputs)` and `compareClinicalSources(left, right)`. Partition each `baseIdentity` group by `compatibilityKey`; when more than one partition exists, add `metadata_conflict` to every resulting entry. Merge and sort `aliases`, `topics`, `usedBy`, `supersedes`, `supersededBy` and warnings deterministically. + +- [ ] **Step 5: Implement URL-backed filters and derived facets** + +Create `src/lib/sources/catalogue-view.ts`. Parse repeated query parameters (`band`, `jurisdiction`, `type`, `publisher`, `topic`, `lifecycle`, `status`, `validation`, `usedBy`) against values present in the entries, default invalid values away, and support `sort=quality|title|currency`. Search only title, aliases, publisher and topics. + +```ts +export function deriveSourceCatalogueFacets(entries: readonly ClinicalSourceCatalogueEntry[]) { + return { + total: entries.length, + australian: entries.filter( + (entry) => entry.geography.scope !== "international" && entry.geography.scope !== "unknown", + ).length, + reviewRequired: entries.filter((entry) => entry.rating.band === "D").length, + inactiveOrExcluded: entries.filter((entry) => entry.lifecycleStatus !== "active").length, + topics: countValues(entries.flatMap((entry) => entry.topics)), + publishers: countValues(entries.map((entry) => entry.publisher).filter((value): value is string => Boolean(value))), + }; +} +``` + +- [ ] **Step 6: Run and refine the focused core tests** + +Run: `node scripts/run-vitest.mjs run tests/source-catalogue-core.test.ts` + +Expected: PASS with the six-weight, band, exclusion, bounded-Australian, deduplication, conflict and unsafe-location cases green. + +- [ ] **Step 7: Commit Task 1** + +```bash +git add src/lib/sources/catalogue-types.ts src/lib/sources/catalogue-core.ts src/lib/sources/catalogue-view.ts tests/source-catalogue-core.test.ts +git commit -m "feat(sources): define catalogue rating and identity" +``` + +--- + +### Task 2: Repository providers, automatic coverage and safe document projection + +**Files:** + +- Create: `src/lib/sources/repository-providers.ts` +- Create: `src/lib/sources/document-source-loader.ts` +- Create: `src/lib/sources/load-source-catalogue.ts` +- Create: `scripts/check-source-catalogue.ts` +- Create: `tests/source-catalogue-providers.test.ts` +- Create: `tests/source-document-loader.test.ts` +- Modify: `package.json` + +**Interfaces:** + +- Consumes: Task 1 `ClinicalSourceReferenceInput` and `canonicalizeSourceReferences()`, plus existing Dictionary, Factsheets, Formulation, Therapy, Specifiers, Forms/MHA, Medication, Services, DSM, calculator, Supabase authentication and owner/public query owners. +- Produces: `ClinicalSourceProvider`, `repositorySourceProviders`, `repositorySourceReferences()`, `loadVisibleDocumentSourceReferences()`, `loadSourceCatalogue()` and the offline `npm run check:source-catalogue` contract. + +- [ ] **Step 1: Write failing provider and document-access tests** + +Create `tests/source-catalogue-providers.test.ts` with the exact provider IDs and source-bearing paths below, assert every provider returns at least one valid reference and usage, assert all structured URLs are HTTPS or become `unsafe_location`, assert every dictionary source ID is represented, and assert Therapy/free-text source material remains provisional rather than being split into inferred publishers. + +```ts +const expectedProviders = { + dictionary: ["src/lib/dictionary-data.ts"], + factsheets: ["src/components/factsheets/factsheets-data.ts"], + formulation: ["src/data/formulation-content.json"], + therapies: ["src/data/therapies-source.json"], + specifiers: ["data/specifiers-content.json"], + forms: ["data/forms-page-snapshot.json"], + mha: ["data/mha-2014-sections.source.json"], + medications: ["data/medications-snapshot.json"], + services: ["data/services-snapshot.json"], + dsm: ["src/data/dsm-clinical-content.json"], + calculators: ["src/components/calculators/calculator-fixtures.ts"], +} as const; + +expect(Object.fromEntries(repositorySourceProviders.map((provider) => [provider.id, provider.sourcePaths]))).toEqual( + expectedProviders, +); +expect(repositorySourceReferences().every((reference) => reference.usage.recordId && reference.usage.field)).toBe(true); +``` + +Create `tests/source-document-loader.test.ts` with an injected Supabase query double and these cases: + +```ts +it("scopes anonymous reads to deliberately public documents", async () => { + const result = await loadVisibleDocumentSourceReferences({ + viewerId: async () => undefined, + query: () => queryDouble, + }); + expect(queryDouble.filters).toContainEqual(["is", "owner_id", null]); + expect(queryDouble.filters).toContainEqual(["eq", "metadata->>public_corpus", "true"]); + expect(result.references.every((reference) => reference.documentId)).toBe(true); +}); + +it("includes a signed-in owner's documents plus public documents", async () => { + await loadVisibleDocumentSourceReferences({ + viewerId: async () => "11111111-1111-4111-8111-111111111111", + query: () => queryDouble, + }); + expect(queryDouble.orFilter).toContain("owner_id.eq.11111111-1111-4111-8111-111111111111"); + expect(queryDouble.orFilter).toContain("metadata->>public_corpus.eq.true"); +}); + +it("returns only allowlisted catalogue fields", () => { + const [reference] = documentRowsToSourceReferences([ + { ...indexedDocument, storage_path: "private/path", metadata: { ...metadata, patient_name: "hidden" } }, + ]); + expect(JSON.stringify(reference)).not.toContain("private/path"); + expect(JSON.stringify(reference)).not.toContain("patient_name"); +}); + +it("excludes registry projections and non-indexed uploads", () => { + expect(documentRowsToSourceReferences([registryProjection, queuedUpload])).toEqual([]); +}); +``` + +- [ ] **Step 2: Run both tests to confirm the red state** + +Run: `node scripts/run-vitest.mjs run tests/source-catalogue-providers.test.ts tests/source-document-loader.test.ts` + +Expected: FAIL because the provider registry and document loader do not exist. + +- [ ] **Step 3: Implement one registered provider contract and all current repository adapters** + +Create `src/lib/sources/repository-providers.ts` and mark it `server-only`. Use this exact contract: + +```ts +export type ClinicalSourceProvider = { + id: + | "dictionary" + | "factsheets" + | "formulation" + | "therapies" + | "specifiers" + | "forms" + | "mha" + | "medications" + | "services" + | "dsm" + | "calculators"; + sourcePaths: readonly string[]; + references(): ClinicalSourceReferenceInput[]; +}; + +export const repositorySourceProviders: readonly ClinicalSourceProvider[] = [ + dictionaryProvider, + factsheetProvider, + formulationProvider, + therapyProvider, + specifierProvider, + formsProvider, + mhaProvider, + medicationProvider, + servicesProvider, + dsmProvider, + calculatorProvider, +]; + +export function repositorySourceReferences() { + return repositorySourceProviders.flatMap((provider) => provider.references()); +} +``` + +Implement adapters conservatively: + +- Dictionary: use `dictionarySources`; collect usages from `dictionaryEntries.sourceRefs`, distinction refs and comparison refs; map `organisation`, `region` and `accessedOn` without treating `clinicalApproval: pending` as approval. +- Factsheets: use exported `factsheets`; each sheet's `sources` produces a usage with `modeId: "factsheets"`, record slug/title and field `sources`; `tag` maps only to the explicit source-type vocabulary and unknown tags stay `unknown`. +- Formulation: use `formulationSourceLibrary` and every mechanism's source IDs; link source-library entries to `modeId: "formulation"`; missing publisher, dates and validation remain unknown. +- Therapy: import `src/data/therapies-source.json` server-side; use each explicit `sources[]` item as a provisional uploaded-document reference; do not split names mentioned inside `reference`; `reviewChecklist.sourceChecked === false` and `reviewStatus === "needs_review"` force unverified D. +- Specifiers: emit the seven exact `authoritativeSources()` entries; separately emit one provisional D entry for each distinct `sourceFamily` used by review records because rows do not identify which authoritative URL supports them. +- Forms: import `data/forms-page-snapshot.json`; project each `sourceDocuments[]` record by its stable `id`, safe title/file name, kind and Forms usage only. Do not copy excerpts, extracted text, local artifact paths or generated prose. Unknown authority and validation remain review debt. +- MHA: use `mhaActMetadata.sourceUrl`, `actVersion` and `actAsAt`; classify as WA legislation and record application usage under Forms without copying section text. +- Medication: traverse `loadMedicationSnapshot()` and emit each row whose section title is `Sources` or whose key is `Source Review` as one provisional legacy reference associated with that medication. Do not split publisher or product names from its prose; every distinct row remains visible as D until upstream metadata becomes structured. +- Services: import the production service catalogue. Emit one reference per explicit `public_source_urls[]` URL and one provisional reference per distinct `source_documents[]` identity, preserving every service usage. Ignore `deep_research_citation_tokens`, `search_text`, contact details and analyst notes because they are neither canonical source identities nor safe metadata. +- DSM: import `src/data/dsm-clinical-content.json` server-side and emit its explicit `source_repository` plus export version/generated date as one structured dataset source used by each diagnosis. Do not pretend the snapshot identifies a licensed manual edition or publisher when it does not. +- Calculators: use exported `calculators`; emit each exact `source` string as a provisional reference used by that calculator. Do not infer DOI, journal, evidence type, approval or publisher from the citation prose. + +- [ ] **Step 4: Implement the server-only accessible-document loader** + +Create `src/lib/sources/document-source-loader.ts` with an injectable query seam. Use `createSupabaseServerClient()` only to resolve the current user and `createAdminClient()` only for the established explicitly-scoped document query. Apply `withOwnerReadScope()` before awaiting the query. + +```ts +const DOCUMENT_SOURCE_COLUMNS = "id,owner_id,title,file_name,status,metadata,updated_at"; + +function createDocumentSourceQuery() { + return createAdminClient().from("documents").select(DOCUMENT_SOURCE_COLUMNS); +} + +type DocumentSourceQuery = ReturnType; + +export type DocumentSourceLoadResult = { + references: ClinicalSourceReferenceInput[]; + availability: "available" | "unavailable"; +}; + +export type DocumentSourceLoaderDependencies = { + viewerId(): Promise; + query(): DocumentSourceQuery; +}; + +const defaultDocumentSourceLoaderDependencies: DocumentSourceLoaderDependencies = { + async viewerId() { + const client = await createSupabaseServerClient(); + if (!client) return undefined; + const { data, error } = await client.auth.getUser(); + return error ? undefined : data.user?.id; + }, + query: createDocumentSourceQuery, +}; + +export async function loadVisibleDocumentSourceReferences( + dependencies: DocumentSourceLoaderDependencies = defaultDocumentSourceLoaderDependencies, +): Promise { + try { + const viewerId = await dependencies.viewerId(); + const query = withOwnerReadScope(dependencies.query(), viewerId); + const { data, error } = await query.eq("status", "indexed").order("updated_at", { ascending: false }); + if (error) return { references: [], availability: "unavailable" }; + return { references: documentRowsToSourceReferences(data ?? []), availability: "available" }; + } catch { + return { references: [], availability: "unavailable" }; + } +} +``` + +`documentRowsToSourceReferences()` must call `normalizeSourceMetadata(row.metadata)`, exclude `source_kind === "registry_record"`, emit internal `/documents/` locations, and copy only title/file-name fallback, publisher/code, jurisdiction, version, dates, document/validation status and safe topic labels already present in structured metadata. Do not return `owner_id` or raw metadata. + +- [ ] **Step 5: Assemble the complete server catalogue with availability state** + +Create `src/lib/sources/load-source-catalogue.ts`: + +```ts +import "server-only"; + +export type LoadedSourceCatalogue = { + entries: ClinicalSourceCatalogueEntry[]; + hostedDocuments: "available" | "unavailable"; +}; + +export async function loadSourceCatalogue(): Promise { + const documents = await loadVisibleDocumentSourceReferences(); + return { + entries: canonicalizeSourceReferences([...repositorySourceReferences(), ...documents.references]), + hostedDocuments: documents.availability, + }; +} +``` + +- [ ] **Step 6: Add the offline automatic-coverage check** + +Create `scripts/check-source-catalogue.ts`. It must import only repository providers, never Supabase. It fails on duplicate provider IDs, duplicate registered paths, a provider with no references, dangling dictionary/formulation source IDs, missing coverage for any calculator source, medication Source Review row, service public URL/source-document identity, Forms source-document ID or DSM `source_repository`, unsafe structured URLs or a reference without usage. It reports but does not fail on missing publisher/version/dates/jurisdiction/evidence type/validation; those counts are review debt. + +This is the automatic-addition boundary: adding a record or source to any registered production owner above changes the catalogue on the next request with no catalogue edit. Adding a genuinely new source-bearing dataset is intentionally fail-closed work: its provider ID/path must be registered and tested rather than being silently scraped from prose. This preserves automatic capture without broad repository URL scanning or invented clinical metadata. + +Add to `package.json`: + +```json +"check:source-catalogue": "node scripts/run-tsx.mjs scripts/check-source-catalogue.ts" +``` + +Keep the script standalone for fast Sources work. Automatic enforcement comes from `tests/source-catalogue-providers.test.ts`, which is already included by the repository's full `npm test`/`verify:cheap` path. Do not modify the gate manifest, CI workflow or `verify-pr-local` selector merely to call the same provider contract twice. + +- [ ] **Step 7: Run the focused provider, loader and offline coverage checks** + +Run: + +```bash +node scripts/run-vitest.mjs run tests/source-catalogue-core.test.ts tests/source-catalogue-providers.test.ts tests/source-document-loader.test.ts +npm run check:source-catalogue +``` + +Expected: all tests PASS; the offline check reports captured source counts and review-debt counts without contacting Supabase. + +- [ ] **Step 8: Commit Task 2** + +```bash +git add package.json scripts/check-source-catalogue.ts src/lib/sources/repository-providers.ts src/lib/sources/document-source-loader.ts src/lib/sources/load-source-catalogue.ts tests/source-catalogue-providers.test.ts tests/source-document-loader.test.ts +git commit -m "feat(sources): aggregate governed source providers" +``` + +--- + +### Task 3: Sources application mode, routes and accessible interface + +**Files:** + +- Create: `src/components/sources/sources-catalogue-client.tsx` +- Create: `src/components/sources/sources-pages.tsx` +- Create: `src/app/(search-app)/sources/page.tsx` +- Create: `src/app/(search-app)/sources/topics/page.tsx` +- Create: `src/app/(search-app)/sources/publishers/page.tsx` +- Create: `src/app/(search-app)/sources/method/page.tsx` +- Create: `src/app/(search-app)/sources/[sourceId]/page.tsx` +- Modify: `src/app/(search-app)/dictionary/sources/page.tsx` +- Modify: `src/lib/app-modes.ts` +- Modify: `src/lib/category-identity.ts` +- Modify: `src/lib/category-identity-icons.ts` +- Modify: `src/lib/ui-copy.ts` +- Modify: `src/lib/universal-search-mode-context.ts` +- Modify: `src/lib/tools-catalog.ts` +- Modify: `src/lib/mode-secondary-navigation.ts` +- Modify: `src/components/mode-nav/registry-mode-nav.tsx` +- Modify: `src/components/clinical-dashboard/ClinicalSidebar.tsx` +- Modify: `src/components/clinical-dashboard/use-sidebar-pins.ts` +- Modify: `src/lib/search-shell-props.ts` +- Modify: `src/lib/information-pages.ts` +- Modify: `tests/app-modes.test.ts` +- Modify: `tests/category-identity.test.ts` +- Modify: `tests/ui-copy.test.ts` +- Modify: `tests/tools-catalog.test.ts` +- Modify: `tests/mode-secondary-navigation.test.ts` +- Modify: `tests/search-shell-props.test.ts` +- Modify: `tests/shared-home-empty-state.dom.test.tsx` +- Modify: `tests/sidebar-pins.test.ts` +- Modify: `tests/sidebar-production.dom.test.tsx` +- Modify: `tests/route-reachability.test.ts` +- Create: `tests/sources-mode.dom.test.tsx` + +**Interfaces:** + +- Consumes: Task 2 `loadSourceCatalogue()` and Task 1 filters/facets. +- Produces: application mode ID `sources`, routes `/sources`, `/sources/topics`, `/sources/publishers`, `/sources/method`, `/sources/[sourceId]`, redirect `/dictionary/sources?*` to `/sources?usedBy=dictionary`, and accessible read-only catalogue components. + +- [ ] **Step 1: Restore/link dependencies and read the version-matched Next.js guidance before route code** + +Read `docs/agents/codex-dependency-shortcut.md` and use its exact-lock shortcut if available. If dependencies must be restored, wait for the repository run coordinator and run the documented restoration command; do not install during another worktree's test/build lease. + +Then locate and read the installed Next.js App Router pages for async `params`, async `searchParams`, Server Components and redirects: + +```bash +rg -n "params.*Promise|searchParams.*Promise|redirect\(" node_modules/next/dist/docs -g "*.md" -g "*.mdx" +``` + +Expected: implementation follows the installed Next version rather than remembered APIs. + +- [ ] **Step 2: Write failing mode-wiring and DOM tests** + +Extend exhaustive mode tests to require 16 modes, `appModeHomeHref("sources", { query: "RANZCP", run: true }) === "/sources?q=RANZCP&run=1"`, a unique Sources icon, shared-home copy, a Tools catalogue record, the four secondary destinations and Sources in the sidebar's More modes/pinnable set without changing the six default pins. + +Create `tests/sources-mode.dom.test.tsx` using a small fixture catalogue. Assert: + +```ts +expect(screen.getByRole("heading", { level: 1, name: "Sources" })).toBeVisible(); +expect(screen.getByText("A · Preferred")).toBeVisible(); +expect(screen.getByLabelText("Filter by quality band")).toHaveValue(""); +expect(screen.getByLabelText("Sort sources")).toHaveValue("quality"); +expect(screen.getByRole("status")).toHaveTextContent("2 sources"); +expect(screen.getByText("Hosted document sources are temporarily unavailable")).toBeVisible(); +expect(screen.queryByText(/storage_path|owner_id|patient/i)).not.toBeInTheDocument(); +``` + +Add interaction cases for `usedBy=dictionary`, band and publisher filters, quality/title sorting, reset, empty state, topic links, publisher grouping, Method weights and detail-page three-location labels. + +- [ ] **Step 3: Run mode and DOM tests to confirm the red state** + +Run: + +```bash +node scripts/run-vitest.mjs run tests/app-modes.test.ts tests/category-identity.test.ts tests/ui-copy.test.ts tests/shared-home-empty-state.dom.test.tsx tests/tools-catalog.test.ts tests/mode-secondary-navigation.test.ts tests/search-shell-props.test.ts tests/sidebar-pins.test.ts tests/sidebar-production.dom.test.tsx tests/sources-mode.dom.test.tsx +``` + +Expected: FAIL because Sources is not yet an app mode and its components do not exist. + +- [ ] **Step 4: Wire Sources through the existing exhaustive mode owners** + +Make these exact additions: + +- `appModeIds`: append `"sources"`. +- `appModeDefinitions`: label `Sources`, description `Ranked clinical source catalogue and traceability`, href `/sources`, local `tools` search, placeholder `Search sources, publishers, or topics...`, result heading `Sources`, next step `Filter by quality, location, publisher, topic, or usage`. +- `namespaceIsolatedModes`: add `sources`. +- `CATEGORY_ICON_KEYS`: add `libraryBig`; bind it to Lucide `LibraryBig`; use it for both `APP_MODE_ICON.sources` and new `TOOL_ICON["source-catalogue"]` while preserving uniqueness within each axis. +- `APP_MODE_ACCENT.sources`: use `source`. +- `sharedHomePresentation.sources`: title `Sources`, subtitle `Clinical source catalogue.`, suggestions `Australian guidelines`, `RANZCP`, `review required`. +- `preferredDomainsByMode.sources`: `[]` because Sources searches its own catalogue and is not a universal-search domain. +- `ToolCatalogId`: add `source-catalogue`; add a ready, source-backed reference-area record linking to `/sources`. +- `sidebarMoreModeIds`: append `sources`, making the mode reachable from the existing sidebar without adding a second navigation owner. +- `pinnableSidebarModeIds`: append `sources`; leave `defaultSidebarPinnedModeIds` unchanged so the new mode is discoverable and user-pinnable without displacing a current default. + +Add the secondary registry and active-route logic: + +```ts +sources: [ + { id: "catalogue", label: "Catalogue", href: "/sources" }, + { id: "topics", label: "Topics", href: "/sources/topics" }, + { id: "publishers", label: "Publishers", href: "/sources/publishers" }, + { id: "method", label: "Method", href: "/sources/method" }, +], +``` + +Adopt `sources` into `MODE_NAV_ADOPTED_MODES`, use density `balanced-four`, and map icons `catalogue: LibraryBig`, `publishers: Landmark`, `method: Scale`. Preserve `q` and `usedBy` when navigating Catalogue/Topics/Publishers; Method stays clean. Return active IDs for the four exact routes and no active item on `/sources/[sourceId]`. + +In `searchShellPropsForPathname`, resolve `/sources*` to `initialMode: "sources"` and `desktopSearchPlacement: "hero"`; hide the composer only on `/sources/method` and source detail routes. In `information-pages.ts`, classify only `/sources/[sourceId]` as an information page and exclude `topics`, `publishers` and `method` from the dynamic-detail rule. + +- [ ] **Step 5: Build the single catalogue client surface** + +Create `src/components/sources/sources-catalogue-client.tsx` as a client component. Read `q` and filters from `useSearchParams`; update filters with `router.replace`; never render another search input because the shared composer owns `q`. + +Render: + +- one `h1` Sources heading; +- four `
` count tiles for visible/all, Australian, review-required and inactive/excluded; +- native labelled selects for band, jurisdiction, source type, publisher, topic, lifecycle, currentness, validation, application usage and sort; +- a reset button only when a filter is active; +- a restrained `

` result count; +- a semantic desktop table at `md` and a semantic phone list below `md`, with the same band, title, publisher, location, currency, warnings and usage information; +- `` for detail navigation; +- no raw score as the dominant label: show `A · Preferred`, `B · Strong`, `C · Supplementary`, `D · Review required` or `Excluded`, with the numeric score secondary; +- a degraded-state notice when `hostedDocuments === "unavailable"`. + +Use native controls with `min-h-12`; provide visible labels and do not rely on colour alone. + +- [ ] **Step 6: Build the shared page renderers and route modules** + +Create `src/components/sources/sources-pages.tsx` with these exported server/client boundaries: + +```ts +export async function SourcesCataloguePage(): Promise; +export async function SourcesTopicsPage(): Promise; +export async function SourcesPublishersPage(): Promise; +export function SourcesMethodPage(): ReactNode; +export async function SourceDetailPage({ sourceId }: { sourceId: string }): Promise; +``` + +All pages use `InformationPageShell`. Topics and Publishers derive from Task 1 facets and link back to URL-filtered Catalogue results. Method prints the exact weights, thresholds, exclusion-first rule, bounded Australian preference, missing-data policy and the statement that this is not RAG relevance or patient-specific guidance. Detail renders identity, canonical/geographic/application locations, all six rating dimensions, dates, lifecycle, content mode, version relations, warnings and usages; render an outbound anchor only for safe URL locations and an internal Link for document locations. + +Create route modules with static metadata and async Next route props. `/sources/[sourceId]` calls `notFound()` when the entry is not visible to the current user. Do not use `generateStaticParams()` because private document entries are request-scoped. + +Replace `src/app/(search-app)/dictionary/sources/page.tsx` with: + +```ts +import { redirect } from "next/navigation"; + +export default function DictionarySourcesRedirect() { + redirect("/sources?usedBy=dictionary"); +} +``` + +Retain `src/components/dictionary/dictionary-sources-page.tsx` in this focused change. Removing an exported module requires the repository's dead-code-candidate workflow and is not necessary for the redirect; treat deletion as a separate follow-up only if that gate authorizes it. + +- [ ] **Step 7: Run focused wiring, route and DOM tests** + +Run: + +```bash +node scripts/run-vitest.mjs run tests/app-modes.test.ts tests/category-identity.test.ts tests/ui-copy.test.ts tests/shared-home-empty-state.dom.test.tsx tests/tools-catalog.test.ts tests/mode-secondary-navigation.test.ts tests/search-shell-props.test.ts tests/sidebar-pins.test.ts tests/sidebar-production.dom.test.tsx tests/route-reachability.test.ts tests/sources-mode.dom.test.tsx +``` + +Expected: PASS with 16 modes, four Sources tabs, the Dictionary redirect, reachable routes, one shared composer owner and accessible catalogue interactions. + +- [ ] **Step 8: Commit Task 3** + +```bash +git add 'src/app/(search-app)/sources' 'src/app/(search-app)/dictionary/sources/page.tsx' src/components/sources src/components/mode-nav/registry-mode-nav.tsx src/components/clinical-dashboard/ClinicalSidebar.tsx src/components/clinical-dashboard/use-sidebar-pins.ts src/lib/app-modes.ts src/lib/category-identity.ts src/lib/category-identity-icons.ts src/lib/ui-copy.ts src/lib/universal-search-mode-context.ts src/lib/tools-catalog.ts src/lib/mode-secondary-navigation.ts src/lib/search-shell-props.ts src/lib/information-pages.ts tests/app-modes.test.ts tests/category-identity.test.ts tests/ui-copy.test.ts tests/shared-home-empty-state.dom.test.tsx tests/tools-catalog.test.ts tests/mode-secondary-navigation.test.ts tests/search-shell-props.test.ts tests/sidebar-pins.test.ts tests/sidebar-production.dom.test.tsx tests/route-reachability.test.ts tests/sources-mode.dom.test.tsx +git commit -m "feat(sources): add source catalogue mode" +``` + +--- + +### Task 4: Browser proof, generated documentation and bounded handoff + +**Files:** + +- Create: `tests/ui-sources.spec.ts` +- Modify: `tests/ui-dictionary.spec.ts` +- Modify: `scripts/playwright-pr-shards.mjs` +- Modify: `docs/codebase-index.md` +- Modify only generated files changed by: `npm run docs:update` + +**Interfaces:** + +- Consumes: completed Sources mode from Tasks 1–3 and the repository test coordinator. +- Produces: focused browser evidence, route/documentation synchronization, final diff review and an implementation handoff with provider/hosted checks still explicitly gated. + +- [ ] **Step 1: Write the focused browser journey** + +Remove `/dictionary/sources` from the old Dictionary page matrix, because it no longer renders `dictionary-sources-main`. Create `tests/ui-sources.spec.ts` using the same external-request blocker and overflow helper as `tests/ui-dictionary.spec.ts`; import `AxeBuilder` from `@axe-core/playwright`. Cover the redirect plus these exact journeys: + +```ts +test("Dictionary sources redirects into the Sources catalogue", async ({ page }) => { + await page.goto("/dictionary/sources", { waitUntil: "domcontentloaded" }); + await expect(page).toHaveURL(/\/sources\?usedBy=dictionary$/); + await expect(page.getByLabel("Filter by application usage")).toHaveValue("dictionary"); +}); + +test("@critical Sources catalogue filters and opens traceability", async ({ page }) => { + await page.goto("/sources?usedBy=dictionary", { waitUntil: "domcontentloaded" }); + await expect(page.getByRole("heading", { level: 1, name: "Sources" })).toBeVisible(); + await expect(page.getByLabel("Filter by application usage")).toHaveValue("dictionary"); + await page.getByLabel("Filter by quality band").selectOption("D"); + await expect(page.getByRole("status")).toContainText("source"); + await page + .getByRole("link", { name: /view source details/i }) + .first() + .click(); + await expect(page.getByRole("heading", { level: 2, name: "Source locations" })).toBeVisible(); + await expect(page.getByText("Application location")).toBeVisible(); +}); + +test("Sources remains operable at phone width and under accessibility media", async ({ + page, + browserName, +}, testInfo) => { + test.skip(browserName !== "chromium", "forced-colors emulation is Chromium-only"); + await page.setViewportSize({ width: 320, height: 760 }); + await page.emulateMedia({ reducedMotion: "reduce", forcedColors: "active" }); + await page.goto("/sources"); + await expect(page.getByTestId("sources-catalogue-main")).toBeVisible(); + await page.keyboard.press("Tab"); + await expect(page.locator(":focus-visible")).toHaveCount(1); + const overflow = await page.evaluate(() => document.documentElement.scrollWidth - window.innerWidth); + expect(overflow).toBeLessThanOrEqual(2); + const axe = await new AxeBuilder({ page }).withTags(["wcag2a", "wcag2aa", "wcag21a", "wcag21aa"]).analyze(); + await testInfo.attach("sources-axe", { + body: JSON.stringify(axe.violations, null, 2), + contentType: "application/json", + }); + expect( + axe.violations.filter((violation) => violation.impact === "critical" || violation.impact === "serious"), + ).toEqual([]); +}); +``` + +Add `tests/ui-sources.spec.ts` to an appropriate shard in `scripts/playwright-pr-shards.mjs`; do not add it to mockup projects. + +- [ ] **Step 2: Start the verified local app and run only the Sources browser file** + +Run: `npm run ensure` + +Use only the printed URL after `/api/local-project-id` confirms this project. + +Run: `node scripts/run-playwright.mjs tests/ui-sources.spec.ts --project=chromium` + +Expected: PASS for Catalogue/detail navigation, 320px overflow, keyboard focus, reduced motion, forced colours and serious/critical axe violations. + +- [ ] **Step 3: Synchronize route documentation** + +Add a concise Sources entry to `docs/codebase-index.md`, then run: `npm run docs:update` + +Inspect the generated diff. Keep only the documentation, site-map and inventory changes required by the new production routes; do not absorb unrelated snapshots or concurrent work. + +Run: + +```bash +npm run docs:check-index +npm run sitemap:check +git diff --check +``` + +Expected: all three PASS. + +- [ ] **Step 4: Run the final offline source and focused domain checks** + +Run: + +```bash +npm run check:source-catalogue +node scripts/run-vitest.mjs run tests/source-catalogue-core.test.ts tests/source-catalogue-providers.test.ts tests/source-document-loader.test.ts tests/sources-mode.dom.test.tsx tests/app-modes.test.ts tests/category-identity.test.ts tests/ui-copy.test.ts tests/shared-home-empty-state.dom.test.tsx tests/tools-catalog.test.ts tests/mode-secondary-navigation.test.ts tests/search-shell-props.test.ts tests/sidebar-pins.test.ts tests/sidebar-production.dom.test.tsx tests/route-reachability.test.ts +``` + +Expected: PASS. This is local/offline proof only; it does not establish hosted Supabase completeness or production readiness. + +- [ ] **Step 5: Confirm the RAG and privacy boundaries in the final diff** + +Run: + +```bash +git diff --name-only 058693b97 -- | rg "^(src/lib/rag/|src/app/api/(ask|search)|supabase/migrations/)" +rg -n "document_chunks|embedding|rag_queries|patient|storage_path|owner_id" src/components/sources src/lib/sources +``` + +Expected: the first command prints nothing. The second may find only explicit privacy assertions/tests or server-side scoping; it must find no browser projection of prohibited fields. + +- [ ] **Step 6: Consult the gate arbiter and buy one broad local verdict at most** + +Run: `npm run arbiter -- verify:pr-local` + +- If the verdict is `RUN`, execute `npm run verify:pr-local` once and record the decisive output. +- If the verdict is `DEFER`, report `deferred to CI` with the arbiter's evidence; do not call it passed. +- If the verdict is `PROVEN`, report the exact reused receipt/SHA; do not rerun it. + +Do not run live RAG evaluations: this change does not alter retrieval or answers. Do not run `npm run check:production-readiness`, `npm run audit:source-governance`, any live Supabase audit or provider command unless the user separately authorizes that exact connected check. + +- [ ] **Step 7: Review the complete diff and commit Task 4** + +Inspect `git status --short`, `git diff --stat`, `git diff` and `git diff --check`. Confirm no raw metadata, document content, RAG change, migration, debug output, placeholder, duplicate navigation owner or unrelated file is included. + +```bash +git add tests/ui-sources.spec.ts tests/ui-dictionary.spec.ts scripts/playwright-pr-shards.mjs docs/codebase-index.md docs/site-map.md docs/scripts-index.md +git commit -m "test(sources): verify catalogue routes and accessibility" +``` + +Stage only generated documentation files that actually changed. Do not push, open a PR, deploy or run connected checks. + +## Completion Evidence + +At handoff, report: + +- exact source counts by provider and D-band review-debt count from `check:source-catalogue`; +- exact focused Vitest and Playwright commands with results; +- whether `verify:pr-local` ran, deferred or reused proof; +- that Supabase document metadata was tested locally through injected fixtures; +- that no live Supabase completeness audit, production-readiness gate, RAG evaluation, migration, deployment, push or PR was performed; +- the branch, local commits, final worktree status and any residual legacy-source debt. + +## Residual Risk Boundaries + +- Free-text therapy and specifier source families remain provisional D entries until upstream content supplies exact structured citations. +- The provider registry automatically incorporates new references added to registered source-bearing schemas. A genuinely new source-bearing dataset must declare a provider and source path; the offline check rejects an invalid or empty provider but does not infer arbitrary new schemas. +- Local fixture proof establishes access projection logic, not current hosted catalogue completeness. A metadata-only hosted read remains a separately authorised acceptance step. +- Catalogue rating is deterministic organisation, not clinical endorsement, patient-specific guidance or evidence of factual accuracy. diff --git a/docs/superpowers/specs/2026-09-01-sources-mode-design.md b/docs/superpowers/specs/2026-09-01-sources-mode-design.md new file mode 100644 index 0000000000..4ddd7f59e8 --- /dev/null +++ b/docs/superpowers/specs/2026-09-01-sources-mode-design.md @@ -0,0 +1,204 @@ +# Sources Mode and Clinical Source Catalogue Design + +**Status:** Approved design, written 2026-09-01 against `058693b97`. + +## Outcome + +Create a read-only **Sources** mode at `/sources` that catalogues every production academic or clinical information source used by the application. It organises sources by topic, publisher, location, status and quality; explains a deterministic ranking; retains every known usage location; and automatically incorporates future structured source references. + +This feature does not search for new sources, edit source metadata, change RAG retrieval or ranking, copy source content, or claim that an unreviewed source is clinically accurate. + +## Scope + +Included sources are academic and clinical information authorities used by production content, including: + +- uploaded or indexed clinical documents visible to the current user; +- structured references used by Dictionary, Therapy, Medication, Forms, Services, DSM, Specifiers, Formulation, calculators and other production clinical catalogues; +- legislation, regulatory material, guidelines, standards, systematic reviews, primary studies, professional references and approved link-only references; and +- incomplete or legacy source references, which remain visible as review-required rather than being omitted or automatically trusted. + +Excluded from discovery are build documentation, developer documentation, tests, fixtures used only by tests, mockups, design references, package metadata, issue trackers and incidental URLs in prose that is not a production clinical source field. + +## Information architecture + +Sources is a namespace-isolated application mode with the visible label **Sources** and subtitle **Clinical source catalogue**. + +| Route | Purpose | +| --------------------- | ------------------------------------------------------------------------------- | +| `/sources` | Ranked catalogue, summary counts, search, sorting and filters | +| `/sources/topics` | Clinical topics with source counts and direct filtered catalogue links | +| `/sources/publishers` | Publisher and authority coverage, grouped by jurisdiction | +| `/sources/method` | Plain-language rating method, limitations and status definitions | +| `/sources/[sourceId]` | One source's identity, locations, rating breakdown, status, versions and usages | + +The secondary mode navigation is **Catalogue · Topics · Publishers · Method**. The mode reuses `app-modes.ts`, `RegistryModeNav`, the shared mode composer, the tools catalogue, universal navigation, information-page shells, responsive tokens and existing accessibility contracts. It does not create parallel navigation or search chrome. + +`/dictionary/sources` redirects to `/sources?usedBy=dictionary`, preserving the existing entry point while making `/sources` the canonical catalogue. + +## Catalogue contract + +One canonical entry represents one distinct document or resource version. Entries are grouped by publisher; older, withdrawn and superseded versions are retained with explicit inactive or excluded status. + +```ts +type ClinicalSourceCatalogueEntry = { + id: string; + title: string; + version: string | null; + publisher: string | null; + publisherCode: string | null; + sourceType: ClinicalSourceType; + canonicalLocation: SourceCanonicalLocation; + jurisdiction: SourceJurisdiction; + topics: string[]; + publicationDate: string | null; + reviewDate: string | null; + expiryDate: string | null; + documentStatus: "current" | "review_due" | "outdated" | "unknown"; + validationStatus: "approved" | "locally_reviewed" | "unverified" | "unknown"; + contentMode: "indexed_content" | "link_only" | "metadata_only"; + lifecycleStatus: "active" | "inactive" | "excluded"; + supersedes: string[]; + supersededBy: string[]; + usedBy: SourceUsage[]; + rating: ClinicalSourceRating; + warnings: SourceCatalogueWarning[]; +}; +``` + +The three source locations are all retained and shown: + +1. **Canonical location:** allowlisted HTTPS URL, accessible document route, or structured dataset identity. +2. **Geographic location:** WA/local, Australian national, another Australian state, international or unknown. +3. **Application location:** every clinical mode, record or dataset that uses the source. + +Private source entries obey the same owner/public visibility rules as their documents. The catalogue must not expose inaccessible private document titles, metadata, counts or usage relationships. + +## Identity and deduplication + +Identity is deterministic and conservative: + +1. an existing stable document or source ID is preferred; +2. otherwise use a canonical URL plus explicit version; +3. otherwise use publisher, normalised title and explicit version; +4. otherwise retain the normalised reference text as a provisional review-required identity. + +Aliases and repeated citations resolve to one canonical entry. `usedBy` retains every occurrence. Conflicting publishers, jurisdictions or versions do not merge; they produce separate entries and a warning. + +Titles, filenames and source prose cannot grant authority. Authority comes only from existing structured publisher metadata or the canonical authority registry. + +## Rating and ranking + +The catalogue ranking is organisational only and never enters RAG retrieval, answer generation or clinical decision ranking. + +Every entry exposes six deterministic dimensions totalling 100 points: + +| Dimension | Weight | Meaning | +| ------------------------ | -----: | --------------------------------------------------------------------------------- | +| Accuracy assurance | 25 | Evidence that the source version was reviewed, validated or explicitly checked | +| Reliability | 20 | Publisher authority, provenance and independence | +| Evidence quality | 20 | Guideline, systematic review, study, standard, professional review or weaker type | +| Currency | 15 | Publication, review, expiry and supersession state | +| Australian applicability | 15 | WA/local, Australian national, other Australian jurisdiction or international | +| Traceability | 5 | Identity, version, date, canonical location and usage completeness | + +User-facing bands are: + +- **A · Preferred:** 85–100 +- **B · Strong:** 70–84 +- **C · Supplementary:** 50–69 +- **D · Review required:** below 50, or any material identity/verification uncertainty +- **Excluded:** rejected, decommissioned, forbidden, withdrawn, or superseded by an identified current replacement + +Hard exclusions run before the score. A high location or authority score cannot rescue an excluded source. Australian applicability is bounded: equally credible Australian sources are preferred, but weak Australian material does not automatically outrank substantially stronger international evidence. + +The interface leads with the band and dimension explanations, not a percentage. A numeric score is secondary and exists to make sorting reproducible. The label is **Accuracy assurance**, never a claim that software measured factual truth. + +Missing fields remain `unknown`. The catalogue never invents publisher, location, currency, evidence type or approval from prose. Newly discovered incomplete sources appear automatically as **D · Review required**, unless an existing governance rule requires exclusion. + +## Automatic future coverage + +The automatic system has three layers: + +1. **Typed reference contract.** New structured production clinical information uses one `ClinicalSourceReferenceInput` shape for source ID, title, publisher, URL/document ID, version, dates, jurisdiction, evidence type and usage context. +2. **Adapters for existing sources.** Narrow adapters project current repository datasets and accessible Supabase document metadata into the same input. Free-text legacy references are preserved as provisional entries rather than parsed into invented citations. +3. **Coverage enforcement.** A focused repository check inventories recognised production source-bearing paths, validates every structured reference, rejects dangling source IDs, and reports provisional or incomplete entries. Known source-bearing schemas cannot add a new source field without an adapter or an explicit exclusion reason. + +The catalogue is a generated view over existing source ownership, not a second manually maintained master file. Adding or changing upstream structured source metadata therefore changes the catalogue and rating automatically. No in-app catalogue editor is included. + +The check distinguishes: + +- **failure:** a structured production source reference cannot be normalised, has an unsafe location, or bypasses a registered source-bearing contract; +- **review debt:** a source is captured but publisher, version, dates, jurisdiction, evidence type or validation remains unknown; and +- **excluded scope:** tests, mockups, developer docs and non-clinical build references. + +## Supabase document projection + +The Sources mode consumes metadata only for documents visible to the current user, using the configured runtime Supabase project and existing RLS/owner-public scope. It does not require a new table or migration. + +Allowed projection fields are limited to document identity, safe title/file name, accessible source route, source metadata, status, dates and safe clinical labels needed for catalogue topics. Document text, chunks, embeddings, summaries, generated answers, queries, user identifiers, storage paths and patient data are excluded. + +When Supabase is unavailable, the repository catalogue remains available and the interface truthfully labels the hosted-document portion unavailable. It does not present a partial result as complete. + +## Interface behaviour + +### Catalogue + +- Default sort: quality band, score, Australian applicability, currency, then title. +- Search: title, publisher, aliases and topics. +- Filters: band, jurisdiction, source type, publisher, topic, lifecycle status, currentness, validation and application usage. +- Desktop: dense accessible table/list with explicit column labels. +- Phone: stacked source rows with the same information hierarchy and 48px controls. +- Counts distinguish all visible sources, Australian sources, review-required sources and excluded/inactive sources. + +### Topics and publishers + +These are derived views, not manually maintained collections. Topics come from existing structured source labels and the clinical records in `usedBy`. Publishers use the canonical authority registry when recognized and remain unclassified when ambiguous. + +### Source details + +The detail page shows identity, three locations, rating explanations, warnings, dates, lifecycle, content mode, version relationships and usages. It links to the canonical location only when access is permitted. It does not reproduce source excerpts or document content. + +### Method + +The method page publishes the weights, bands, hard exclusions, Australian preference, missing-data behavior and limitations. It explicitly states that catalogue quality is not query relevance, patient-specific guidance, specialist sign-off or RAG ranking. + +## Accessibility and responsive behaviour + +- Reuse existing shared mode and information-page navigation owners. +- Preserve one shared composer and one phone header collapse owner. +- Every filter, sort and source action has an accessible name and keyboard path. +- Bands and warnings use text and icons as well as colour. +- Search/filter result counts use restrained live-region updates. +- Verify phone and desktop layouts, keyboard navigation, focus, reduced motion and forced colours. + +## Error and degraded states + +- Missing metadata: captured as review debt with exact field reasons. +- Ambiguous identity: separate provisional source; never silently merge. +- Unsafe or malformed URL: no outbound link; review warning. +- Supabase unavailable: repository sources remain, hosted source coverage is labelled unavailable. +- Access denied: source is absent without leaking its identity or aggregate count. +- Empty filtered state: preserve filters and offer a clear reset. + +## Verification + +The smallest credible evidence includes: + +- unit tests for normalisation, identity, deduplication, score dimensions, bands, hard exclusions, Australian ordering and missing metadata; +- adapter and coverage tests for recognised production source-bearing datasets; +- access-projection tests proving private source metadata is not leaked; +- mode, navigation, redirect and route-reachability contracts; +- DOM tests for search, filters, sorting, method explanations and accessible band/warning labels; +- focused browser proof for `/sources`, a source detail, phone/desktop overflow, keyboard access, reduced motion and forced colours; and +- the existing source-governance audit where its fixtures cover the changed metadata behavior. + +No provider evaluation or live RAG canary is required because retrieval and answer behavior remain unchanged. A metadata-only hosted read can verify integration after local behavior passes, but local fixtures remain the repeatable contract. + +## Delivery boundaries + +- No database migration or new Supabase table. +- No writes to hosted source metadata. +- No source-content ingestion or new-source internet research. +- No in-app editor, approval workflow or analytics dashboard. +- No RAG score, retrieval, prompt, citation or answer-generation change. +- No deployment, push or pull request without separate authorization. diff --git a/package.json b/package.json index 897d58adb1..fa3799198c 100644 --- a/package.json +++ b/package.json @@ -141,6 +141,7 @@ "check:cross-mode-index": "node scripts/build-cross-mode-differentials-index.mjs --check", "check:mha-act-sections": "node scripts/build-mha-act-sections.mjs --check", "check:runtime": "node scripts/run-tsx.mjs scripts/check-runtime.ts", + "check:source-catalogue": "node scripts/run-tsx.mjs scripts/check-source-catalogue.ts", "check:installed-lock-parity": "node scripts/check-installed-lock-parity.mjs", "check:upload-limit-parity": "node scripts/check-upload-limit-parity.mjs --self-test && node scripts/check-upload-limit-parity.mjs", "check:codex-cloud": "node scripts/check-codex-cloud-setup.mjs", diff --git a/playwright.config.ts b/playwright.config.ts index 9bd6a26a04..01dbb3141b 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -23,7 +23,7 @@ const chromiumExecutablePath = process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH; // `tests/playwright-project-isolation.test.ts` asserts every such file on disk is // matched here. const productionSpecPattern = - /.*(?:answer-progress-ui-smoke|dsm-ui-smoke|ui-(smoke|stress|accessibility|caring-contacts-workspace|clinical-ask|dictionary|document-canvas|tools|overlap|universal-search|specifiers|formulation(?:-result-cards)?|forms-section-nav|chrome-scroll|therapy-nav-scroll|therapy-pathways|mode-nav-density|phone-motion|phone-scroll(?:-[a-z0-9-]+)?|pwa|route-coverage|style-contract|visual-artifacts|hydration))\.spec\.ts/; + /.*(?:answer-progress-ui-smoke|dsm-ui-smoke|ui-(smoke|stress|accessibility|caring-contacts-workspace|clinical-ask|dictionary|document-canvas|tools|overlap|universal-search|specifiers|sources|formulation(?:-result-cards)?|forms-section-nav|chrome-scroll|therapy-nav-scroll|therapy-pathways|mode-nav-density|phone-motion|phone-scroll(?:-[a-z0-9-]+)?|pwa|route-coverage|style-contract|visual-artifacts|hydration))\.spec\.ts/; const mockupSpecPattern = /.*ui-(answer-chat-perfected-mockup|care-plan-mockup|caring-contact-mockup|document-image-status-mockup|document-top-navigation-mockup|sidebar-live-mockup|therapy-navigation-mockup|tools|tools-collapse|tools-search-mode-mockup|tools-task-directory|ward-management|ward-coordinator|ward-roles|ward-discharges)\.spec\.ts/; const mockupTag = /@mockup/; @@ -31,7 +31,7 @@ const mockupTag = /@mockup/; export default defineConfig({ testDir: "./tests", testMatch: - /.*(?:answer-progress-ui-smoke|dsm-ui-smoke|ui-(smoke|stress|accessibility|answer-chat-perfected-mockup|care-plan-mockup|caring-contact-mockup|caring-contacts-workspace|clinical-ask|dictionary|document-canvas|document-image-status-mockup|document-top-navigation-mockup|sidebar-live-mockup|therapy-navigation-mockup|tools|tools-collapse|tools-search-mode-mockup|tools-task-directory|ward-(?:management|coordinator|roles|discharges)|overlap|universal-search|specifiers|formulation(?:-result-cards)?|forms-section-nav|chrome-scroll|therapy-nav-scroll|therapy-pathways|mode-nav-density|phone-motion|phone-scroll(?:-[a-z0-9-]+)?|pwa|route-coverage|style-contract|visual-artifacts|hydration))\.spec\.ts/, + /.*(?:answer-progress-ui-smoke|dsm-ui-smoke|ui-(smoke|stress|accessibility|answer-chat-perfected-mockup|care-plan-mockup|caring-contact-mockup|caring-contacts-workspace|clinical-ask|dictionary|document-canvas|document-image-status-mockup|document-top-navigation-mockup|sidebar-live-mockup|therapy-navigation-mockup|tools|tools-collapse|tools-search-mode-mockup|tools-task-directory|ward-(?:management|coordinator|roles|discharges)|overlap|universal-search|specifiers|sources|formulation(?:-result-cards)?|forms-section-nav|chrome-scroll|therapy-nav-scroll|therapy-pathways|mode-nav-density|phone-motion|phone-scroll(?:-[a-z0-9-]+)?|pwa|route-coverage|style-contract|visual-artifacts|hydration))\.spec\.ts/, timeout: 60_000, retries: 0, // Fail the run if a stray `test.only` is committed: otherwise it silently diff --git a/scripts/check-source-catalogue.ts b/scripts/check-source-catalogue.ts new file mode 100644 index 0000000000..a93ecca2e6 --- /dev/null +++ b/scripts/check-source-catalogue.ts @@ -0,0 +1,56 @@ +import { canonicalizeSourceReferences } from "../src/lib/sources/catalogue-core"; +import { + repositorySourceCoverageIssues, + repositorySourceProviders, + repositorySourceReferenceIssues, + repositorySourceReferences, +} from "../src/lib/sources/repository-providers"; + +const errors: string[] = []; +const providerIds = new Set(); +const sourcePaths = new Set(); + +for (const provider of repositorySourceProviders) { + if (providerIds.has(provider.id)) errors.push(`Duplicate provider id: ${provider.id}`); + providerIds.add(provider.id); + for (const sourcePath of provider.sourcePaths) { + if (sourcePaths.has(sourcePath)) errors.push(`Duplicate registered source path: ${sourcePath}`); + sourcePaths.add(sourcePath); + } + const references = provider.references(); + if (references.length === 0) errors.push(`Provider ${provider.id} returned no references`); + errors.push(...repositorySourceReferenceIssues(provider.id, references)); +} + +errors.push(...repositorySourceCoverageIssues()); + +const references = repositorySourceReferences(); +const entries = canonicalizeSourceReferences(references); +const debtWarnings = [ + "missing_publisher", + "missing_version", + "missing_dates", + "unknown_jurisdiction", + "unknown_evidence_type", + "verification_unknown", + "invalid_date", +] as const; + +console.log("Source catalogue provider counts:"); +for (const provider of repositorySourceProviders) { + console.log(`- ${provider.id}: ${provider.references().length}`); +} +console.log(`Captured references: ${references.length}`); +console.log(`Canonical repository sources: ${entries.length}`); +console.log(`D-band review debt: ${entries.filter((entry) => entry.rating.band === "D").length}`); +for (const warning of debtWarnings) { + console.log(`${warning}: ${entries.filter((entry) => entry.warnings.includes(warning)).length}`); +} + +if (errors.length > 0) { + console.error("Source catalogue coverage failed:"); + for (const error of [...new Set(errors)].sort()) console.error(`- ${error}`); + process.exitCode = 1; +} else { + console.log("Source catalogue coverage passed."); +} diff --git a/scripts/generate-site-map.ts b/scripts/generate-site-map.ts index aa4579110f..3b8f4c91a6 100644 --- a/scripts/generate-site-map.ts +++ b/scripts/generate-site-map.ts @@ -80,6 +80,7 @@ const documentedRedirectTargets: Record = { // Pinned because the page forwards the incoming query string, so its // `redirect()` argument is a template literal the regex above cannot read. "/dictionary/browse": "/dictionary/search", + "/dictionary/sources": "/sources?usedBy=dictionary", "/mockups/ward-flow/constellation": "/mockups/ward-flow/network", }; @@ -116,7 +117,8 @@ const routeDescriptions: Record = { "/dictionary/compare": "Side-by-side clinical term definition and nuance comparison.", "/dictionary/search": "The clinical term and abbreviation catalogue: an empty query lists everything, a typed query narrows the same list.", - "/dictionary/sources": "Clinical dictionary governance, references, and source catalogue.", + "/dictionary/sources": + "Query-preserving compatibility redirect to `/sources?usedBy=dictionary`; incoming catalogue filters are retained and application usage is set to Dictionary.", "/dictionary/topics": "Clinical dictionary topic category index.", "/dictionary/topics/[slug]": "Clinical dictionary topic category term list.", "/differentials": "Differentials home and search surface.", @@ -406,6 +408,7 @@ function renderModeRoutes() { "therapy-compass": appModeHomeHref("therapy-compass", { query: "behavioural activation", focus: true, run: true }), factsheets: appModeHomeHref("factsheets", { query: "sertraline", focus: true, run: true }), dictionary: appModeHomeHref("dictionary", { query: "mental state examination", focus: true, run: true }), + sources: appModeHomeHref("sources", { query: "RANZCP", focus: true, run: true }), }; return appModeDefinitions.map((mode) => { @@ -523,7 +526,14 @@ function renderModePageIndex() { home: appModeHomeHref("dictionary"), search: appModeHomeHref("dictionary", { query: "MSE", focus: true, run: true }), detail: - "`/dictionary/search` is one catalogue for both searching and browsing; `/dictionary/browse` redirects to it. Also `/topics`, `/topics/[slug]`, `/compare`, `/sources` and `/dictionary/[slug]` records.", + "`/dictionary/search` is one catalogue for both searching and browsing; `/dictionary/browse` redirects to it. Also `/topics`, `/topics/[slug]`, `/compare` and `/dictionary/[slug]` records; `/dictionary/sources` redirects to Sources.", + }, + { + mode: "Sources", + home: appModeHomeHref("sources"), + search: appModeHomeHref("sources", { query: "RANZCP", focus: true, run: true }), + detail: + "`/sources/topics`, `/sources/publishers`, `/sources/method`, and `/sources/[sourceId]` traceability records.", }, { mode: "Therapy Compass", diff --git a/scripts/playwright-pr-shards.mjs b/scripts/playwright-pr-shards.mjs index a1305b1ad9..5cc00b2de4 100644 --- a/scripts/playwright-pr-shards.mjs +++ b/scripts/playwright-pr-shards.mjs @@ -19,7 +19,7 @@ import { childProcessExitCode } from "./child-process-result.mjs"; /** Same matcher as playwright.config.ts `productionSpecPattern` (keep in sync). */ export const productionSpecFilePattern = - /^(?:answer-progress-ui-smoke|dsm-ui-smoke|ui-(?:smoke|stress|accessibility|caring-contacts-workspace|clinical-ask|dictionary|document-canvas|tools|overlap|universal-search|specifiers|formulation(?:-result-cards)?|forms-section-nav|chrome-scroll|therapy-nav-scroll|therapy-pathways|mode-nav-density|phone-motion|phone-scroll(?:-[a-z0-9-]+)?|pwa|route-coverage|style-contract|visual-artifacts|hydration))\.spec\.ts$/; + /^(?:answer-progress-ui-smoke|dsm-ui-smoke|ui-(?:smoke|stress|accessibility|caring-contacts-workspace|clinical-ask|dictionary|document-canvas|tools|overlap|universal-search|specifiers|sources|formulation(?:-result-cards)?|forms-section-nav|chrome-scroll|therapy-nav-scroll|therapy-pathways|mode-nav-density|phone-motion|phone-scroll(?:-[a-z0-9-]+)?|pwa|route-coverage|style-contract|visual-artifacts|hydration))\.spec\.ts$/; /** * One source of truth for shard membership and its latest hosted timing sample. @@ -38,6 +38,8 @@ export const prUiSpecProfiles = Object.freeze([ { file: "tests/ui-formulation.spec.ts", shard: 1, fullSeconds: 11.0, criticalSeconds: 0 }, // New route-focused suite; keep on the lightest measured shard until hosted timing is available. { file: "tests/ui-dictionary.spec.ts", shard: 1, fullSeconds: 0, criticalSeconds: 0 }, + // New route-focused suite; keep on the lightest measured shard until hosted timing is available. + { file: "tests/ui-sources.spec.ts", shard: 1, fullSeconds: 0, criticalSeconds: 0 }, // Critical-only acceptance coverage; the required critical job owns its runtime. { file: "tests/ui-clinical-ask.spec.ts", shard: 1, fullSeconds: 1, criticalSeconds: 1 }, // Added after the timing sample. Measured locally at ~4.8s for 3 tests; replace diff --git a/src/app/(search-app)/dictionary/sources/page.tsx b/src/app/(search-app)/dictionary/sources/page.tsx index b156d22807..2f3c635697 100644 --- a/src/app/(search-app)/dictionary/sources/page.tsx +++ b/src/app/(search-app)/dictionary/sources/page.tsx @@ -1,12 +1,16 @@ -import type { Metadata } from "next"; +import { redirect } from "next/navigation"; -import { DictionarySourcesPage } from "@/components/dictionary/dictionary-sources-page"; - -export const metadata: Metadata = { - title: "Dictionary sources and review | PsychSift", - description: "Understand source checking, authority coverage, and dictionary review cadence.", -}; - -export default function DictionarySourcesRoute() { - return ; +export default async function DictionarySourcesRedirect({ + searchParams, +}: { + searchParams: Promise>; +}) { + const incoming = await searchParams; + const destination = new URLSearchParams(); + for (const [key, value] of Object.entries(incoming)) { + if (key === "usedBy" || value === undefined) continue; + for (const item of Array.isArray(value) ? value : [value]) destination.append(key, item); + } + destination.set("usedBy", "dictionary"); + redirect(`/sources?${destination.toString()}`); } diff --git a/src/app/(search-app)/sources/[sourceId]/page.tsx b/src/app/(search-app)/sources/[sourceId]/page.tsx new file mode 100644 index 0000000000..f8d28870f1 --- /dev/null +++ b/src/app/(search-app)/sources/[sourceId]/page.tsx @@ -0,0 +1,13 @@ +import type { Metadata } from "next"; + +import { SourceDetailPage } from "@/components/sources/sources-pages"; + +export const metadata: Metadata = { + title: "Source traceability", + description: "Identity, rating, locations and application usage for a clinical source.", +}; + +export default async function SourcePage({ params }: { params: Promise<{ sourceId: string }> }) { + const { sourceId } = await params; + return ; +} diff --git a/src/app/(search-app)/sources/loading.tsx b/src/app/(search-app)/sources/loading.tsx new file mode 100644 index 0000000000..59334e70b5 --- /dev/null +++ b/src/app/(search-app)/sources/loading.tsx @@ -0,0 +1,5 @@ +import { ModeHomeRouteLoading } from "@/components/mode-home-page-skeleton"; + +export default function Loading() { + return ; +} diff --git a/src/app/(search-app)/sources/method/page.tsx b/src/app/(search-app)/sources/method/page.tsx new file mode 100644 index 0000000000..d96bd7dbc7 --- /dev/null +++ b/src/app/(search-app)/sources/method/page.tsx @@ -0,0 +1,12 @@ +import type { Metadata } from "next"; + +import { SourcesMethodPage } from "@/components/sources/sources-pages"; + +export const metadata: Metadata = { + title: "Source catalogue method", + description: "Rating method, limitations and status definitions for Sources.", +}; + +export default function MethodPage() { + return ; +} diff --git a/src/app/(search-app)/sources/page.tsx b/src/app/(search-app)/sources/page.tsx new file mode 100644 index 0000000000..fb4386d0f0 --- /dev/null +++ b/src/app/(search-app)/sources/page.tsx @@ -0,0 +1,12 @@ +import type { Metadata } from "next"; + +import { SourcesCataloguePage } from "@/components/sources/sources-pages"; + +export const metadata: Metadata = { + title: "Sources", + description: "Ranked clinical source catalogue and traceability.", +}; + +export default function SourcesPage() { + return ; +} diff --git a/src/app/(search-app)/sources/publishers/page.tsx b/src/app/(search-app)/sources/publishers/page.tsx new file mode 100644 index 0000000000..2684d92d72 --- /dev/null +++ b/src/app/(search-app)/sources/publishers/page.tsx @@ -0,0 +1,12 @@ +import type { Metadata } from "next"; + +import { SourcesPublishersPage } from "@/components/sources/sources-pages"; + +export const metadata: Metadata = { + title: "Source publishers", + description: "Browse publisher coverage across the clinical source catalogue.", +}; + +export default function PublishersPage() { + return ; +} diff --git a/src/app/(search-app)/sources/topics/page.tsx b/src/app/(search-app)/sources/topics/page.tsx new file mode 100644 index 0000000000..a153fd4ad6 --- /dev/null +++ b/src/app/(search-app)/sources/topics/page.tsx @@ -0,0 +1,12 @@ +import type { Metadata } from "next"; + +import { SourcesTopicsPage } from "@/components/sources/sources-pages"; + +export const metadata: Metadata = { + title: "Source topics", + description: "Browse clinical source topics and filtered catalogue links.", +}; + +export default function TopicsPage() { + return ; +} diff --git a/src/components/clinical-dashboard/ClinicalSidebar.tsx b/src/components/clinical-dashboard/ClinicalSidebar.tsx index 0728051bc3..ea956e3e35 100644 --- a/src/components/clinical-dashboard/ClinicalSidebar.tsx +++ b/src/components/clinical-dashboard/ClinicalSidebar.tsx @@ -106,6 +106,7 @@ const sidebarMoreModeIds = [ "calculators", "therapy-compass", "dictionary", + "sources", ] as const satisfies readonly AppModeId[]; const sidebarModeItems = [ diff --git a/src/components/clinical-dashboard/use-sidebar-pins.ts b/src/components/clinical-dashboard/use-sidebar-pins.ts index 1838ea65eb..33bfe16ef5 100644 --- a/src/components/clinical-dashboard/use-sidebar-pins.ts +++ b/src/components/clinical-dashboard/use-sidebar-pins.ts @@ -25,6 +25,7 @@ export const pinnableSidebarModeIds = [ "formulation", "therapy-compass", "dictionary", + "sources", ] as const satisfies readonly AppModeId[]; const changeEvent = "clinical-kb-sidebar-pins-change"; diff --git a/src/components/mode-nav/registry-mode-nav.tsx b/src/components/mode-nav/registry-mode-nav.tsx index bfc9d2cae9..6d2d47fcbf 100644 --- a/src/components/mode-nav/registry-mode-nav.tsx +++ b/src/components/mode-nav/registry-mode-nav.tsx @@ -6,11 +6,14 @@ import { ClipboardCheck, ClipboardList, GitCompareArrows, + Landmark, + LibraryBig, ListChecks, Network, Search, Sparkles, Stethoscope, + Scale, Waypoints, type LucideIcon, } from "lucide-react"; @@ -43,6 +46,7 @@ export const registryModeNavDensityProfiles = { // "Presentations". `extended` was chosen when the mode had five destinations // and Search/Browse were two names for one place. dictionary: "balanced-four", + sources: "balanced-four", } as const satisfies Record; /** @@ -68,6 +72,9 @@ const iconByItemId: Record = { // on the same screen. topics: BookOpenText, sources: BookMarked, + catalogue: LibraryBig, + publishers: Landmark, + method: Scale, }; /** diff --git a/src/components/sources/sources-catalogue-client.tsx b/src/components/sources/sources-catalogue-client.tsx new file mode 100644 index 0000000000..6709c97d71 --- /dev/null +++ b/src/components/sources/sources-catalogue-client.tsx @@ -0,0 +1,431 @@ +"use client"; + +import Link from "next/link"; +import { SearchResultsHeaderBand } from "@/components/clinical-dashboard/search-results-header-band"; +import { usePathname, useRouter, useSearchParams } from "next/navigation"; +import { useMemo } from "react"; + +import type { ClinicalSourceCatalogueEntry, SourceQualityBand } from "@/lib/sources/catalogue-types"; +import { + deriveSourceCatalogueFacets, + filterAndSortSourceCatalogue, + parseSourceCatalogueFilters, +} from "@/lib/sources/catalogue-view"; + +type HostedDocumentsStatus = "available" | "unavailable"; + +const bandLabels: Record = { + A: "A · Preferred", + B: "B · Strong", + C: "C · Supplementary", + D: "D · Review required", + excluded: "Excluded", +}; + +const filterClassName = + "min-h-12 w-full rounded-xl border border-[color:var(--border)] bg-[color:var(--surface)] px-3 text-sm text-[color:var(--text)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:var(--primary)]"; + +function titleCase(value: string) { + return value.replaceAll("_", " ").replace(/\b\w/g, (letter) => letter.toUpperCase()); +} + +function formatDate(value: string | null) { + if (!value) return "Unknown"; + const date = new Date(`${value}T00:00:00`); + return Number.isNaN(date.getTime()) + ? value + : new Intl.DateTimeFormat("en-AU", { day: "numeric", month: "short", year: "numeric" }).format(date); +} + +function canonicalLocationLabel(entry: ClinicalSourceCatalogueEntry) { + if (entry.canonicalLocation.kind === "url") return entry.canonicalLocation.href; + if (entry.canonicalLocation.kind === "document") return "Accessible hosted document"; + if (entry.canonicalLocation.kind === "dataset") return entry.canonicalLocation.label; + return "Not provided"; +} + +function SourceSummary({ entry }: { entry: ClinicalSourceCatalogueEntry }) { + return ( +

+
+ {bandLabels[entry.rating.band]} + Score {entry.rating.score}/100 +
+ + {entry.title} + +

+ {entry.publisher ?? "Publisher unknown"} · {entry.geography.label} +

+

+ {canonicalLocationLabel(entry)} · {titleCase(entry.documentStatus)} · reviewed {formatDate(entry.reviewDate)} +

+ {entry.warnings.length > 0 ? ( +

+ Review: {entry.warnings.map(titleCase).join(", ")} +

+ ) : null} +

+ Used by {entry.usedBy.map((usage) => usage.recordLabel).join(", ") || "no registered application records"} +

+
+ ); +} + +function FilterSelect({ + label, + selectedValues, + options, + onChange, +}: { + label: string; + selectedValues: readonly string[]; + options: readonly { value: string; label: string }[]; + onChange: (value: string) => void; +}) { + const value = selectedValues.length === 1 ? selectedValues[0] : ""; + return ( + + ); +} + +function uniqueSorted(values: readonly string[]) { + return [...new Set(values)].sort((left, right) => left.localeCompare(right, "en-AU", { sensitivity: "base" })); +} + +export function SourcesCatalogueClient({ + entries, + hostedDocuments, +}: { + entries: readonly ClinicalSourceCatalogueEntry[]; + hostedDocuments: HostedDocumentsStatus; +}) { + const pathname = usePathname(); + const router = useRouter(); + const searchParams = useSearchParams(); + const filters = useMemo(() => parseSourceCatalogueFilters(searchParams, entries), [entries, searchParams]); + const visibleEntries = useMemo(() => filterAndSortSourceCatalogue(entries, filters), [entries, filters]); + const facets = useMemo(() => deriveSourceCatalogueFacets(entries), [entries]); + + const replaceFilter = (key: string, value: string) => { + const next = new URLSearchParams(searchParams.toString()); + next.delete(key); + if (value) next.append(key, value); + const suffix = next.toString(); + router.replace(`${pathname}${suffix ? `?${suffix}` : ""}`, { scroll: false }); + }; + + const removeFilterValue = (key: string, value: string) => { + const next = new URLSearchParams(); + for (const [candidateKey, candidateValue] of searchParams.entries()) { + if (candidateKey !== key) { + next.append(candidateKey, candidateValue); + continue; + } + for (const sibling of candidateValue + .split(",") + .map((item) => item.trim()) + .filter((item) => item && item !== value)) { + next.append(candidateKey, sibling); + } + } + const suffix = next.toString(); + router.replace(`${pathname}${suffix ? `?${suffix}` : ""}`, { scroll: false }); + }; + + const hasActiveFilter = + Boolean(filters.q) || + filters.bands.length > 0 || + filters.jurisdictions.length > 0 || + filters.sourceTypes.length > 0 || + filters.publishers.length > 0 || + filters.topics.length > 0 || + filters.lifecycleStatuses.length > 0 || + filters.documentStatuses.length > 0 || + filters.validationStatuses.length > 0 || + filters.usedBy.length > 0 || + filters.sort !== "quality"; + + const options = { + bands: uniqueSorted(entries.map((entry) => entry.rating.band)).map((value) => ({ + value, + label: bandLabels[value as SourceQualityBand], + })), + jurisdictions: uniqueSorted(entries.map((entry) => entry.geography.scope)).map((value) => ({ + value, + label: titleCase(value), + })), + types: uniqueSorted(entries.map((entry) => entry.sourceType)).map((value) => ({ value, label: titleCase(value) })), + publishers: uniqueSorted(entries.flatMap((entry) => (entry.publisher ? [entry.publisher] : []))).map((value) => ({ + value, + label: value, + })), + topics: uniqueSorted(entries.flatMap((entry) => entry.topics)).map((value) => ({ value, label: titleCase(value) })), + lifecycle: uniqueSorted(entries.map((entry) => entry.lifecycleStatus)).map((value) => ({ + value, + label: titleCase(value), + })), + statuses: uniqueSorted(entries.map((entry) => entry.documentStatus)).map((value) => ({ + value, + label: titleCase(value), + })), + validation: uniqueSorted(entries.map((entry) => entry.validationStatus)).map((value) => ({ + value, + label: titleCase(value), + })), + usages: uniqueSorted(entries.flatMap((entry) => entry.usedBy.map((usage) => usage.modeId))).map((value) => ({ + value, + label: titleCase(value), + })), + }; + const activeFilterGroups = [ + { key: "band", label: "Quality band", values: filters.bands, options: options.bands }, + { + key: "jurisdiction", + label: "Jurisdiction", + values: filters.jurisdictions, + options: options.jurisdictions, + }, + { key: "type", label: "Source type", values: filters.sourceTypes, options: options.types }, + { key: "publisher", label: "Publisher", values: filters.publishers, options: options.publishers }, + { key: "topic", label: "Topic", values: filters.topics, options: options.topics }, + { key: "lifecycle", label: "Lifecycle", values: filters.lifecycleStatuses, options: options.lifecycle }, + { key: "status", label: "Currentness", values: filters.documentStatuses, options: options.statuses }, + { key: "validation", label: "Validation", values: filters.validationStatuses, options: options.validation }, + { key: "usedBy", label: "Application usage", values: filters.usedBy, options: options.usages }, + ]; + + return ( +
+
+

Traceability

+

Sources

+

+ Browse the clinical sources registered across the application. Ratings organise review work and do not measure + factual truth. +

+
+ + + + {hostedDocuments === "unavailable" ? ( +
+

Hosted document sources are temporarily unavailable

+

+ Repository sources remain available; this catalogue is not a complete hosted-document count. +

+
+ ) : null} + +
+ {[ + ["Visible sources", `${visibleEntries.length} of ${facets.total}`], + ["Australian", String(facets.australian)], + ["Review required", String(facets.reviewRequired)], + ["Inactive or excluded", String(facets.inactiveOrExcluded)], + ].map(([label, value]) => ( +
+
{label}
+
{value}
+
+ ))} +
+ +
+
+

+ Filter catalogue +

+ {hasActiveFilter ? ( + + ) : null} +
+ {activeFilterGroups.some((group) => group.values.length > 0) ? ( +
+ Active filters +
    + {activeFilterGroups.flatMap((group) => + group.values.map((value) => { + const valueLabel = group.options.find((option) => option.value === value)?.label ?? titleCase(value); + return ( +
  • + +
  • + ); + }), + )} +
+
+ ) : null} +
+ replaceFilter("band", value)} + /> + replaceFilter("jurisdiction", value)} + /> + replaceFilter("type", value)} + /> + replaceFilter("publisher", value)} + /> + replaceFilter("topic", value)} + /> + replaceFilter("lifecycle", value)} + /> + replaceFilter("status", value)} + /> + replaceFilter("validation", value)} + /> + replaceFilter("usedBy", value)} + /> + +
+
+ +

+ {visibleEntries.length} {visibleEntries.length === 1 ? "source" : "sources"} +

+ + {visibleEntries.length === 0 ? ( +
+

No sources match these filters

+

+ Reset the catalogue filters or broaden the shared search query. +

+
+ ) : ( + <> +
+ + + + + + + + + + + {visibleEntries.map((entry) => ( + + + + + + + ))} + +
Quality and sourcePublisherLocation and currencyWarnings and usage
+ + {entry.publisher ?? "Unknown"} + {entry.geography.label} +
+ {titleCase(entry.documentStatus)} +
+ {entry.warnings.length ? entry.warnings.map(titleCase).join(", ") : "No catalogue warnings"} +
+
+
    + {visibleEntries.map((entry) => ( +
  • + +
  • + ))} +
+ + )} +
+ ); +} diff --git a/src/components/sources/sources-pages.tsx b/src/components/sources/sources-pages.tsx new file mode 100644 index 0000000000..1219dbe7b3 --- /dev/null +++ b/src/components/sources/sources-pages.tsx @@ -0,0 +1,450 @@ +import Link from "next/link"; +import { notFound } from "next/navigation"; +import type { ReactNode } from "react"; + +import { + InformationPageBreadcrumbs, + InformationPageHeader, + InformationPageShell, +} from "@/components/information-page-shell"; +import { SourcesCatalogueClient } from "@/components/sources/sources-catalogue-client"; +import { + SOURCE_RATING_WEIGHTS, + type ClinicalSourceCatalogueEntry, + type SourceGeographyScope, +} from "@/lib/sources/catalogue-types"; +import { deriveSourceCatalogueFacets } from "@/lib/sources/catalogue-view"; +import { loadSourceCatalogue } from "@/lib/sources/load-source-catalogue"; + +const bandLabels = { + A: "A · Preferred", + B: "B · Strong", + C: "C · Supplementary", + D: "D · Review required", + excluded: "Excluded", +} as const; + +function titleCase(value: string) { + return value.replaceAll("_", " ").replace(/\b\w/g, (letter) => letter.toUpperCase()); +} + +function valueOrUnknown(value: string | null) { + return value?.trim() || "Unknown"; +} + +function dateOrUnknown(value: string | null) { + if (!value) return "Unknown"; + const date = new Date(`${value}T00:00:00`); + return Number.isNaN(date.getTime()) + ? value + : new Intl.DateTimeFormat("en-AU", { day: "numeric", month: "long", year: "numeric" }).format(date); +} + +function PageIntroduction({ title, description }: { title: string; description: string }) { + return ( + <> + + + + ); +} + +export async function SourcesCataloguePage(): Promise { + const catalogue = await loadSourceCatalogue(); + return ( + + + + ); +} + +export async function SourcesTopicsPage(): Promise { + const { entries, hostedDocuments } = await loadSourceCatalogue(); + const topics = deriveSourceCatalogueFacets(entries).topics; + return ( + + + {hostedDocuments === "unavailable" ? ( +

+ Hosted document topics are temporarily unavailable; repository topic counts remain visible. +

+ ) : null} + {topics.length ? ( +
    + {topics.map((topic) => ( +
  • + + {titleCase(topic.value)} + {topic.count} + +
  • + ))} +
+ ) : ( +

+ No structured source topics are available. +

+ )} +
+ ); +} + +export async function SourcesPublishersPage(): Promise { + const { entries, hostedDocuments } = await loadSourceCatalogue(); + const publisherScopes: readonly { scope: SourceGeographyScope; label: string }[] = [ + { scope: "wa", label: "Western Australia" }, + { scope: "australian_national", label: "Australian national" }, + { scope: "australian_state", label: "Another Australian state" }, + { scope: "international", label: "International" }, + { scope: "unknown", label: "Unknown jurisdiction" }, + ]; + const publisherGroups = publisherScopes + .map((group) => ({ + ...group, + publishers: deriveSourceCatalogueFacets( + entries.filter((entry) => entry.publisher && entry.geography.scope === group.scope), + ).publishers, + })) + .filter((group) => group.publishers.length > 0); + return ( + + + {hostedDocuments === "unavailable" ? ( +

+ Hosted document publishers are temporarily unavailable; repository publisher counts remain visible. +

+ ) : null} + {publisherGroups.length ? ( +
+ {publisherGroups.map((group) => ( +
+

+ {group.label} +

+
+ {group.publishers.map((publisher) => { + const publisherEntries = entries.filter( + (entry) => entry.publisher === publisher.value && entry.geography.scope === group.scope, + ); + const jurisdictions = [...new Set(publisherEntries.map((entry) => entry.geography.label))]; + return ( +
+

{publisher.value}

+

+ {publisher.count} {publisher.count === 1 ? "source" : "sources"} ·{" "} + {jurisdictions.join(", ") || "Jurisdiction unknown"} +

+ + View {publisher.value} sources + +
+ ); + })} +
+
+ ))} +
+ ) : ( +

+ No structured publishers are available. +

+ )} +
+ ); +} + +export function SourcesMethodPage(): ReactNode { + const weights = [ + ["Accuracy assurance", SOURCE_RATING_WEIGHTS.accuracyAssurance, "Version review, validation or an explicit check"], + ["Reliability", SOURCE_RATING_WEIGHTS.reliability, "Publisher authority, provenance and independence"], + ["Evidence quality", SOURCE_RATING_WEIGHTS.evidenceQuality, "The declared evidence or reference type"], + ["Currency", SOURCE_RATING_WEIGHTS.currency, "Publication, review, expiry and supersession state"], + [ + "Australian applicability", + SOURCE_RATING_WEIGHTS.australianApplicability, + "WA, national, state or international applicability", + ], + ["Traceability", SOURCE_RATING_WEIGHTS.traceability, "Identity, version, dates, location and registered usage"], + ] as const; + const statusDefinitions = [ + [ + "Currentness", + [ + ["Current", "The structured status says the source is within its current review period."], + ["Review due", "An explicit upstream status says the source is due for structured review."], + ["Outdated", "The source is past its structured expiry date or is explicitly marked outdated."], + ["Unknown currentness", "A malformed expiry does not establish currentness, so currentness remains unknown."], + ], + ], + [ + "Validation", + [ + ["Approved", "The source carries an explicit approved clinical validation status."], + ["Locally reviewed", "The source has a recorded local review but is not marked approved."], + ["Unverified", "The source is explicitly marked as not yet verified."], + ["Unknown validation", "No structured clinical validation status was supplied."], + ], + ], + [ + "Lifecycle", + [ + ["Active", "The source remains available for current catalogue use."], + ["Inactive", "The source is retained for traceability but is not currently active."], + ["Excluded", "A lifecycle or governance rule removes the source from normal catalogue use."], + ], + ], + [ + "Content mode", + [ + ["Indexed content", "The source content can be searched inside the application."], + ["Link only", "The catalogue stores a governed outbound location, not searchable source content."], + ["Metadata only", "Only structured identity and review metadata are available to the catalogue."], + ], + ], + ] as const; + return ( + + +
+

+ Rating dimensions +

+
+ {weights.map(([label, points, description]) => ( +
+
{label}
+
+ {points} points · {description} +
+
+ ))} +
+
+
+

+ Quality bands +

+
    +
  • A · Preferred · 85–100
  • +
  • B · Strong · 70–84
  • +
  • C · Supplementary · 50–69
  • +
  • D · Review required · below 50, incomplete metadata, or material identity or verification uncertainty
  • +
  • + Excluded · applied before any score when lifecycle or governance rules reject the source, including an + identified replacement +
  • +
+
+
+

+ Boundaries and missing data +

+

+ Australian applicability is bounded within 15 points. Weak Australian material cannot bypass identity, + validation, lifecycle or evidence-quality controls. +

+

+ Missing fields remain unknown. The catalogue does not infer publisher, jurisdiction, evidence type, version, + approval or currentness from titles or prose. +

+

+ Missing publisher, version, dates, jurisdiction, evidence type or validation forces D · Review required. A + past expiry receives no current currency credit; a source with an identified replacement is excluded. +

+

+ This organisational rating is not RAG relevance or patient-specific guidance, specialist sign-off, clinical + endorsement, or a measurement of factual truth. +

+
+
+

+ Catalogue status definitions +

+
+ {statusDefinitions.map(([group, definitions]) => ( +
+

{group}

+
+ {definitions.map(([label, definition]) => ( +
+
{label}
+
{definition}
+
+ ))} +
+
+ ))} +
+
+
+ ); +} + +function CanonicalLocation({ entry }: { entry: ClinicalSourceCatalogueEntry }) { + const location = entry.canonicalLocation; + if (location.kind === "url") { + return ( + + Open canonical source + + ); + } + if (location.kind === "document") { + return ( + + Open accessible document + + ); + } + if (location.kind === "dataset") return {location.label}; + return Not provided; +} + +export async function SourceDetailPage({ sourceId }: { sourceId: string }): Promise { + const { entries } = await loadSourceCatalogue(); + const entry = entries.find((candidate) => candidate.id === sourceId); + if (!entry) notFound(); + + const identityRows = [ + ["Publisher", valueOrUnknown(entry.publisher)], + ["Publisher code", valueOrUnknown(entry.publisherCode)], + ["Version", valueOrUnknown(entry.version)], + ["Source type", titleCase(entry.sourceType)], + ["Validation", titleCase(entry.validationStatus)], + ["Currentness", titleCase(entry.documentStatus)], + ["Lifecycle", titleCase(entry.lifecycleStatus)], + ["Content mode", titleCase(entry.contentMode)], + ["Published", dateOrUnknown(entry.publicationDate)], + ["Review date", dateOrUnknown(entry.reviewDate)], + ["Expiry date", dateOrUnknown(entry.expiryDate)], + ] as const; + + return ( + + + + +
+

+ Source locations +

+
+
+
Canonical location
+
+ +
+
+
+
Geographic location
+
{entry.geography.label}
+
+
+
Application location
+
+ {entry.usedBy.length} registered {entry.usedBy.length === 1 ? "usage" : "usages"} +
+
+
+
+ +
+

+ Identity and status +

+
+ {identityRows.map(([label, value]) => ( +
+
{label}
+
{value}
+
+ ))} +
+

+ Topics: {entry.topics.length ? entry.topics.map(titleCase).join(", ") : "Unknown"} +

+

+ Aliases: {entry.aliases.length ? entry.aliases.join(", ") : "None registered"} +

+
+ +
+

+ Rating breakdown +

+
    + {entry.rating.reasons.map((reason) => ( +
  • + {reason} +
  • + ))} +
+
+ +
+

+ Versions and warnings +

+

+ Supersedes: {entry.supersedes.join(", ") || "None registered"} +

+

+ Superseded by: {entry.supersededBy.join(", ") || "None registered"} +

+

+ Warnings:{" "} + {entry.warnings.length ? entry.warnings.map(titleCase).join(", ") : "No catalogue warnings"} +

+
+ +
+

+ Application usages +

+
    + {entry.usedBy.map((usage) => ( +
  • + {usage.recordLabel} · {titleCase(usage.modeId)} · {titleCase(usage.field)} +
  • + ))} +
+
+
+ ); +} diff --git a/src/lib/app-modes.ts b/src/lib/app-modes.ts index f74890757e..d60cfd8f22 100644 --- a/src/lib/app-modes.ts +++ b/src/lib/app-modes.ts @@ -19,6 +19,7 @@ export const appModeIds = [ "therapy-compass", "factsheets", "dictionary", + "sources", ] as const; export type AppModeId = (typeof appModeIds)[number]; @@ -455,6 +456,29 @@ export const appModeDefinitions = [ badgeLabel: null, }, }, + { + id: "sources", + label: "Sources", + description: "Ranked clinical source catalogue and traceability", + href: "/sources", + search: { + kind: "tools", + placeholder: "Search sources, publishers, or topics...", + inputAriaLabel: "Search sources, publishers, or topics", + submitIdleLabel: "Sources", + submitBusyLabel: "Sources", + submitAriaLabel: "Search sources", + emptyTitle: "Search sources", + readyTitle: "Search the clinical source catalogue", + progressLabel: "Searching the source catalogue.", + resultKind: "tools", + resultHeading: "Sources", + resultsSurface: "results-band", + statusLabel: "Sources", + nextStep: "Filter by quality, location, publisher, topic, or usage", + badgeLabel: null, + }, + }, ] as const satisfies readonly AppModeDefinition[]; export function appModeDefinition(modeId: AppModeId) { @@ -490,6 +514,7 @@ const namespaceIsolatedModes = new Set([ "therapy-compass", "factsheets", "dictionary", + "sources", "tools", "calculators", ]); diff --git a/src/lib/category-identity-icons.ts b/src/lib/category-identity-icons.ts index 36662936f6..a9e762c508 100644 --- a/src/lib/category-identity-icons.ts +++ b/src/lib/category-identity-icons.ts @@ -12,6 +12,7 @@ import { FileText, Heart, HeartHandshake, + LibraryBig, MessagesSquare, Network, Pill, @@ -55,6 +56,7 @@ const categoryIcons: Record = { compass: Compass, bookOpenText: BookOpenText, bookMarked: BookMarked, + libraryBig: LibraryBig, search: Search, scrollText: ScrollText, shieldCheck: ShieldCheck, diff --git a/src/lib/category-identity.ts b/src/lib/category-identity.ts index 12c4a6f54f..033df61f11 100644 --- a/src/lib/category-identity.ts +++ b/src/lib/category-identity.ts @@ -86,6 +86,7 @@ export const CATEGORY_ICON_KEYS = [ "compass", "bookOpenText", "bookMarked", + "libraryBig", "search", "scrollText", "shieldCheck", @@ -121,6 +122,7 @@ export const APP_MODE_ICON: Record = { "therapy-compass": "compass", factsheets: "bookOpenText", dictionary: "bookMarked", + sources: "libraryBig", }; /** @@ -138,6 +140,7 @@ export const APP_MODE_ACCENT: Record = { documents: "document", factsheets: "document", dictionary: "source", + sources: "source", differentials: "indigo", "therapy-compass": "indigo", specifiers: "table", @@ -163,6 +166,7 @@ export const TOOL_ICON: Record = { differentials: "brainCircuit", documents: "fileText", "clinical-dictionary": "bookMarked", + "source-catalogue": "libraryBig", guidelines: "scrollText", "risk-safety": "shieldCheck", "medication-prescribing": "pill", diff --git a/src/lib/information-pages.ts b/src/lib/information-pages.ts index 6649e07ed2..10a39256f0 100644 --- a/src/lib/information-pages.ts +++ b/src/lib/information-pages.ts @@ -19,7 +19,8 @@ export type InformationPageMode = | "therapy-compass" | "differentials" | "dsm" - | "documents"; + | "documents" + | "sources"; // Reserved route suffixes, not record slugs. `search` is here because home // consolidation gave every consolidated mode a `/search` results route: @@ -69,6 +70,7 @@ export function isInformationPage(pathname: string): boolean { if (isSlugDetail(pathname, "/formulation")) return true; if (isSlugDetail(pathname, "/factsheets", ["search", "topics"])) return true; if (isSlugDetail(pathname, "/dictionary", ["search", "browse", "topics", "compare", "sources"])) return true; + if (isSlugDetail(pathname, "/sources", ["topics", "publishers", "method"])) return true; if (pathname.startsWith("/dictionary/topics/") && !pathname.slice("/dictionary/topics/".length).includes("/")) return true; @@ -105,6 +107,7 @@ export const informationPageShellModes = [ "formulation", "factsheets", "dictionary", + "sources", "therapy-compass", "dsm", ] as const satisfies readonly InformationPageMode[]; diff --git a/src/lib/mode-secondary-navigation.ts b/src/lib/mode-secondary-navigation.ts index c93030cd22..1bf510923e 100644 --- a/src/lib/mode-secondary-navigation.ts +++ b/src/lib/mode-secondary-navigation.ts @@ -99,6 +99,12 @@ export const modeSecondaryNavigationRegistry = { { id: "compare", label: "Compare", href: "/dictionary/compare" }, { id: "sources", label: "Sources", href: "/dictionary/sources" }, ], + sources: [ + { id: "catalogue", label: "Catalogue", href: "/sources" }, + { id: "topics", label: "Topics", href: "/sources/topics" }, + { id: "publishers", label: "Publishers", href: "/sources/publishers" }, + { id: "method", label: "Method", href: "/sources/method" }, + ], } as const satisfies Record; type RegistryEntry = (typeof modeSecondaryNavigationRegistry)[AppModeId][number]; @@ -132,6 +138,7 @@ export const MODE_NAV_ADOPTED_MODES = [ "factsheets", "therapy-compass", "dictionary", + "sources", ] as const satisfies readonly AppModeId[]; export type ModeNavAdoptedMode = (typeof MODE_NAV_ADOPTED_MODES)[number]; @@ -216,6 +223,13 @@ export function activeModeSecondaryNavigationId(modeId: AppModeId, pathname: str if (pathname === "/dictionary/sources") return "sources"; return null; } + if (modeId === "sources") { + if (pathname === "/sources") return "catalogue"; + if (pathname === "/sources/topics") return "topics"; + if (pathname === "/sources/publishers") return "publishers"; + if (pathname === "/sources/method") return "method"; + return null; + } // Every mode with destinations has a branch above; the rest register none, so // nothing can be current. This used to be // `modeSecondaryNavigationRegistry[modeId][0]?.id ?? null`, which existed only @@ -271,6 +285,9 @@ export function isModeSecondaryNavigationRoute(params: { pathname, ); } + if (modeId === "sources") { + return ["/sources", "/sources/topics", "/sources/publishers", "/sources/method"].includes(pathname); + } return false; } @@ -470,5 +487,13 @@ export function modeSecondaryNavigationHref(params: { } } + if (modeId === "sources") { + if (itemId === "method") return href; + const entries: Array = []; + if (query) entries.push(["q", query]); + for (const usage of currentSearchParams.getAll("usedBy")) entries.push(["usedBy", usage]); + return navigationHrefWithParams(href, entries); + } + return href; } diff --git a/src/lib/search-command-surface.ts b/src/lib/search-command-surface.ts index 9913c15d11..627acaac62 100644 --- a/src/lib/search-command-surface.ts +++ b/src/lib/search-command-surface.ts @@ -180,6 +180,16 @@ const searchCommandSurfaceByMode: Partial([ "therapy-compass", "factsheets", "dictionary", + "sources", "tools", "calculators", ]); @@ -26,14 +27,15 @@ const routeOwnedSubmittedSearchModes = new Set([ * navigation cannot flip the shell into dock reserve mid-transition. */ export const standaloneModeHomePaths = [ - // The four modes that still own a home of their own. Every other mode was - // consolidated onto the shared home at `/?mode=`, whose composer the - // dashboard owns; their bare paths redirect and render nothing to reserve - // geometry for (`consolidatedModeHomePaths`). + // Modes that still own a home of their own. Consolidated modes use the shared + // home at `/?mode=`, whose composer the dashboard owns; their bare paths + // redirect and render nothing to reserve geometry for + // (`consolidatedModeHomePaths`). "/favourites", "/tools", "/medications", "/documents", + "/sources", ] as const; /** @@ -100,6 +102,7 @@ const alwaysStandaloneShellPathPrefixes = [ "/formulation", "/factsheets", "/dictionary", + "/sources", "/therapy-compass", "/medications", "/calculators", diff --git a/src/lib/search-shell-props.ts b/src/lib/search-shell-props.ts index c651b41e06..59b01ce61b 100644 --- a/src/lib/search-shell-props.ts +++ b/src/lib/search-shell-props.ts @@ -94,6 +94,16 @@ export function searchShellPropsForPathname(pathname: string): SearchShellPathPr return { initialMode: "factsheets", desktopSearchPlacement: "hero" }; } + if (pathname.startsWith("/sources")) { + const rest = pathname.slice("/sources/".length); + const isDetail = pathname.startsWith("/sources/") && !["topics", "publishers", "method"].includes(rest); + return { + initialMode: "sources", + desktopSearchPlacement: "hero", + ...(pathname === "/sources/method" || isDetail ? { searchComposerVisible: false } : {}), + }; + } + if (pathname.startsWith("/dictionary")) { // `/dictionary/sources` is a read-only governance page — the source method, // the authority hierarchy, the index and the review cadence. Nothing on it diff --git a/src/lib/sources/catalogue-core.ts b/src/lib/sources/catalogue-core.ts new file mode 100644 index 0000000000..b53e5eebcb --- /dev/null +++ b/src/lib/sources/catalogue-core.ts @@ -0,0 +1,482 @@ +import { createHash } from "node:crypto"; + +import { classifySourceAuthority, normalizeSourceAuthorityText } from "@/lib/source-authority-registry"; +import { normalizeSourceMetadata } from "@/lib/source-metadata"; +import { hasInvalidStructuredSourceDate, strictSourceDate } from "@/lib/sources/source-date-policy"; +import { + SOURCE_RATING_WEIGHTS, + type ClinicalSourceCatalogueEntry, + type ClinicalSourceReferenceInput, + type ClinicalSourceRating, + type ClinicalSourceType, + type SourceCanonicalLocation, + type SourceCatalogueWarning, + type SourceGeographyScope, + type SourceLifecycleStatus, + type SourceUsage, +} from "@/lib/sources/catalogue-types"; +import { safeCanonicalSourceUrl } from "@/lib/sources/source-url-policy"; + +const ACCURACY = { approved: 25, locally_reviewed: 20, unverified: 5, unknown: 0 } as const; +const EVIDENCE = { + guideline: 20, + standard: 20, + legislation: 20, + regulatory: 20, + systematic_review: 18, + primary_study: 14, + professional_reference: 12, + consumer_reference: 8, + uploaded_document: 6, + dataset: 6, + other: 4, + unknown: 0, +} as const; +const AUSTRALIAN = { wa: 15, australian_national: 13, australian_state: 11, international: 6, unknown: 0 } as const; +const CURRENCY = { current: 15, review_due: 8, unknown: 4, outdated: 0 } as const; +const BAND_ORDER = { A: 0, B: 1, C: 2, D: 3, excluded: 4 } as const; +const INCOMPLETE_METADATA_WARNINGS = new Set([ + "missing_publisher", + "missing_version", + "missing_dates", + "unknown_jurisdiction", + "unknown_evidence_type", + "verification_unknown", + "invalid_date", +]); + +function opaqueSourceId(identity: string) { + return `src_${createHash("sha256").update(identity).digest("hex").slice(0, 20)}`; +} + +export function safeHttpsUrl(value: string | null) { + return safeCanonicalSourceUrl(value); +} + +function baseIdentity(input: ClinicalSourceReferenceInput) { + if (input.documentId) return `document:${input.documentId}`; + if (input.sourceId) return `source:${input.sourceId.trim().toLowerCase()}`; + const url = safeHttpsUrl(input.canonicalUrl); + if (url) return `url:${url}|version:${input.version ?? "unknown"}`; + if (input.publisher && input.title) { + return `title:${normalizeSourceAuthorityText(input.publisher)}|${normalizeSourceAuthorityText(input.title)}|${input.version ?? "unknown"}`; + } + const provisionalIdentity = normalizeSourceAuthorityText(input.referenceText ?? input.title); + return provisionalIdentity ? `provisional:${provisionalIdentity}` : "provisional:unresolved"; +} + +function compatibilityKey(input: ClinicalSourceReferenceInput) { + return [input.publisher, input.publisherCode, input.jurisdiction, input.version] + .map((value) => normalizeSourceAuthorityText(value)) + .join("|"); +} + +function metadataFor(input: ClinicalSourceReferenceInput) { + return normalizeSourceMetadata({ + source_kind: input.documentId ? "document" : null, + source_title: input.title, + publisher: input.publisher, + publisher_code: input.publisherCode, + jurisdiction: input.jurisdiction, + version: input.version, + publication_date: input.publicationDate, + review_date: input.reviewDate, + document_status: input.documentStatus, + clinical_validation_status: input.validationStatus, + extraction_quality: input.contentMode === "indexed_content" ? "good" : "unknown", + }); +} + +function authorityFor(input: ClinicalSourceReferenceInput) { + return classifySourceAuthority(metadataFor(input)); +} + +function geographyFor(input: ClinicalSourceReferenceInput) { + const classification = authorityFor(input); + if (classification.conflict) return { scope: "unknown" as const, label: "Unknown" }; + const authority = classification.authority; + const scope: SourceGeographyScope = authority?.scope ?? "unknown"; + const fallbackLabel = { + wa: "Western Australia", + australian_national: "Australia", + australian_state: "Australian state", + international: "International", + unknown: "Unknown", + }[scope]; + return { scope, label: scope === "unknown" ? fallbackLabel : (input.jurisdiction?.trim() ?? fallbackLabel) }; +} + +function hasStableIdentity(input: ClinicalSourceReferenceInput) { + return Boolean( + input.documentId || + input.sourceId || + safeHttpsUrl(input.canonicalUrl) || + (input.publisher?.trim() && input.title?.trim()), + ); +} + +function canonicalLocationFor(inputs: readonly ClinicalSourceReferenceInput[]): SourceCanonicalLocation { + const documentId = uniqueStrings(inputs.map((input) => input.documentId)).at(0); + if (documentId) { + return { + kind: "document", + documentId, + href: `/documents/${encodeURIComponent(documentId)}`, + }; + } + const href = uniqueStrings(inputs.map((input) => safeHttpsUrl(input.canonicalUrl))).at(0); + if (href) return { kind: "url", href }; + const dataset = uniqueStrings(inputs.map((input) => input.datasetLocation)).at(0); + if (dataset) return { kind: "dataset", label: dataset }; + return { kind: "none" }; +} + +function hasText(value: string | null) { + return Boolean(value?.trim()); +} + +function isPastExpiryDate(value: string | null) { + const date = strictSourceDate(value); + return Boolean(date && date < new Date().toISOString().slice(0, 10)); +} + +function effectiveDocumentStatus(input: ClinicalSourceReferenceInput) { + if (hasInvalidStructuredSourceDate(input.expiryDate)) return "unknown" as const; + return isPastExpiryDate(input.expiryDate) ? ("outdated" as const) : input.documentStatus; +} + +function hasIdentifiedReplacement(input: ClinicalSourceReferenceInput) { + return input.supersededBy.some(hasText); +} + +function effectiveLifecycleStatus(input: ClinicalSourceReferenceInput): SourceLifecycleStatus { + return hasIdentifiedReplacement(input) ? "excluded" : input.lifecycleStatus; +} + +function sourceWarnings(input: ClinicalSourceReferenceInput): SourceCatalogueWarning[] { + const authority = authorityFor(input); + const warnings: SourceCatalogueWarning[] = []; + if (!hasStableIdentity(input)) warnings.push("ambiguous_identity"); + if (authority.conflict) warnings.push("metadata_conflict"); + if (input.canonicalUrl && !safeHttpsUrl(input.canonicalUrl)) warnings.push("unsafe_location"); + if ([input.publicationDate, input.reviewDate, input.expiryDate].some(hasInvalidStructuredSourceDate)) { + warnings.push("invalid_date"); + } + if (!hasText(input.publisher)) warnings.push("missing_publisher"); + if (!hasText(input.version)) warnings.push("missing_version"); + if (![input.publicationDate, input.reviewDate, input.expiryDate].some(hasText)) warnings.push("missing_dates"); + if (!hasText(input.jurisdiction) || geographyFor(input).scope === "unknown") warnings.push("unknown_jurisdiction"); + if (input.evidenceType === "unknown") warnings.push("unknown_evidence_type"); + if (input.validationStatus === "unverified" || input.validationStatus === "unknown") { + warnings.push("verification_unknown"); + } + if (effectiveDocumentStatus(input) === "outdated") warnings.push("outdated"); + if (hasIdentifiedReplacement(input)) warnings.push("superseded"); + return sortedWarnings(warnings); +} + +function rateClinicalSourceWithWarnings( + input: ClinicalSourceReferenceInput, + warnings: readonly SourceCatalogueWarning[], +): ClinicalSourceRating { + const authority = authorityFor(input); + const geography = geographyFor(input); + const accuracyAssurance = ACCURACY[input.validationStatus]; + const reliability = + authority.designation === "official" + ? 20 + : authority.designation === "trusted" + ? 16 + : hasStableIdentity(input) && Boolean(input.publisher?.trim()) + ? 8 + : 0; + const evidenceQuality = EVIDENCE[input.evidenceType]; + const currency = CURRENCY[effectiveDocumentStatus(input)]; + const australianApplicability = AUSTRALIAN[geography.scope]; + const traceability = [ + hasStableIdentity(input), + Boolean(input.version), + Boolean(input.publicationDate || input.reviewDate || input.expiryDate), + canonicalLocationFor([input]).kind !== "none", + Boolean(input.usage.recordId && input.usage.recordLabel && input.usage.field), + ].filter(Boolean).length; + const dimensions = { + accuracyAssurance, + reliability, + evidenceQuality, + currency, + australianApplicability, + traceability, + }; + const score = Object.values(dimensions).reduce((total, value) => total + value, 0); + const incompleteMetadata = warnings.some((warning) => INCOMPLETE_METADATA_WARNINGS.has(warning)); + const materialUncertainty = warnings.some( + (warning) => + INCOMPLETE_METADATA_WARNINGS.has(warning) || + ["ambiguous_identity", "unsafe_location", "metadata_conflict"].includes(warning), + ); + const lifecycleStatus = effectiveLifecycleStatus(input); + const band = + lifecycleStatus === "excluded" + ? "excluded" + : materialUncertainty || score < 50 + ? "D" + : score >= 85 + ? "A" + : score >= 70 + ? "B" + : "C"; + + return { + score, + band, + dimensions, + weights: SOURCE_RATING_WEIGHTS, + reasons: [ + `Accuracy assurance: ${accuracyAssurance}/${SOURCE_RATING_WEIGHTS.accuracyAssurance}`, + `Reliability: ${reliability}/${SOURCE_RATING_WEIGHTS.reliability}`, + `Evidence quality: ${evidenceQuality}/${SOURCE_RATING_WEIGHTS.evidenceQuality}`, + `Currency: ${currency}/${SOURCE_RATING_WEIGHTS.currency}`, + `Australian applicability: ${australianApplicability}/${SOURCE_RATING_WEIGHTS.australianApplicability}`, + `Traceability: ${traceability}/${SOURCE_RATING_WEIGHTS.traceability}`, + ...(lifecycleStatus === "excluded" + ? [ + hasIdentifiedReplacement(input) + ? "Excluded because a current replacement is identified" + : "Excluded by lifecycle status", + ] + : materialUncertainty + ? [ + incompleteMetadata + ? "Incomplete source metadata requires review" + : "Material identity or verification uncertainty requires review", + ] + : []), + ], + }; +} + +export function rateClinicalSource(input: ClinicalSourceReferenceInput): ClinicalSourceRating { + return rateClinicalSourceWithWarnings(input, sourceWarnings(input)); +} + +function uniqueStrings(values: readonly (string | null | undefined)[]) { + return [...new Set(values.map((value) => value?.trim()).filter((value): value is string => Boolean(value)))].sort( + compareText, + ); +} + +function sortedWarnings(values: readonly SourceCatalogueWarning[]) { + return [...new Set(values)].sort(compareText); +} + +function compareText(left: string, right: string) { + return left.localeCompare(right, "en-AU", { sensitivity: "base" }) || left.localeCompare(right, "en-AU"); +} + +function canonicalReferenceKey(input: ClinicalSourceReferenceInput) { + return JSON.stringify([ + input.sourceId, + input.documentId, + input.title, + [...input.aliases].sort(compareText), + input.publisher, + input.publisherCode, + input.jurisdiction, + input.version, + input.canonicalUrl, + input.datasetLocation, + input.publicationDate, + input.reviewDate, + input.expiryDate, + input.evidenceType, + input.documentStatus, + input.validationStatus, + input.contentMode, + input.lifecycleStatus, + [...input.supersedes].sort(compareText), + [...input.supersededBy].sort(compareText), + [...input.topics].sort(compareText), + input.usage.modeId, + input.usage.recordId, + input.usage.recordLabel, + input.usage.field, + input.referenceText, + ]); +} + +function uniqueUsages(values: readonly SourceUsage[]) { + const usages = new Map(); + for (const usage of values) { + const key = [usage.modeId, usage.recordId, usage.recordLabel, usage.field].join("\u0000"); + usages.set(key, usage); + } + return [...usages.values()].sort((left, right) => + compareText( + [left.modeId, left.recordLabel, left.recordId, left.field].join("\u0000"), + [right.modeId, right.recordLabel, right.recordId, right.field].join("\u0000"), + ), + ); +} + +function firstString(values: readonly (string | null | undefined)[]) { + return uniqueStrings(values).at(0) ?? null; +} + +function worstValue(values: readonly T[], orderedWorstFirst: readonly T[]) { + const present = new Set(values); + return orderedWorstFirst.find((value) => present.has(value)) ?? values[0]; +} + +function mergedReference(inputs: readonly ClinicalSourceReferenceInput[]): ClinicalSourceReferenceInput { + const ordered = [...inputs].sort((left, right) => + compareText(canonicalReferenceKey(left), canonicalReferenceKey(right)), + ); + const title = firstString(ordered.map((input) => input.title)); + const referenceText = title ? null : firstString(ordered.map((input) => input.referenceText)); + return { + ...ordered[0], + sourceId: firstString(ordered.map((input) => input.sourceId)), + documentId: firstString(ordered.map((input) => input.documentId)), + title, + aliases: uniqueStrings( + ordered.flatMap((input) => [...input.aliases, ...(input.title && input.title !== title ? [input.title] : [])]), + ), + publisher: firstString(ordered.map((input) => input.publisher)), + publisherCode: firstString(ordered.map((input) => input.publisherCode)), + canonicalUrl: firstString(ordered.map((input) => safeHttpsUrl(input.canonicalUrl))), + datasetLocation: firstString(ordered.map((input) => input.datasetLocation)), + version: firstString(ordered.map((input) => input.version)), + publicationDate: firstString(ordered.map((input) => strictSourceDate(input.publicationDate))), + reviewDate: firstString(ordered.map((input) => strictSourceDate(input.reviewDate))), + expiryDate: firstString(ordered.map((input) => strictSourceDate(input.expiryDate))), + evidenceType: worstValue( + ordered.map((input) => input.evidenceType), + [ + "unknown", + "other", + "dataset", + "uploaded_document", + "consumer_reference", + "professional_reference", + "primary_study", + "systematic_review", + "guideline", + "standard", + "legislation", + "regulatory", + ] satisfies ClinicalSourceType[], + ), + documentStatus: worstValue(ordered.map(effectiveDocumentStatus), ["outdated", "review_due", "unknown", "current"]), + validationStatus: worstValue( + ordered.map((input) => input.validationStatus), + ["unknown", "unverified", "locally_reviewed", "approved"], + ), + contentMode: worstValue( + ordered.map((input) => input.contentMode), + ["metadata_only", "link_only", "indexed_content"], + ), + lifecycleStatus: worstValue(ordered.map(effectiveLifecycleStatus), [ + "excluded", + "inactive", + "active", + ] satisfies SourceLifecycleStatus[]), + supersedes: uniqueStrings(ordered.flatMap((input) => input.supersedes)), + supersededBy: uniqueStrings(ordered.flatMap((input) => input.supersededBy)), + topics: uniqueStrings(ordered.flatMap((input) => input.topics)), + usage: uniqueUsages(ordered.map((input) => input.usage))[0], + referenceText, + }; +} + +function catalogueEntry( + identity: string, + inputs: readonly ClinicalSourceReferenceInput[], + metadataConflict: boolean, +): ClinicalSourceCatalogueEntry { + const merged = mergedReference(inputs); + const aliases = uniqueStrings( + inputs.flatMap((input) => [ + ...input.aliases, + ...(input.title && input.title !== merged.title ? [input.title] : []), + ]), + ); + const warnings = sortedWarnings([ + ...inputs.flatMap(sourceWarnings), + ...(metadataConflict ? (["metadata_conflict"] satisfies SourceCatalogueWarning[]) : []), + ]); + const canonicalLocation = canonicalLocationFor(inputs); + const title = merged.title ?? firstString(inputs.map((input) => input.referenceText)) ?? "Untitled clinical source"; + return { + id: opaqueSourceId(identity), + sourceId: merged.sourceId, + title, + aliases, + version: merged.version, + publisher: merged.publisher, + publisherCode: merged.publisherCode, + sourceType: merged.evidenceType, + canonicalLocation, + geography: geographyFor(merged), + topics: merged.topics, + publicationDate: merged.publicationDate, + reviewDate: merged.reviewDate, + expiryDate: merged.expiryDate, + documentStatus: merged.documentStatus, + validationStatus: merged.validationStatus, + contentMode: merged.contentMode, + lifecycleStatus: merged.lifecycleStatus, + supersedes: merged.supersedes, + supersededBy: merged.supersededBy, + usedBy: uniqueUsages(inputs.map((input) => input.usage)), + rating: rateClinicalSourceWithWarnings(merged, warnings), + warnings, + }; +} + +export function canonicalizeSourceReferences( + inputs: readonly ClinicalSourceReferenceInput[], +): ClinicalSourceCatalogueEntry[] { + const identityGroups = new Map(); + const unresolvedByKey = new Map(); + for (const input of inputs) { + const identity = baseIdentity(input); + if (identity === "provisional:unresolved") { + const key = canonicalReferenceKey(input); + unresolvedByKey.set(key, [...(unresolvedByKey.get(key) ?? []), input]); + continue; + } + identityGroups.set(identity, [...(identityGroups.get(identity) ?? []), input]); + } + + const entries = [...unresolvedByKey.entries()] + .sort(([left], [right]) => compareText(left, right)) + .flatMap(([key, keyInputs]) => + keyInputs.map((input, index) => + catalogueEntry(`provisional:unresolved|key:${key}|occurrence:${index}`, [input], false), + ), + ); + for (const [identity, identityInputs] of identityGroups) { + const partitions = new Map(); + for (const input of identityInputs) { + const key = compatibilityKey(input); + partitions.set(key, [...(partitions.get(key) ?? []), input]); + } + const metadataConflict = partitions.size > 1; + for (const [key, partition] of partitions) { + entries.push(catalogueEntry(`${identity}|compatibility:${key}`, partition, metadataConflict)); + } + } + return entries.sort(compareClinicalSources); +} + +export function compareClinicalSources(left: ClinicalSourceCatalogueEntry, right: ClinicalSourceCatalogueEntry) { + return ( + BAND_ORDER[left.rating.band] - BAND_ORDER[right.rating.band] || + right.rating.score - left.rating.score || + right.rating.dimensions.australianApplicability - left.rating.dimensions.australianApplicability || + right.rating.dimensions.currency - left.rating.dimensions.currency || + compareText(left.title, right.title) || + compareText(left.id, right.id) + ); +} diff --git a/src/lib/sources/catalogue-types.ts b/src/lib/sources/catalogue-types.ts new file mode 100644 index 0000000000..6cd68a1384 --- /dev/null +++ b/src/lib/sources/catalogue-types.ts @@ -0,0 +1,136 @@ +import type { AppModeId } from "@/lib/app-modes"; + +export type ClinicalSourceType = + | "guideline" + | "systematic_review" + | "primary_study" + | "standard" + | "legislation" + | "regulatory" + | "professional_reference" + | "consumer_reference" + | "uploaded_document" + | "dataset" + | "other" + | "unknown"; + +export type SourceGeographyScope = "wa" | "australian_national" | "australian_state" | "international" | "unknown"; +export type SourceLifecycleStatus = "active" | "inactive" | "excluded"; +export type SourceContentMode = "indexed_content" | "link_only" | "metadata_only"; +export type SourceQualityBand = "A" | "B" | "C" | "D" | "excluded"; +export type SourceCatalogueWarning = + | "ambiguous_identity" + | "metadata_conflict" + | "unsafe_location" + | "invalid_date" + | "missing_publisher" + | "missing_version" + | "missing_dates" + | "unknown_jurisdiction" + | "unknown_evidence_type" + | "verification_unknown" + | "outdated" + | "superseded"; + +export type SourceUsage = { + modeId: AppModeId; + recordId: string; + recordLabel: string; + field: string; +}; + +export type SourceCanonicalLocation = + | { kind: "url"; href: string } + | { kind: "document"; documentId: string; href: string } + | { kind: "dataset"; label: string } + | { kind: "none" }; + +export type ClinicalSourceReferenceInput = { + sourceId: string | null; + documentId: string | null; + title: string | null; + aliases: string[]; + publisher: string | null; + publisherCode: string | null; + canonicalUrl: string | null; + datasetLocation: string | null; + version: string | null; + publicationDate: string | null; + reviewDate: string | null; + expiryDate: string | null; + jurisdiction: string | null; + evidenceType: ClinicalSourceType; + documentStatus: "current" | "review_due" | "outdated" | "unknown"; + validationStatus: "approved" | "locally_reviewed" | "unverified" | "unknown"; + contentMode: SourceContentMode; + lifecycleStatus: SourceLifecycleStatus; + supersedes: string[]; + supersededBy: string[]; + topics: string[]; + usage: SourceUsage; + referenceText: string | null; +}; + +export type ClinicalSourceRating = { + score: number; + band: SourceQualityBand; + dimensions: { + accuracyAssurance: number; + reliability: number; + evidenceQuality: number; + currency: number; + australianApplicability: number; + traceability: number; + }; + weights: typeof SOURCE_RATING_WEIGHTS; + reasons: string[]; +}; + +export const SOURCE_RATING_WEIGHTS = { + accuracyAssurance: 25, + reliability: 20, + evidenceQuality: 20, + currency: 15, + australianApplicability: 15, + traceability: 5, +} as const; + +export type ClinicalSourceCatalogueEntry = { + id: string; + sourceId: string | null; + title: string; + aliases: string[]; + version: string | null; + publisher: string | null; + publisherCode: string | null; + sourceType: ClinicalSourceType; + canonicalLocation: SourceCanonicalLocation; + geography: { scope: SourceGeographyScope; label: string }; + topics: string[]; + publicationDate: string | null; + reviewDate: string | null; + expiryDate: string | null; + documentStatus: ClinicalSourceReferenceInput["documentStatus"]; + validationStatus: ClinicalSourceReferenceInput["validationStatus"]; + contentMode: SourceContentMode; + lifecycleStatus: SourceLifecycleStatus; + supersedes: string[]; + supersededBy: string[]; + usedBy: SourceUsage[]; + rating: ClinicalSourceRating; + warnings: SourceCatalogueWarning[]; +}; + +export type SourceCatalogueFilters = { + q: string; + bands: SourceQualityBand[]; + jurisdictions: SourceGeographyScope[]; + sourceTypes: ClinicalSourceType[]; + publishers: string[]; + topics: string[]; + lifecycleStatuses: SourceLifecycleStatus[]; + documentStatuses: ClinicalSourceReferenceInput["documentStatus"][]; + validationStatuses: ClinicalSourceReferenceInput["validationStatus"][]; + usedBy: AppModeId[]; + sort: "quality" | "title" | "currency"; +}; diff --git a/src/lib/sources/catalogue-view.ts b/src/lib/sources/catalogue-view.ts new file mode 100644 index 0000000000..99c30c25fa --- /dev/null +++ b/src/lib/sources/catalogue-view.ts @@ -0,0 +1,172 @@ +import type { AppModeId } from "@/lib/app-modes"; +import type { + ClinicalSourceCatalogueEntry, + ClinicalSourceReferenceInput, + ClinicalSourceType, + SourceCatalogueFilters, + SourceGeographyScope, + SourceLifecycleStatus, + SourceQualityBand, +} from "@/lib/sources/catalogue-types"; + +type ReadableSearchParams = Pick; +const BAND_ORDER = { A: 0, B: 1, C: 2, D: 3, excluded: 4 } as const; + +function compareText(left: string, right: string) { + return left.localeCompare(right, "en-AU", { sensitivity: "base" }) || left.localeCompare(right, "en-AU"); +} + +function compareQuality(left: ClinicalSourceCatalogueEntry, right: ClinicalSourceCatalogueEntry) { + return ( + BAND_ORDER[left.rating.band] - BAND_ORDER[right.rating.band] || + right.rating.score - left.rating.score || + right.rating.dimensions.australianApplicability - left.rating.dimensions.australianApplicability || + right.rating.dimensions.currency - left.rating.dimensions.currency || + compareText(left.title, right.title) || + compareText(left.id, right.id) + ); +} + +function valuesFrom(params: ReadableSearchParams, key: string) { + return params + .getAll(key) + .flatMap((value) => value.split(",")) + .map((value) => value.trim()) + .filter(Boolean); +} + +function uniqueKnown(values: readonly string[], known: ReadonlySet): T[] { + return [...new Set(values.filter((value): value is T => known.has(value as T)))]; +} + +function presentValues(values: readonly (T | null)[]) { + return new Set(values.filter((value): value is T => Boolean(value))); +} + +export function parseSourceCatalogueFilters( + params: ReadableSearchParams, + entries: readonly ClinicalSourceCatalogueEntry[], +): SourceCatalogueFilters { + const sortValue = params.get("sort"); + return { + q: (params.get("q") ?? "").trim(), + bands: uniqueKnown( + valuesFrom(params, "band"), + presentValues(entries.map((entry) => entry.rating.band)), + ), + jurisdictions: uniqueKnown( + valuesFrom(params, "jurisdiction"), + presentValues(entries.map((entry) => entry.geography.scope)), + ), + sourceTypes: uniqueKnown( + valuesFrom(params, "type"), + presentValues(entries.map((entry) => entry.sourceType)), + ), + publishers: uniqueKnown(valuesFrom(params, "publisher"), presentValues(entries.map((entry) => entry.publisher))), + topics: uniqueKnown(valuesFrom(params, "topic"), presentValues(entries.flatMap((entry) => entry.topics))), + lifecycleStatuses: uniqueKnown( + valuesFrom(params, "lifecycle"), + presentValues(entries.map((entry) => entry.lifecycleStatus)), + ), + documentStatuses: uniqueKnown( + valuesFrom(params, "status"), + presentValues(entries.map((entry) => entry.documentStatus)), + ), + validationStatuses: uniqueKnown( + valuesFrom(params, "validation"), + presentValues(entries.map((entry) => entry.validationStatus)), + ), + usedBy: uniqueKnown( + valuesFrom(params, "usedBy"), + presentValues(entries.flatMap((entry) => entry.usedBy.map((usage) => usage.modeId))), + ), + sort: sortValue === "title" || sortValue === "currency" ? sortValue : "quality", + }; +} + +function normalizeSearchValue(value: string) { + return value.normalize("NFKC").trim().toLocaleLowerCase("en-AU").replace(/\s+/g, " "); +} + +function matchesAny(selection: readonly T[], values: readonly T[]) { + return selection.length === 0 || values.some((value) => selection.includes(value)); +} + +function matchesFilters(entry: ClinicalSourceCatalogueEntry, filters: SourceCatalogueFilters) { + const query = normalizeSearchValue(filters.q); + if ( + query && + ![entry.title, ...entry.aliases, entry.publisher ?? "", ...entry.topics] + .map(normalizeSearchValue) + .some((value) => value.includes(query)) + ) { + return false; + } + if (!matchesAny(filters.bands, [entry.rating.band])) return false; + if (!matchesAny(filters.jurisdictions, [entry.geography.scope])) return false; + if (!matchesAny(filters.sourceTypes, [entry.sourceType])) return false; + if (!matchesAny(filters.publishers, entry.publisher ? [entry.publisher] : [])) return false; + if (!matchesAny(filters.topics, entry.topics)) return false; + if (!matchesAny(filters.lifecycleStatuses, [entry.lifecycleStatus])) return false; + if (!matchesAny(filters.documentStatuses, [entry.documentStatus])) return false; + if (!matchesAny(filters.validationStatuses, [entry.validationStatus])) return false; + if ( + !matchesAny( + filters.usedBy, + entry.usedBy.map((usage) => usage.modeId), + ) + ) + return false; + return true; +} + +function dateValue(value: string | null) { + if (!value) return Number.NEGATIVE_INFINITY; + const timestamp = Date.parse(value); + return Number.isNaN(timestamp) ? Number.NEGATIVE_INFINITY : timestamp; +} + +function mostRecentDate(entry: ClinicalSourceCatalogueEntry) { + return Math.max(dateValue(entry.publicationDate), dateValue(entry.reviewDate), dateValue(entry.expiryDate)); +} + +export function filterAndSortSourceCatalogue( + entries: readonly ClinicalSourceCatalogueEntry[], + filters: SourceCatalogueFilters, +) { + const filtered = entries.filter((entry) => matchesFilters(entry, filters)); + return filtered.sort((left, right) => { + if (filters.sort === "title") { + return compareText(left.title, right.title) || compareText(left.id, right.id); + } + if (filters.sort === "currency") { + return ( + right.rating.dimensions.currency - left.rating.dimensions.currency || + mostRecentDate(right) - mostRecentDate(left) || + compareQuality(left, right) + ); + } + return compareQuality(left, right); + }); +} + +function countValues(values: readonly string[]) { + const counts = new Map(); + for (const value of values) counts.set(value, (counts.get(value) ?? 0) + 1); + return [...counts] + .map(([value, count]) => ({ value, count })) + .sort((left, right) => compareText(left.value, right.value)); +} + +export function deriveSourceCatalogueFacets(entries: readonly ClinicalSourceCatalogueEntry[]) { + return { + total: entries.length, + australian: entries.filter( + (entry) => entry.geography.scope !== "international" && entry.geography.scope !== "unknown", + ).length, + reviewRequired: entries.filter((entry) => entry.rating.band === "D").length, + inactiveOrExcluded: entries.filter((entry) => entry.lifecycleStatus !== "active").length, + topics: countValues(entries.flatMap((entry) => entry.topics)), + publishers: countValues(entries.map((entry) => entry.publisher).filter((value): value is string => Boolean(value))), + }; +} diff --git a/src/lib/sources/document-source-loader.ts b/src/lib/sources/document-source-loader.ts new file mode 100644 index 0000000000..c8db301859 --- /dev/null +++ b/src/lib/sources/document-source-loader.ts @@ -0,0 +1,108 @@ +import "server-only"; + +import { withOwnerReadScope } from "@/lib/public-api-access"; +import { normalizeSourceMetadata } from "@/lib/source-metadata"; +import type { ClinicalSourceReferenceInput } from "@/lib/sources/catalogue-types"; +import { createAdminClient } from "@/lib/supabase/admin"; +import { createSupabaseServerClient } from "@/lib/supabase/server"; + +const DOCUMENT_SOURCE_COLUMNS = "id,owner_id,title,file_name,status,metadata,updated_at"; + +function createDocumentSourceQuery() { + return createAdminClient().from("documents").select(DOCUMENT_SOURCE_COLUMNS); +} + +type DocumentSourceQuery = ReturnType; + +type DocumentSourceRow = { + id?: unknown; + title?: unknown; + file_name?: unknown; + status?: unknown; + metadata?: unknown; +}; + +export type DocumentSourceLoadResult = { + references: ClinicalSourceReferenceInput[]; + availability: "available" | "unavailable"; +}; + +export type DocumentSourceLoaderDependencies = { + viewerId(): Promise; + query(): DocumentSourceQuery; +}; + +function cleanString(value: unknown) { + return typeof value === "string" && value.trim() ? value.trim() : null; +} + +export function documentRowsToSourceReferences(rows: readonly unknown[]): ClinicalSourceReferenceInput[] { + const references: ClinicalSourceReferenceInput[] = []; + for (const input of rows) { + if (!input || typeof input !== "object") continue; + const row = input as DocumentSourceRow; + if (row.status !== "indexed") continue; + const documentId = cleanString(row.id); + if (!documentId) continue; + const metadata = normalizeSourceMetadata(row.metadata); + if (metadata.source_kind === "registry_record") continue; + const title = + metadata.source_title ?? cleanString(row.title) ?? cleanString(row.file_name) ?? "Untitled document source"; + references.push({ + sourceId: null, + documentId, + title, + aliases: [], + publisher: metadata.publisher, + publisherCode: metadata.publisher_code ?? null, + canonicalUrl: null, + datasetLocation: null, + version: metadata.version, + publicationDate: metadata.publication_date, + reviewDate: metadata.review_date, + expiryDate: null, + jurisdiction: metadata.jurisdiction, + evidenceType: "unknown", + documentStatus: metadata.document_status, + validationStatus: + row.metadata && + typeof row.metadata === "object" && + cleanString((row.metadata as Record).clinical_validation_status) + ? metadata.clinical_validation_status + : "unknown", + contentMode: "indexed_content", + lifecycleStatus: "active", + supersedes: [], + supersededBy: [], + topics: [], + usage: { modeId: "documents", recordId: documentId, recordLabel: title, field: "source metadata" }, + referenceText: null, + }); + } + return references; +} + +const defaultDocumentSourceLoaderDependencies: DocumentSourceLoaderDependencies = { + async viewerId() { + const client = await createSupabaseServerClient(); + if (!client) return undefined; + const { data, error } = await client.auth.getUser(); + if (error) throw new Error("Document source authentication is unavailable"); + return data.user?.id; + }, + query: createDocumentSourceQuery, +}; + +export async function loadVisibleDocumentSourceReferences( + dependencies: DocumentSourceLoaderDependencies = defaultDocumentSourceLoaderDependencies, +): Promise { + try { + const viewerId = await dependencies.viewerId(); + const query = withOwnerReadScope(dependencies.query(), viewerId); + const { data, error } = await query.eq("status", "indexed").order("updated_at", { ascending: false }); + if (error) return { references: [], availability: "unavailable" }; + return { references: documentRowsToSourceReferences(data ?? []), availability: "available" }; + } catch { + return { references: [], availability: "unavailable" }; + } +} diff --git a/src/lib/sources/load-source-catalogue.ts b/src/lib/sources/load-source-catalogue.ts new file mode 100644 index 0000000000..dbac13ec5a --- /dev/null +++ b/src/lib/sources/load-source-catalogue.ts @@ -0,0 +1,19 @@ +import "server-only"; + +import { canonicalizeSourceReferences } from "@/lib/sources/catalogue-core"; +import type { ClinicalSourceCatalogueEntry } from "@/lib/sources/catalogue-types"; +import { loadVisibleDocumentSourceReferences } from "@/lib/sources/document-source-loader"; +import { repositorySourceReferences } from "@/lib/sources/repository-providers"; + +export type LoadedSourceCatalogue = { + entries: ClinicalSourceCatalogueEntry[]; + hostedDocuments: "available" | "unavailable"; +}; + +export async function loadSourceCatalogue(): Promise { + const documents = await loadVisibleDocumentSourceReferences(); + return { + entries: canonicalizeSourceReferences([...repositorySourceReferences(), ...documents.references]), + hostedDocuments: documents.availability, + }; +} diff --git a/src/lib/sources/repository-providers.ts b/src/lib/sources/repository-providers.ts new file mode 100644 index 0000000000..9f9d1800ee --- /dev/null +++ b/src/lib/sources/repository-providers.ts @@ -0,0 +1,638 @@ +import "server-only"; + +import { createHash } from "node:crypto"; + +import formsSnapshot from "../../../data/forms-page-snapshot.json"; +import dsmClinicalContent from "../../data/dsm-clinical-content.json"; +import therapiesSource from "../../data/therapies-source.json"; +import { calculators } from "../../components/calculators/calculator-fixtures"; +import { factsheets } from "../../components/factsheets/factsheets-data"; +import { + dictionaryComparisonPairs, + dictionaryEntries, + dictionarySources, + type DictionarySourceRef, +} from "@/lib/dictionary-data"; +import { + formulationMechanisms, + formulationSourceLibrary, + type FormulationMechanism, + type FormulationSource, +} from "@/lib/formulation"; +import { loadMedicationSnapshot } from "@/lib/medication-snapshot"; +import { mhaActMetadata } from "@/lib/mha-act-sections"; +import { loadServicesSnapshot } from "@/lib/service-catalog"; +import { authoritativeSources, loadSpecifiersContent, type AuthoritativeSource } from "@/lib/specifiers-content"; +import { safeHttpsUrl } from "@/lib/sources/catalogue-core"; +import type { ClinicalSourceReferenceInput, ClinicalSourceType, SourceUsage } from "@/lib/sources/catalogue-types"; +import { hasInvalidStructuredSourceDate, strictSourceDate } from "@/lib/sources/source-date-policy"; + +export type ClinicalSourceProvider = { + id: + | "dictionary" + | "factsheets" + | "formulation" + | "therapies" + | "specifiers" + | "forms" + | "mha" + | "medications" + | "services" + | "dsm" + | "calculators"; + sourcePaths: readonly string[]; + references(): ClinicalSourceReferenceInput[]; +}; + +function reference( + usage: SourceUsage, + overrides: Partial = {}, +): ClinicalSourceReferenceInput { + return { + sourceId: null, + documentId: null, + title: null, + aliases: [], + publisher: null, + publisherCode: null, + canonicalUrl: null, + datasetLocation: null, + version: null, + publicationDate: null, + reviewDate: null, + expiryDate: null, + jurisdiction: null, + evidenceType: "unknown", + documentStatus: "unknown", + validationStatus: "unknown", + contentMode: "metadata_only", + lifecycleStatus: "active", + supersedes: [], + supersededBy: [], + topics: [], + usage, + referenceText: null, + ...overrides, + }; +} + +const dictionarySourceById = new Map( + dictionarySources.map((source) => [source.id, source]), +); + +function dictionaryReference(sourceRef: DictionarySourceRef, usage: SourceUsage, topics: string[]) { + const source = dictionarySourceById.get(sourceRef.sourceId); + if (!source) return null; + return reference(usage, { + sourceId: source.id, + title: source.title, + publisher: source.organisation, + canonicalUrl: source.url, + reviewDate: source.accessedOn, + jurisdiction: source.region, + validationStatus: "unverified", + contentMode: "link_only", + topics, + }); +} + +const dictionaryProvider: ClinicalSourceProvider = { + id: "dictionary", + sourcePaths: ["src/lib/dictionary-data.ts"], + references() { + const references: ClinicalSourceReferenceInput[] = []; + for (const entry of dictionaryEntries) { + for (const sourceRef of entry.sourceRefs) { + for (const field of sourceRef.supports) { + const projected = dictionaryReference( + sourceRef, + { modeId: "dictionary", recordId: entry.slug, recordLabel: entry.term, field }, + [entry.topicSlug], + ); + if (projected) references.push(projected); + } + } + for (const distinction of entry.distinctions) { + for (const sourceRef of distinction.sourceRefs) { + const projected = dictionaryReference( + sourceRef, + { + modeId: "dictionary", + recordId: entry.slug, + recordLabel: entry.term, + field: `distinctions.${distinction.slug}`, + }, + [entry.topicSlug], + ); + if (projected) references.push(projected); + } + } + } + for (const comparison of dictionaryComparisonPairs) { + for (const sourceRef of comparison.sourceRefs) { + const projected = dictionaryReference( + sourceRef, + { + modeId: "dictionary", + recordId: comparison.slugs.join("--"), + recordLabel: comparison.slugs.join(" / "), + field: "comparison", + }, + ["comparison"], + ); + if (projected) references.push(projected); + } + } + return references; + }, +}; + +function factsheetEvidenceType(tag: string): ClinicalSourceType { + if (tag === "Consumer") return "consumer_reference"; + if (tag === "Reference") return "professional_reference"; + return "unknown"; +} + +const factsheetProvider: ClinicalSourceProvider = { + id: "factsheets", + sourcePaths: ["src/components/factsheets/factsheets-data.ts"], + references: () => + factsheets.flatMap((sheet) => + sheet.sources.map((source) => + reference( + { modeId: "factsheets", recordId: sheet.slug, recordLabel: sheet.title, field: "sources" }, + { + title: source.title, + publisher: source.org, + canonicalUrl: source.url ?? null, + publicationDate: null, + evidenceType: factsheetEvidenceType(source.tag), + contentMode: source.url ? "link_only" : "metadata_only", + topics: [sheet.category], + }, + ), + ), + ), +}; + +const formulationProvider: ClinicalSourceProvider = { + id: "formulation", + sourcePaths: ["src/data/formulation-content.json"], + references: () => + formulationMechanisms.flatMap((mechanism) => + mechanism.sources.flatMap((sourceId) => { + const source = formulationSourceLibrary[sourceId]; + if (!source) return []; + return [ + reference( + { + modeId: "formulation", + recordId: mechanism.id, + recordLabel: mechanism.name, + field: "sources", + }, + { + sourceId: source.id, + title: source.title, + canonicalUrl: source.url, + contentMode: "link_only", + topics: [...mechanism.domains], + }, + ), + ]; + }), + ), +}; + +type TherapySourceRecord = { + slug: string; + name: string; + reviewStatus: string; + reviewChecklist?: { sourceChecked?: boolean }; + sources: Array<{ title: string; sourceType: string; reference: string }>; +}; + +const therapyProvider: ClinicalSourceProvider = { + id: "therapies", + sourcePaths: ["src/data/therapies-source.json"], + references: () => + (therapiesSource as TherapySourceRecord[]).flatMap((therapy) => + therapy.sources.map((source) => + reference( + { modeId: "therapy-compass", recordId: therapy.slug, recordLabel: therapy.name, field: "sources" }, + { + title: source.title, + evidenceType: "uploaded_document", + validationStatus: + therapy.reviewStatus === "needs_review" || therapy.reviewChecklist?.sourceChecked === false + ? "unverified" + : "unknown", + referenceText: source.reference, + }, + ), + ), + ), +}; + +function specifierReviewReferences() { + const content = loadSpecifiersContent(); + const references: ClinicalSourceReferenceInput[] = []; + const add = (sourceFamily: string | undefined, usage: SourceUsage) => { + if (!sourceFamily?.trim()) return; + references.push( + reference(usage, { + title: sourceFamily, + validationStatus: "unverified", + referenceText: sourceFamily, + }), + ); + }; + for (const specifier of content.universalSpecifiers) { + add(specifier.review.sourceFamily, { + modeId: "specifiers", + recordId: specifier.review.rowKey, + recordLabel: specifier.title, + field: "review.sourceFamily", + }); + } + for (const category of content.categories) { + for (const disorder of category.disorders) { + for (const group of disorder.groups) { + for (const item of group.items) { + add(item.review.sourceFamily, { + modeId: "specifiers", + recordId: item.review.rowKey, + recordLabel: item.label, + field: "review.sourceFamily", + }); + } + } + } + } + return references; +} + +export function specifierAuthoritativeSourceReferences( + sources: readonly AuthoritativeSource[], +): ClinicalSourceReferenceInput[] { + return sources.map((source) => + reference( + { + modeId: "specifiers", + recordId: `authoritative-source-${createHash("sha256").update(source.url).digest("hex").slice(0, 16)}`, + recordLabel: source.label, + field: "authoritativeSources", + }, + { + title: source.label, + canonicalUrl: source.url, + contentMode: "link_only", + }, + ), + ); +} + +const specifierProvider: ClinicalSourceProvider = { + id: "specifiers", + sourcePaths: ["data/specifiers-content.json"], + references: () => [...specifierAuthoritativeSourceReferences(authoritativeSources()), ...specifierReviewReferences()], +}; + +const formsProvider: ClinicalSourceProvider = { + id: "forms", + sourcePaths: ["data/forms-page-snapshot.json"], + references: () => + formsSnapshot.sourceDocuments.flatMap((document) => { + const referencingForms = formsSnapshot.forms.filter((form) => form.sourceDocumentId === document.id); + const usages: SourceUsage[] = referencingForms.length + ? referencingForms.map((form) => ({ + modeId: "forms", + recordId: form.id, + recordLabel: form.name, + field: "sourceDocumentId", + })) + : [ + { + modeId: "forms", + recordId: document.id, + recordLabel: document.title || document.fileName, + field: "sourceDocuments", + }, + ]; + return usages.map((usage) => + reference(usage, { + sourceId: document.id, + title: document.title || document.fileName, + datasetLocation: `Forms source document (${document.kind})`, + topics: [document.kind], + }), + ); + }), +}; + +const mhaProvider: ClinicalSourceProvider = { + id: "mha", + sourcePaths: ["data/mha-2014-sections.source.json"], + references: () => [ + reference( + { + modeId: "forms", + recordId: "mental-health-act-2014-wa", + recordLabel: "Mental Health Act 2014 (WA)", + field: "act", + }, + { + sourceId: "mental-health-act-2014-wa", + title: "Mental Health Act 2014 (WA)", + canonicalUrl: mhaActMetadata.sourceUrl, + version: mhaActMetadata.actVersion, + reviewDate: mhaActMetadata.actAsAt, + jurisdiction: "Australia/WA", + evidenceType: "legislation", + contentMode: "link_only", + topics: ["Mental Health Act", "legislation"], + }, + ), + ], +}; + +function medicationSourceRows() { + return loadMedicationSnapshot().flatMap((medication) => + medication.sections.flatMap((section) => + section.rows + .filter((row) => section.title === "Sources" || row.key === "Source Review") + .map((row) => ({ medication, section, row })), + ), + ); +} + +const medicationProvider: ClinicalSourceProvider = { + id: "medications", + sourcePaths: ["data/medications-snapshot.json"], + references: () => + medicationSourceRows().map(({ medication, section, row }) => + reference( + { + modeId: "prescribing", + recordId: medication.slug, + recordLabel: medication.name, + field: `${section.title}.${row.key}`, + }, + { + title: `${medication.name}: ${row.key || section.title}`, + validationStatus: "unverified", + referenceText: row.val, + topics: [medication.category, medication.class].filter(Boolean), + }, + ), + ), +}; + +const servicesProvider: ClinicalSourceProvider = { + id: "services", + sourcePaths: ["data/services-snapshot.json"], + references: () => + loadServicesSnapshot().services.flatMap((service) => [ + ...service.public_source_urls.map((url) => + reference( + { modeId: "services", recordId: service.id, recordLabel: service.name, field: "public_source_urls" }, + { + title: service.name, + canonicalUrl: url, + contentMode: "link_only", + topics: [...service.tags.setting_flags, ...service.tags.acuity_flags], + }, + ), + ), + ...service.source_documents.map((sourceDocument) => + reference( + { modeId: "services", recordId: service.id, recordLabel: service.name, field: "source_documents" }, + { + title: sourceDocument, + validationStatus: "unverified", + referenceText: sourceDocument, + topics: [...service.tags.setting_flags, ...service.tags.acuity_flags], + }, + ), + ), + ]), +}; + +type DsmClinicalContent = { + export_format_version: string; + generated_at: string; + source_repository: string; + diagnoses: Array<{ record_id: string; title: string; category?: { label?: string } }>; +}; + +const dsmProvider: ClinicalSourceProvider = { + id: "dsm", + sourcePaths: ["src/data/dsm-clinical-content.json"], + references: () => { + const content = dsmClinicalContent as DsmClinicalContent; + return content.diagnoses.map((diagnosis) => + reference( + { modeId: "dsm", recordId: diagnosis.record_id, recordLabel: diagnosis.title, field: "source_repository" }, + { + sourceId: content.source_repository, + title: "DSM clinical content dataset", + datasetLocation: content.source_repository, + version: content.export_format_version, + publicationDate: strictSourceDate(content.generated_at.slice(0, 10)), + evidenceType: "dataset", + topics: diagnosis.category?.label ? [diagnosis.category.label] : [], + }, + ), + ); + }, +}; + +const calculatorProvider: ClinicalSourceProvider = { + id: "calculators", + sourcePaths: ["src/components/calculators/calculator-fixtures.ts"], + references: () => + calculators.map((calculator) => + reference( + { modeId: "calculators", recordId: calculator.id, recordLabel: calculator.name, field: "source" }, + { + title: `${calculator.abbrev} source`, + validationStatus: "unverified", + referenceText: calculator.source, + topics: [calculator.domain], + }, + ), + ), +}; + +export const repositorySourceProviders: readonly ClinicalSourceProvider[] = [ + dictionaryProvider, + factsheetProvider, + formulationProvider, + therapyProvider, + specifierProvider, + formsProvider, + mhaProvider, + medicationProvider, + servicesProvider, + dsmProvider, + calculatorProvider, +]; + +export function repositorySourceReferences() { + return repositorySourceProviders.flatMap((provider) => provider.references()); +} + +export function repositorySourceReferenceIssues( + providerId: string, + references: readonly ClinicalSourceReferenceInput[], +): string[] { + const issues: string[] = []; + for (const sourceReference of references) { + const usage = sourceReference.usage; + if (!usage.modeId || !usage.recordId || !usage.recordLabel || !usage.field) { + issues.push(`Provider ${providerId} returned a reference without a complete usage`); + } + if (sourceReference.canonicalUrl && !safeHttpsUrl(sourceReference.canonicalUrl)) { + issues.push(`Provider ${providerId} returned unsafe structured URL`); + } + if ( + [sourceReference.publicationDate, sourceReference.reviewDate, sourceReference.expiryDate].some( + hasInvalidStructuredSourceDate, + ) + ) { + issues.push(`Provider ${providerId} returned an invalid structured date`); + } + } + return issues; +} + +function coverageKey(reference: ClinicalSourceReferenceInput) { + return [ + reference.sourceId, + reference.canonicalUrl, + reference.referenceText, + reference.usage.recordId, + reference.usage.field, + ].join("\u0000"); +} + +type RepositorySourceCoverageInputs = { + formulationMechanisms?: readonly Pick[]; + formulationSourceLibrary?: Readonly>; +}; + +export function repositorySourceCoverageIssues(inputs: RepositorySourceCoverageInputs = {}): string[] { + const issues: string[] = []; + const references = repositorySourceReferences(); + const keys = new Set(references.map(coverageKey)); + const providerReferences = new Map(repositorySourceProviders.map((provider) => [provider.id, provider.references()])); + const checkedFormulationMechanisms = inputs.formulationMechanisms ?? formulationMechanisms; + const checkedFormulationSourceLibrary = inputs.formulationSourceLibrary ?? formulationSourceLibrary; + + const dictionaryIds = new Set(dictionarySources.map((source) => source.id)); + const usedDictionaryIds = [ + ...dictionaryEntries.flatMap((entry) => [ + ...entry.sourceRefs.map((source) => source.sourceId), + ...entry.distinctions.flatMap((distinction) => distinction.sourceRefs.map((source) => source.sourceId)), + ]), + ...dictionaryComparisonPairs.flatMap((comparison) => comparison.sourceRefs.map((source) => source.sourceId)), + ]; + for (const sourceId of usedDictionaryIds) { + if (!dictionaryIds.has(sourceId)) issues.push(`Dictionary usage references missing source ${sourceId}`); + } + const capturedDictionaryIds = new Set(providerReferences.get("dictionary")?.map((item) => item.sourceId)); + for (const source of dictionarySources) { + if (!capturedDictionaryIds.has(source.id)) issues.push(`Dictionary source ${source.id} has no catalogue usage`); + } + + for (const mechanism of checkedFormulationMechanisms) { + for (const sourceId of mechanism.sources) { + if (!checkedFormulationSourceLibrary[sourceId]) { + issues.push(`Formulation mechanism ${mechanism.id} references missing source ${sourceId}`); + } + const expected = reference( + { modeId: "formulation", recordId: mechanism.id, recordLabel: mechanism.name, field: "sources" }, + { sourceId, canonicalUrl: checkedFormulationSourceLibrary[sourceId]?.url ?? null }, + ); + if (!keys.has(coverageKey(expected))) + issues.push(`Formulation source ${sourceId} is missing usage ${mechanism.id}`); + } + } + const usedFormulationSources = new Set(checkedFormulationMechanisms.flatMap((mechanism) => mechanism.sources)); + for (const sourceId of Object.keys(checkedFormulationSourceLibrary)) { + if (!usedFormulationSources.has(sourceId)) issues.push(`Formulation source ${sourceId} has no mechanism usage`); + } + + for (const calculator of calculators) { + const expected = reference( + { modeId: "calculators", recordId: calculator.id, recordLabel: calculator.name, field: "source" }, + { referenceText: calculator.source }, + ); + if (!keys.has(coverageKey(expected))) issues.push(`Calculator ${calculator.id} source is not captured`); + } + + for (const { medication, section, row } of medicationSourceRows()) { + const expected = reference( + { + modeId: "prescribing", + recordId: medication.slug, + recordLabel: medication.name, + field: `${section.title}.${row.key}`, + }, + { referenceText: row.val }, + ); + if (!keys.has(coverageKey(expected))) issues.push(`Medication ${medication.slug} source row is not captured`); + } + + for (const service of loadServicesSnapshot().services) { + for (const url of service.public_source_urls) { + const expected = reference( + { modeId: "services", recordId: service.id, recordLabel: service.name, field: "public_source_urls" }, + { canonicalUrl: url }, + ); + if (!keys.has(coverageKey(expected))) issues.push(`Service ${service.id} URL ${url} is not captured`); + } + for (const sourceDocument of service.source_documents) { + const expected = reference( + { modeId: "services", recordId: service.id, recordLabel: service.name, field: "source_documents" }, + { referenceText: sourceDocument }, + ); + if (!keys.has(coverageKey(expected))) { + issues.push(`Service ${service.id} source document ${sourceDocument} is not captured`); + } + } + } + + const formIds = new Set(providerReferences.get("forms")?.map((item) => item.sourceId)); + for (const document of formsSnapshot.sourceDocuments) { + if (!formIds.has(document.id)) issues.push(`Forms source document ${document.id} is not captured`); + } + const formReferences = providerReferences.get("forms") ?? []; + for (const form of formsSnapshot.forms) { + if ( + !formReferences.some( + (item) => + item.sourceId === form.sourceDocumentId && + item.usage.recordId === form.id && + item.usage.recordLabel === form.name && + item.usage.field === "sourceDocumentId", + ) + ) { + issues.push(`Forms record ${form.id} source document usage is not captured`); + } + } + + const dsmReferences = providerReferences.get("dsm") ?? []; + const dsmContent = dsmClinicalContent as DsmClinicalContent; + for (const diagnosis of dsmContent.diagnoses) { + if ( + !dsmReferences.some( + (item) => item.datasetLocation === dsmContent.source_repository && item.usage.recordId === diagnosis.record_id, + ) + ) { + issues.push(`DSM source_repository is missing diagnosis usage ${diagnosis.record_id}`); + } + } + + return [...new Set(issues)].sort(); +} diff --git a/src/lib/sources/source-date-policy.ts b/src/lib/sources/source-date-policy.ts new file mode 100644 index 0000000000..31a6c03845 --- /dev/null +++ b/src/lib/sources/source-date-policy.ts @@ -0,0 +1,10 @@ +export function strictSourceDate(value: string | null) { + if (!value || !/^\d{4}-\d{2}-\d{2}$/.test(value)) return null; + const parsed = new Date(`${value}T00:00:00.000Z`); + if (Number.isNaN(parsed.getTime()) || parsed.toISOString().slice(0, 10) !== value) return null; + return value; +} + +export function hasInvalidStructuredSourceDate(value: string | null) { + return Boolean(value?.trim()) && strictSourceDate(value) === null; +} diff --git a/src/lib/sources/source-url-policy.ts b/src/lib/sources/source-url-policy.ts new file mode 100644 index 0000000000..7d37c3fcee --- /dev/null +++ b/src/lib/sources/source-url-policy.ts @@ -0,0 +1,83 @@ +export const GOVERNED_SOURCE_HOSTS = [ + "aci.health.nsw.gov.au", + "admhss.mhc.wa.gov.au", + "australianprescriber.tg.org.au", + "emhs.health.wa.gov.au", + "headspace.org.au", + "helpingminds.org.au", + "icd.who.int", + "kidshelpline.com.au", + "mensline.org.au", + "pmc.ncbi.nlm.nih.gov", + "pubmed.ncbi.nlm.nih.gov", + "qlife.org.au", + "royalperthhospital.health.wa.gov.au", + "rph.health.wa.gov.au", + "ruah.org.au", + "smhs.health.wa.gov.au", + "www.aihw.gov.au", + "www.beyondblue.org.au", + "www.cci.health.wa.gov.au", + "www.entrypointperth.com.au", + "www.gamblinghelponline.org.au", + "www.health.gov.au", + "www.health.wa.gov.au", + "www.healthdirect.gov.au", + "www.healthywa.wa.gov.au", + "www.ihacpa.gov.au", + "www.kemh.health.wa.gov.au", + "www.legalaid.wa.gov.au", + "www.legislation.wa.gov.au", + "www.livingproud.org.au", + "www.mayoclinic.org", + "www.medicarementalhealth.gov.au", + "www.mhas.wa.gov.au", + "www.mhc.wa.gov.au", + "www.mht.wa.gov.au", + "www.ncbi.nlm.nih.gov", + "www.ndis.gov.au", + "www.nice.org.uk", + "www.nimh.nih.gov", + "www.nmhs.health.wa.gov.au", + "www.openarms.gov.au", + "www.psychiatry.org", + "www.ranzcp.org", + "www.wa.gov.au", + "www.wacountry.health.wa.gov.au", + "www.who.int", + "www.wslhd.health.nsw.gov.au", + "www.wungening.com.au", + "www1.health.gov.au", +] as const; + +const governedSourceHosts = new Set(GOVERNED_SOURCE_HOSTS); + +function hasGovernedQuery(url: URL) { + if (!url.search) return true; + + const entries = [...url.searchParams.entries()]; + if (entries.length !== 1) return false; + + const [[key, value]] = entries; + if (url.hostname === "www.health.gov.au") { + return key === "language" && /^[a-z]{2}(?:-[A-Z]{2})?$/.test(value); + } + if (url.hostname === "www.legislation.wa.gov.au") { + return key === "OpenElement" && value === ""; + } + return false; +} + +export function safeCanonicalSourceUrl(value: string | null) { + if (!value) return null; + try { + const url = new URL(value); + if (url.protocol !== "https:" || url.username || url.password) return null; + if (!governedSourceHosts.has(url.hostname)) return null; + if (!hasGovernedQuery(url)) return null; + url.hash = ""; + return url.toString(); + } catch { + return null; + } +} diff --git a/src/lib/tools-catalog.ts b/src/lib/tools-catalog.ts index 21b9d084e8..d0e81a30a1 100644 --- a/src/lib/tools-catalog.ts +++ b/src/lib/tools-catalog.ts @@ -25,6 +25,7 @@ export type ToolCatalogId = | "differentials" | "documents" | "clinical-dictionary" + | "source-catalogue" | "guidelines" | "risk-safety" | "medication-prescribing" @@ -135,6 +136,22 @@ export const toolCatalogRecords: ToolCatalogRecord[] = [ neededInput: ["Term, abbreviation, or topic"], output: "Source-checked definition, related terminology, distinctions, and source links.", }, + { + id: "source-catalogue", + title: "Sources", + description: "Browse ranked clinical sources and their traceability.", + bestFor: "Source quality and provenance review", + detail: "Review source identity, quality bands, locations, publishers, topics, and application usage.", + href: "/sources", + area: "reference", + status: "ready", + sourceBacked: true, + actionLabel: "Browse", + keywords: ["sources", "catalogue", "publisher", "quality", "provenance", "traceability"], + checkFirst: ["Source identity", "Quality band", "Review and lifecycle status"], + neededInput: ["Optional title, publisher, topic, or usage filter"], + output: "Read-only source catalogue records with quality and traceability details.", + }, { id: "guidelines", title: "Guidelines", diff --git a/src/lib/ui-copy.ts b/src/lib/ui-copy.ts index 5c6168512f..0c80a9cf71 100644 --- a/src/lib/ui-copy.ts +++ b/src/lib/ui-copy.ts @@ -114,6 +114,11 @@ export const sharedHomePresentation = { subtitle: "Source-governed psychiatric terms, abbreviations, and distinctions.", suggestions: ["mental state examination", "auditory hallucination", "ACT"], }, + sources: { + title: "Sources", + subtitle: "Clinical source catalogue.", + suggestions: ["Australian guidelines", "RANZCP", "review required"], + }, } as const satisfies Record; /** Browser/assistive-technology title for the mode selected on the shared home. */ diff --git a/src/lib/universal-search-mode-context.ts b/src/lib/universal-search-mode-context.ts index 8fc2de50b6..a9a8463241 100644 --- a/src/lib/universal-search-mode-context.ts +++ b/src/lib/universal-search-mode-context.ts @@ -23,6 +23,7 @@ const preferredDomainsByMode: Record = { diff --git a/tests/app-modes.test.ts b/tests/app-modes.test.ts index 1f822ea9ca..7fdc6e868c 100644 --- a/tests/app-modes.test.ts +++ b/tests/app-modes.test.ts @@ -33,6 +33,7 @@ describe("app mode search contract", () => { expect(universalSearchPreferredDomains("favourites")).toEqual([]); expect(universalSearchPreferredDomains("factsheets")).toEqual([]); expect(universalSearchPreferredDomains("calculators")).toEqual([]); + expect(universalSearchPreferredDomains("sources")).toEqual([]); }); it("requires every mode to declare its search behavior and copy", () => { @@ -195,6 +196,25 @@ describe("app mode search contract", () => { expect(appModeHomeHref("therapy-compass", { query: "CBT", run: true })).toBe("/therapy-compass/search?q=CBT&run=1"); }); + it("routes Sources searches to the read-only catalogue", () => { + const config = appModeSearchConfig("sources"); + const mode = appModeDefinitions.find((definition) => definition.id === "sources"); + + expect(appModeIds).toHaveLength(16); + expect(mode).toMatchObject({ + label: "Sources", + description: "Ranked clinical source catalogue and traceability", + href: "/sources", + }); + expect(config).toMatchObject({ + kind: "tools", + placeholder: "Search sources, publishers, or topics...", + resultHeading: "Sources", + nextStep: "Filter by quality, location, publisher, topic, or usage", + }); + expect(appModeHomeHref("sources", { query: "RANZCP", run: true })).toBe("/sources?q=RANZCP&run=1"); + }); + it("keeps source-library shortcut searches in their active mode family", () => { expect(appModeCanUseSourceLibraryShortcut("answer")).toBe(false); expect(appModeCanUseSourceLibraryShortcut("tools")).toBe(false); @@ -418,6 +438,7 @@ describe("app mode search contract", () => { formulation: "/formulation/search?q=clozapine&run=1", "therapy-compass": "/therapy-compass/search?q=clozapine&run=1", calculators: "/calculators/search?q=clozapine&run=1", + sources: "/sources?q=clozapine&run=1", // Same route, submitted branch: these still own a home of their own. favourites: "/favourites?q=clozapine&run=1", // Tools has no search route by design: it filters its launcher in place. diff --git a/tests/category-identity.test.ts b/tests/category-identity.test.ts index 6e5ec8d187..185a63ea93 100644 --- a/tests/category-identity.test.ts +++ b/tests/category-identity.test.ts @@ -94,6 +94,14 @@ describe("category identity registry", () => { expect(new Set(keys).size).toBe(keys.length); }); + it("uses the library glyph for Sources on both independent identity axes", () => { + expect(APP_MODE_ICON.sources).toBe("libraryBig"); + expect(TOOL_ICON["source-catalogue"]).toBe("libraryBig"); + expect(categoryIconComponent("libraryBig").displayName ?? categoryIconComponent("libraryBig").name).toMatch( + /LibraryBig/, + ); + }); + it("resolves every declared glyph key to a component", () => { for (const key of CATEGORY_ICON_KEYS) { expect(typeof categoryIconComponent(key), `glyph "${key}" does not resolve`).not.toBe("undefined"); diff --git a/tests/design-system-adoption.test.ts b/tests/design-system-adoption.test.ts index dbbafe244a..0325cb8960 100644 --- a/tests/design-system-adoption.test.ts +++ b/tests/design-system-adoption.test.ts @@ -1417,7 +1417,7 @@ describe("design-system adoption manifest", () => { ["committed", "not-committed", "not-applicable"].includes(surface.baseline.status), ), ).toBe(true); - // 76 = 59 + 6 + 10 + 1: the 59 production pages that preceded both changes, the six + // 81 = 76 prior census + 5 Sources routes. Prior 76 = 59 + 6 + 10 + 1: the 59 production pages that preceded both changes, the six // `/search` routes home consolidation split out of the bare paths, the Caring // Contacts workspace's ten screens (Today; the Patients caseload from Phase 2B Task 5; // the per-patient overview from Task 6; the activation wizard from Task 7; the Schedule @@ -1432,7 +1432,7 @@ describe("design-system adoption manifest", () => { // route the same way it always excluded theirs. Redirect stubs keep legacy deep links // resolving and still count as declared routes. This is a census, so a route nobody // intended to add still fails the contract. - expect(manifest.routeCoverage.discovered).toHaveLength(76); + expect(manifest.routeCoverage.discovered).toHaveLength(81); expect(manifest.routeCoverage.declared).toEqual(manifest.routeCoverage.discovered); expect(manifest.routeCoverage.undeclared).toEqual([]); expect(manifest.routeCoverage.missing).toEqual([]); diff --git a/tests/mode-home-loading-contract.test.ts b/tests/mode-home-loading-contract.test.ts index b769f0d990..ebfe9ce86a 100644 --- a/tests/mode-home-loading-contract.test.ts +++ b/tests/mode-home-loading-contract.test.ts @@ -22,6 +22,7 @@ const MODE_HOME_LOADING_ROUTES = [ "documents", "calculators", "dictionary", + "sources", ] as const; describe("mode-home loading contract", () => { diff --git a/tests/mode-secondary-navigation.test.ts b/tests/mode-secondary-navigation.test.ts index 9ea543bd08..1fdffe5627 100644 --- a/tests/mode-secondary-navigation.test.ts +++ b/tests/mode-secondary-navigation.test.ts @@ -28,6 +28,7 @@ const expectedLabels: Record = { "therapy-compass": ["Search", "Recommend", "Compare", "Pathways", "Review"], factsheets: ["Search", "Topics"], dictionary: ["Terms", "Topics", "Compare", "Sources"], + sources: ["Catalogue", "Topics", "Publishers", "Method"], }; const cleanLandingPath: Record = { @@ -46,6 +47,7 @@ const cleanLandingPath: Record = { "therapy-compass": "/therapy-compass", factsheets: "/factsheets", dictionary: "/dictionary", + sources: "/sources", }; /** @@ -67,9 +69,9 @@ const emptyRegistryModes = [ ] as const satisfies readonly AppModeId[]; describe("mode secondary navigation registry", () => { - it("covers all 15 modes with the approved destinations and no Home item", () => { + it("covers all 16 modes with the approved destinations and no Home item", () => { expect(Object.keys(modeSecondaryNavigationRegistry).sort()).toEqual([...appModeIds].sort()); - expect(appModeIds).toHaveLength(15); + expect(appModeIds).toHaveLength(16); for (const modeId of appModeIds) { const labels = modeSecondaryNavigationRegistry[modeId].map((item) => item.label); @@ -100,7 +102,7 @@ describe("mode secondary navigation registry", () => { for (const modeId of appModeIds) { expect( isModeSecondaryNavigationRoute({ modeId, pathname: cleanLandingPath[modeId], hasSubmittedSearch: false }), - ).toBe(false); + ).toBe(modeId === "sources"); expect( isModeSecondaryNavigationRoute({ modeId, pathname: cleanLandingPath[modeId], hasSubmittedSearch: true }), ).toBe(true); @@ -146,6 +148,16 @@ describe("mode secondary navigation registry", () => { hasSubmittedSearch: false, }), ).toBe(false); + for (const pathname of ["/sources", "/sources/topics", "/sources/publishers", "/sources/method"]) { + expect(isModeSecondaryNavigationRoute({ modeId: "sources", pathname, hasSubmittedSearch: false })).toBe(true); + } + expect( + isModeSecondaryNavigationRoute({ + modeId: "sources", + pathname: "/sources/src_detail", + hasSubmittedSearch: false, + }), + ).toBe(false); expect( isModeSecondaryNavigationRoute({ modeId: "factsheets", @@ -347,6 +359,29 @@ describe("mode secondary navigation registry", () => { ), }), ).toBe("/therapy-compass/compare?q=trauma&run=1&ids=cbt%2Cact&topic=Anxiety&density=dense"); + + for (const [itemId, href] of [ + ["catalogue", "/sources"], + ["topics", "/sources/topics"], + ["publishers", "/sources/publishers"], + ] as const) { + expect( + modeSecondaryNavigationHref({ + modeId: "sources", + itemId, + href, + currentSearchParams: new URLSearchParams("q=RANZCP&usedBy=dictionary&band=A"), + }), + ).toBe(`${href}?q=RANZCP&usedBy=dictionary`); + } + expect( + modeSecondaryNavigationHref({ + modeId: "sources", + itemId: "method", + href: "/sources/method", + currentSearchParams: new URLSearchParams("q=RANZCP&usedBy=dictionary"), + }), + ).toBe("/sources/method"); }); it("adopts only modes with two or more routed destinations (explicit list, not silent derivation)", () => { @@ -361,6 +396,7 @@ describe("mode secondary navigation registry", () => { "dsm", "factsheets", "formulation", + "sources", "specifiers", "therapy-compass", ]); @@ -414,6 +450,11 @@ describe("mode secondary navigation registry", () => { expect(activeModeSecondaryNavigationId("dictionary", "/dictionary/topics/assessment-and-measurement")).toBe( "topics", ); + expect(activeModeSecondaryNavigationId("sources", "/sources")).toBe("catalogue"); + expect(activeModeSecondaryNavigationId("sources", "/sources/topics")).toBe("topics"); + expect(activeModeSecondaryNavigationId("sources", "/sources/publishers")).toBe("publishers"); + expect(activeModeSecondaryNavigationId("sources", "/sources/method")).toBe("method"); + expect(activeModeSecondaryNavigationId("sources", "/sources/src_detail")).toBeNull(); // The `registry[modeId][0]?.id` fallback is gone. A mode with no branch and // no entries has no current destination, rather than silently lighting its @@ -454,6 +495,7 @@ describe("information page classification", () => { "/dsm/diagnoses/major-depressive-disorder", "/dsm/diagnoses/major-depressive-disorder/differentials", "/documents/11111111-1111-4111-8111-111111111111", + "/sources/src_example", ])("classifies %s as an information page", (pathname) => { expect(isInformationPage(pathname)).toBe(true); }); @@ -472,6 +514,10 @@ describe("information page classification", () => { "/differentials/compare", "/dsm/compare", "/documents/search", + "/sources", + "/sources/topics", + "/sources/publishers", + "/sources/method", ])("does not classify workflow route %s as an information page", (pathname) => { expect(isInformationPage(pathname)).toBe(false); }); diff --git a/tests/route-reachability.test.ts b/tests/route-reachability.test.ts index e5ae30cacc..69eac3621f 100644 --- a/tests/route-reachability.test.ts +++ b/tests/route-reachability.test.ts @@ -754,6 +754,24 @@ describe("route reachability", () => { } }); + it("links the dynamic Sources detail family from the catalogue", () => { + const sourceDetailRoute = collectSiteMapData().pageRoutes.find((route) => route.route === "/sources/[sourceId]"); + expect(sourceDetailRoute, "the Sources detail page route is missing").toBeDefined(); + + const catalogueClient = sourceFiles.find( + (file) => file.rel === "src/components/sources/sources-catalogue-client.tsx", + ); + expect(catalogueClient, "the Sources catalogue client is missing").toBeDefined(); + const catalogueSource = readFileSync( + path.join(srcRoot, "components", "sources", "sources-catalogue-client.tsx"), + "utf8", + ); + expect( + / { const routes = new Set(staticPageRoutes.map((entry) => entry.route)); for (const route of REACHABILITY_ALLOWLIST.keys()) { diff --git a/tests/search-route-ownership.test.ts b/tests/search-route-ownership.test.ts index 71e7f96484..77b397cb66 100644 --- a/tests/search-route-ownership.test.ts +++ b/tests/search-route-ownership.test.ts @@ -43,6 +43,20 @@ describe("shared-search route ownership", () => { expect(shouldRenderClinicalDashboard({ hasSubmittedSearch: false, mode: "answer", pathname: "/" })).toBe(true); }); + it("keeps the Sources catalogue route-owned before and after submission", () => { + expect(isStandaloneModeHomePath("/sources")).toBe(true); + expect(isAlwaysStandaloneShellPath("/sources")).toBe(true); + expect(shouldRenderClinicalDashboard({ hasSubmittedSearch: false, mode: "sources", pathname: "/sources" })).toBe( + false, + ); + expect(shouldRenderDashboardSearch({ hasSubmittedSearch: true, mode: "sources", pathname: "/sources" })).toBe( + false, + ); + expect(shouldRenderClinicalDashboard({ hasSubmittedSearch: true, mode: "sources", pathname: "/sources" })).toBe( + false, + ); + }); + it("never replaces an explicit medication detail or document-search mockup", () => { expect( shouldRenderClinicalDashboard({ @@ -61,7 +75,7 @@ describe("shared-search route ownership", () => { }); it("classifies standalone mode homes from pathname alone", () => { - for (const pathname of ["/favourites", "/tools", "/medications", "/documents"]) { + for (const pathname of ["/favourites", "/tools", "/medications", "/documents", "/sources"]) { expect(isStandaloneModeHomePath(pathname)).toBe(true); } expect(isStandaloneModeHomePath("/")).toBe(false); @@ -122,6 +136,7 @@ describe("shared-search route ownership", () => { expect(isAlwaysStandaloneShellPath("/differentials/presentations/acute-confusion-encephalopathy")).toBe(true); expect(isAlwaysStandaloneShellPath("/medications/acamprosate")).toBe(true); expect(isAlwaysStandaloneShellPath("/tools")).toBe(true); + expect(isAlwaysStandaloneShellPath("/sources")).toBe(true); // `/` and Documents still need searchParams for the dashboard gate. expect(isAlwaysStandaloneShellPath("/")).toBe(false); expect(isAlwaysStandaloneShellPath("/documents/search")).toBe(false); diff --git a/tests/search-shell-props.test.ts b/tests/search-shell-props.test.ts index a4249f0fc9..aa1434b13e 100644 --- a/tests/search-shell-props.test.ts +++ b/tests/search-shell-props.test.ts @@ -76,4 +76,13 @@ describe("searchShellPropsForPathname", () => { desktopSearchPlacement: "hero", }); }); + + it("keeps one Sources composer on catalogue views and hides it on method and detail pages", () => { + const visible = { initialMode: "sources", desktopSearchPlacement: "hero" } as const; + expect(searchShellPropsForPathname("/sources")).toEqual(visible); + expect(searchShellPropsForPathname("/sources/topics")).toEqual(visible); + expect(searchShellPropsForPathname("/sources/publishers")).toEqual(visible); + expect(searchShellPropsForPathname("/sources/method")).toEqual({ ...visible, searchComposerVisible: false }); + expect(searchShellPropsForPathname("/sources/src_example")).toEqual({ ...visible, searchComposerVisible: false }); + }); }); diff --git a/tests/shared-home-empty-state.dom.test.tsx b/tests/shared-home-empty-state.dom.test.tsx index 401e8acc4b..c5c361c8a1 100644 --- a/tests/shared-home-empty-state.dom.test.tsx +++ b/tests/shared-home-empty-state.dom.test.tsx @@ -102,6 +102,12 @@ const expectedPresentations = [ subtitle: "Source-governed psychiatric terms, abbreviations, and distinctions.", iconClass: "lucide-book-marked", }, + { + modeId: "sources", + title: "Sources", + subtitle: "Clinical source catalogue.", + iconClass: "lucide-library-big", + }, ] as const satisfies ReadonlyArray<{ modeId: AppModeId; title: string; diff --git a/tests/sidebar-pins.test.ts b/tests/sidebar-pins.test.ts index d52f34a1fe..d7f9aaaf38 100644 --- a/tests/sidebar-pins.test.ts +++ b/tests/sidebar-pins.test.ts @@ -1,14 +1,25 @@ import { describe, expect, it } from "vitest"; -import { defaultSidebarPinnedModeIds, readSidebarPinnedModes } from "@/components/clinical-dashboard/use-sidebar-pins"; +import { + defaultSidebarPinnedModeIds, + pinnableSidebarModeIds, + readSidebarPinnedModes, +} from "@/components/clinical-dashboard/use-sidebar-pins"; describe("sidebar pin persistence", () => { it("uses the six product defaults for missing or malformed preferences", () => { + expect(defaultSidebarPinnedModeIds).toHaveLength(6); + expect(defaultSidebarPinnedModeIds).not.toContain("sources"); + expect(pinnableSidebarModeIds).toContain("sources"); expect(readSidebarPinnedModes(null)).toEqual(defaultSidebarPinnedModeIds); expect(readSidebarPinnedModes("not-json")).toEqual(defaultSidebarPinnedModeIds); expect(readSidebarPinnedModes(JSON.stringify({ answer: true }))).toEqual(defaultSidebarPinnedModeIds); }); + it("accepts Sources as a user pin", () => { + expect(readSidebarPinnedModes(JSON.stringify(["sources", "answer"]))).toEqual(["sources", "answer"]); + }); + it("keeps an intentional empty list and removes unknown or duplicate mode ids", () => { expect(readSidebarPinnedModes("[]")).toEqual([]); expect(readSidebarPinnedModes(JSON.stringify(["forms", "unknown", "forms", "answer"]))).toEqual([ diff --git a/tests/sidebar-production.dom.test.tsx b/tests/sidebar-production.dom.test.tsx index 40d03ff91d..6374b414b6 100644 --- a/tests/sidebar-production.dom.test.tsx +++ b/tests/sidebar-production.dom.test.tsx @@ -101,6 +101,7 @@ describe("production Clinical Guide sidebar", () => { const editor = screen.getByRole("dialog", { name: "More modes" }); expect(within(editor).queryByText(/\d+ pinned/i)).not.toBeInTheDocument(); + expect(within(editor).getByRole("button", { name: "Pin Sources" })).toBeVisible(); await user.click(within(editor).getByRole("button", { name: "Unpin Documents" })); await user.click(within(editor).getByRole("button", { name: "Pin Forms" })); await user.click(within(editor).getByRole("button", { name: "Move Forms up" })); diff --git a/tests/site-map.test.ts b/tests/site-map.test.ts index 3412e53268..a93bf8f896 100644 --- a/tests/site-map.test.ts +++ b/tests/site-map.test.ts @@ -147,6 +147,20 @@ describe("tracked sitemap", () => { } }); + it("describes Dictionary Sources as the query-preserving Sources compatibility redirect", async () => { + const data = collectSiteMapData(); + const rendered = await renderSiteMap(data); + + expect(data.redirects).toContainEqual({ + route: "/dictionary/sources", + file: "src/app/(search-app)/dictionary/sources/page.tsx", + target: "/sources?usedBy=dictionary", + }); + expect(rendered).toContain( + "`/dictionary/sources` - Query-preserving compatibility redirect to `/sources?usedBy=dictionary`", + ); + }); + it("documents seeded dynamic slugs", () => { for (const service of serviceRecords) expectDocumentedRoute(service.slug); for (const form of formRecords) expectDocumentedRoute(form.slug); diff --git a/tests/source-catalogue-core.test.ts b/tests/source-catalogue-core.test.ts new file mode 100644 index 0000000000..7fe952f62e --- /dev/null +++ b/tests/source-catalogue-core.test.ts @@ -0,0 +1,577 @@ +import { describe, expect, it } from "vitest"; + +import { canonicalizeSourceReferences, compareClinicalSources, rateClinicalSource } from "@/lib/sources/catalogue-core"; +import type { + ClinicalSourceCatalogueEntry, + ClinicalSourceReferenceInput, + SourceCatalogueFilters, +} from "@/lib/sources/catalogue-types"; +import { + deriveSourceCatalogueFacets, + filterAndSortSourceCatalogue, + parseSourceCatalogueFilters, +} from "@/lib/sources/catalogue-view"; + +function reference(overrides: Partial = {}): ClinicalSourceReferenceInput { + return { + sourceId: "akg-guideline", + documentId: null, + title: "Example clinical guideline", + aliases: [], + publisher: "Armadale Kalamunda Group", + publisherCode: "AKG", + canonicalUrl: "https://www.ranzcp.org/example", + datasetLocation: null, + version: "1", + publicationDate: "2025-01-01", + reviewDate: "2026-01-01", + expiryDate: null, + jurisdiction: "Australia/WA", + evidenceType: "guideline", + documentStatus: "current", + validationStatus: "approved", + contentMode: "link_only", + lifecycleStatus: "active", + supersedes: [], + supersededBy: [], + topics: ["governance"], + usage: { + modeId: "dictionary", + recordId: "mse", + recordLabel: "Mental state examination", + field: "definition", + }, + referenceText: null, + ...overrides, + }; +} + +function catalogueEntry( + sourceId: string, + title: string, + overrides: Partial = {}, +): ClinicalSourceCatalogueEntry { + const [entry] = canonicalizeSourceReferences([reference({ sourceId, title })]); + return { ...entry, ...overrides }; +} + +function noFilters(overrides: Partial = {}): SourceCatalogueFilters { + return { + q: "", + bands: [], + jurisdictions: [], + sourceTypes: [], + publishers: [], + topics: [], + lifecycleStatuses: [], + documentStatuses: [], + validationStatuses: [], + usedBy: [], + sort: "quality", + ...overrides, + }; +} + +describe("clinical source catalogue", () => { + it("uses the published six weights and band thresholds", () => { + const rating = rateClinicalSource(reference()); + expect(rating.weights).toEqual({ + accuracyAssurance: 25, + reliability: 20, + evidenceQuality: 20, + currency: 15, + australianApplicability: 15, + traceability: 5, + }); + expect(rating.score).toBe(100); + expect(rating.band).toBe("A"); + }); + + it("applies the exact 85, 70, 50 and below-50 band boundaries", () => { + const exact85 = rateClinicalSource( + reference({ + sourceId: "exact-85", + publisher: "World Health Organization", + publisherCode: "WHO", + jurisdiction: "International", + evidenceType: "systematic_review", + }), + ); + const exact70 = rateClinicalSource( + reference({ + sourceId: "exact-70", + publisher: "NSW Health", + publisherCode: "NSWHEALTH", + jurisdiction: "Australia/NSW", + evidenceType: "primary_study", + documentStatus: "unknown", + validationStatus: "locally_reviewed", + }), + ); + const exact50 = rateClinicalSource( + reference({ + sourceId: "exact-50", + publisher: "BMJ Best Practice", + publisherCode: "BMJ", + canonicalUrl: null, + jurisdiction: "International", + evidenceType: "other", + documentStatus: "outdated", + validationStatus: "locally_reviewed", + }), + ); + const below50 = rateClinicalSource( + reference({ + sourceId: "below-50", + publisher: "Unclassified publisher", + publisherCode: null, + canonicalUrl: null, + jurisdiction: null, + evidenceType: "professional_reference", + documentStatus: "unknown", + validationStatus: "locally_reviewed", + }), + ); + + expect([exact85.score, exact85.band]).toEqual([85, "A"]); + expect([exact70.score, exact70.band]).toEqual([70, "B"]); + expect([exact50.score, exact50.band]).toEqual([50, "C"]); + expect([below50.score, below50.band]).toEqual([48, "D"]); + }); + + it("forces incomplete future references into D without discarding them", () => { + const [entry] = canonicalizeSourceReferences([ + reference({ + sourceId: null, + title: null, + publisher: null, + publisherCode: null, + canonicalUrl: null, + version: null, + publicationDate: null, + reviewDate: null, + jurisdiction: null, + evidenceType: "unknown", + validationStatus: "unknown", + referenceText: "Legacy prose citation", + }), + ]); + expect(entry.title).toBe("Legacy prose citation"); + expect(entry.id).toMatch(/^src_[a-f0-9]{20}$/); + expect(entry.rating.band).toBe("D"); + expect(entry.warnings).toEqual(expect.arrayContaining(["ambiguous_identity", "verification_unknown"])); + expect(entry).not.toHaveProperty("referenceText"); + }); + + it("forces an otherwise preferred official WA guideline with missing version and dates into D", () => { + const [entry] = canonicalizeSourceReferences([ + reference({ + version: null, + publicationDate: null, + reviewDate: null, + expiryDate: null, + }), + ]); + + expect(entry.rating.score).toBeGreaterThanOrEqual(85); + expect(entry.rating.band).toBe("D"); + expect(entry.warnings).toEqual(["missing_dates", "missing_version"]); + expect(entry.rating.reasons).toContain("Incomplete source metadata requires review"); + }); + + it("keeps registry geography while forcing a recognized authority with missing jurisdiction into D", () => { + const [entry] = canonicalizeSourceReferences([ + reference({ + publisher: "World Health Organization", + publisherCode: "WHO", + jurisdiction: null, + }), + ]); + + expect(entry.geography).toEqual({ scope: "international", label: "International" }); + expect(entry.rating.score).toBe(87); + expect(entry.rating.band).toBe("D"); + expect(entry.warnings).toContain("unknown_jurisdiction"); + expect(entry.rating.reasons).toContain("Incomplete source metadata requires review"); + }); + + it("does not award current currency credit after a source expiry date", () => { + const [expired, future] = canonicalizeSourceReferences([ + reference({ sourceId: "expired", expiryDate: "2000-01-01" }), + reference({ sourceId: "future", expiryDate: "2999-01-01" }), + ]).sort((left, right) => left.sourceId!.localeCompare(right.sourceId!)); + + expect(expired.sourceId).toBe("expired"); + expect(expired.documentStatus).toBe("outdated"); + expect(expired.rating.dimensions.currency).toBe(0); + expect(expired.warnings).toContain("outdated"); + expect(expired.rating.reasons).toContain("Currency: 0/15"); + expect(future.sourceId).toBe("future"); + expect(future.documentStatus).toBe("current"); + expect(future.rating.dimensions.currency).toBe(15); + }); + + it("hard-excludes a source with an identified replacement even when marked active", () => { + const [entry] = canonicalizeSourceReferences([ + reference({ lifecycleStatus: "active", supersededBy: ["akg-guideline-v2"] }), + ]); + + expect(entry.lifecycleStatus).toBe("excluded"); + expect(entry.rating.band).toBe("excluded"); + expect(entry.warnings).toContain("superseded"); + expect(entry.rating.reasons).toContain("Excluded because a current replacement is identified"); + }); + + it("runs lifecycle exclusion before the numeric score", () => { + expect(rateClinicalSource(reference({ lifecycleStatus: "excluded" })).band).toBe("excluded"); + }); + + it("keeps a substantially stronger international source above a weak Australian source", () => { + const entries = canonicalizeSourceReferences([ + reference({ + sourceId: "strong-int", + publisher: "World Health Organization", + publisherCode: "WHO", + jurisdiction: "International", + }), + reference({ + sourceId: "weak-au", + publisher: null, + publisherCode: null, + validationStatus: "unverified", + evidenceType: "other", + }), + ]); + expect(entries.map((entry) => entry.sourceId)).toEqual(["strong-int", "weak-au"]); + }); + + it("never infers authority or geography from source prose", () => { + const rating = rateClinicalSource( + reference({ + publisher: null, + publisherCode: null, + jurisdiction: null, + title: "World Health Organization Australian guideline", + referenceText: "Official WA guidance", + }), + ); + expect(rating.dimensions.reliability).toBe(0); + expect(rating.dimensions.australianApplicability).toBe(0); + }); + + it("merges compatible aliases while retaining every usage", () => { + const entries = canonicalizeSourceReferences([ + reference({ aliases: ["AKG guidance"], topics: ["governance", "assessment"] }), + reference({ + aliases: ["AKG guidance", "Local guidance"], + topics: ["assessment"], + usage: { + modeId: "factsheets", + recordId: "depression", + recordLabel: "Depression", + field: "sources", + }, + }), + ]); + expect(entries).toHaveLength(1); + expect(entries[0].aliases).toEqual(["AKG guidance", "Local guidance"]); + expect(entries[0].topics).toEqual(["assessment", "governance"]); + expect(entries[0].usedBy).toHaveLength(2); + }); + + it("does not merge conflicting versions or publishers", () => { + const entries = canonicalizeSourceReferences([ + reference(), + reference({ version: "2", publisher: "Different publisher", publisherCode: null }), + ]); + expect(entries).toHaveLength(2); + expect(entries.every((entry) => entry.warnings.includes("metadata_conflict"))).toBe(true); + expect(entries.every((entry) => entry.rating.band === "D")).toBe(true); + }); + + it("keeps registry and supplied jurisdiction conflicts internally consistent", () => { + const [entry] = canonicalizeSourceReferences([ + reference({ + sourceId: "conflicting-who", + publisher: "World Health Organization", + publisherCode: "WHO", + jurisdiction: "Australia/WA", + }), + ]); + expect(entry.geography).toEqual({ scope: "unknown", label: "Unknown" }); + expect(entry.warnings).toEqual(expect.arrayContaining(["metadata_conflict", "unknown_jurisdiction"])); + expect(entry.rating.band).toBe("D"); + }); + + it("removes unsafe outbound locations", () => { + const [entry] = canonicalizeSourceReferences([reference({ canonicalUrl: "javascript:alert(1)" })]); + expect(entry.canonicalLocation).toEqual({ kind: "none" }); + expect(entry.warnings).toContain("unsafe_location"); + expect(entry.rating.band).toBe("D"); + }); + + it("removes HTTPS outbound locations on hosts outside the governed allowlist", () => { + const [entry] = canonicalizeSourceReferences([ + reference({ canonicalUrl: "https://unreviewed-source.example/clinical-guidance" }), + ]); + + expect(entry.canonicalLocation).toEqual({ kind: "none" }); + expect(entry.warnings).toContain("unsafe_location"); + expect(entry.rating.band).toBe("D"); + }); + + it.each([ + "token", + "API_KEY", + "api-key", + "access_token", + "secret", + "password", + "signature", + "sig", + "credential", + "authorization", + "auth", + "X-Amz-Signature", + "client_secret", + "refresh_token", + "session_token", + "jwt", + "access_key", + "auth_token", + "X-Amz-Credential", + "X-Amz-Security-Token", + ])("redacts canonical locations carrying the %s query credential", (parameter) => { + const secret = "catalogue-query-secret"; + const [entry] = canonicalizeSourceReferences([ + reference({ canonicalUrl: `https://www.ranzcp.org/guidance?${parameter}=${secret}` }), + ]); + + expect(entry.canonicalLocation).toEqual({ kind: "none" }); + expect(entry.warnings).toContain("unsafe_location"); + expect(entry.rating.band).toBe("D"); + expect(JSON.stringify(entry)).not.toContain(secret); + }); + + it("rejects credential-bearing HTTPS locations without exposing credentials", () => { + const [entry] = canonicalizeSourceReferences([ + reference({ canonicalUrl: "https://catalogue-user:catalogue-secret@example.org/private" }), + ]); + expect(entry.canonicalLocation).toEqual({ kind: "none" }); + expect(entry.warnings).toContain("unsafe_location"); + expect(entry.rating.band).toBe("D"); + expect(JSON.stringify(entry)).not.toContain("catalogue-user"); + expect(JSON.stringify(entry)).not.toContain("catalogue-secret"); + }); + + it.each(["2025-02-29", "2025-13-01", "01-02-2025", "2025-2-01"])( + "treats malformed structured date %s as review debt without projecting it", + (malformedDate) => { + const [entry] = canonicalizeSourceReferences([ + reference({ publicationDate: malformedDate, reviewDate: null, expiryDate: malformedDate }), + ]); + + expect(entry.publicationDate).toBeNull(); + expect(entry.expiryDate).toBeNull(); + expect(entry.documentStatus).toBe("unknown"); + expect(entry.rating.dimensions.currency).toBe(4); + expect(entry.warnings).toContain("invalid_date"); + expect(entry.rating.band).toBe("D"); + }, + ); + + it("ignores blank-only replacement identifiers for lifecycle exclusion", () => { + const [entry] = canonicalizeSourceReferences([reference({ supersededBy: ["", " "] })]); + + expect(entry.lifecycleStatus).toBe("active"); + expect(entry.rating.band).toBe("A"); + expect(entry.warnings).not.toContain("superseded"); + }); + + it("keeps fully unresolved references separate with deterministic opaque IDs", () => { + const unresolved = (modeId: "dictionary" | "factsheets", recordId: string): ClinicalSourceReferenceInput => + reference({ + sourceId: null, + documentId: null, + title: null, + publisher: null, + publisherCode: null, + canonicalUrl: null, + datasetLocation: null, + version: null, + publicationDate: null, + reviewDate: null, + expiryDate: null, + jurisdiction: null, + evidenceType: "unknown", + documentStatus: "unknown", + validationStatus: "unknown", + contentMode: "metadata_only", + referenceText: null, + usage: { modeId, recordId, recordLabel: `Unresolved ${recordId}`, field: "sources" }, + }); + const inputs = [unresolved("dictionary", "first"), unresolved("factsheets", "second")]; + const entries = canonicalizeSourceReferences(inputs); + const reversed = canonicalizeSourceReferences([...inputs].reverse()); + + expect(entries).toHaveLength(2); + expect(new Set(entries.map((entry) => entry.id))).toHaveLength(2); + expect(entries.map((entry) => entry.id)).toEqual(reversed.map((entry) => entry.id)); + expect(entries.every((entry) => entry.warnings.includes("ambiguous_identity"))).toBe(true); + }); + + it("keeps an unresolved bookmark stable when an unrelated unresolved reference is inserted or removed", () => { + const unresolved = (modeId: "dictionary" | "factsheets", recordId: string): ClinicalSourceReferenceInput => + reference({ + sourceId: null, + documentId: null, + title: null, + publisher: null, + publisherCode: null, + canonicalUrl: null, + datasetLocation: null, + version: null, + publicationDate: null, + reviewDate: null, + expiryDate: null, + jurisdiction: null, + evidenceType: "unknown", + documentStatus: "unknown", + validationStatus: "unknown", + contentMode: "metadata_only", + referenceText: null, + usage: { modeId, recordId, recordLabel: `Unresolved ${recordId}`, field: "sources" }, + }); + const target = unresolved("factsheets", "stable-bookmark"); + const earlier = unresolved("dictionary", "earlier-unrelated"); + const targetId = (inputs: ClinicalSourceReferenceInput[]) => + canonicalizeSourceReferences(inputs).find((entry) => + entry.usedBy.some((usage) => usage.recordId === "stable-bookmark"), + )?.id; + + const id = targetId([target]); + expect(targetId([earlier, target])).toBe(id); + expect(targetId([target])).toBe(id); + expect(id).toMatch(/^src_[a-f0-9]{20}$/); + expect(id).not.toContain("stable-bookmark"); + }); + + it("normalizes safe HTTPS locations without retaining fragments", () => { + const [entry] = canonicalizeSourceReferences([ + reference({ canonicalUrl: "https://www.health.gov.au/path?language=en#private-fragment" }), + ]); + expect(entry.canonicalLocation).toEqual({ + kind: "url", + href: "https://www.health.gov.au/path?language=en", + }); + }); + + it("orders by band, score, Australian applicability, currency, then title", () => { + const base = catalogueEntry("base", "Base"); + const entry = ( + sourceId: string, + title: string, + band: ClinicalSourceCatalogueEntry["rating"]["band"], + score: number, + australianApplicability: number, + currency: number, + ): ClinicalSourceCatalogueEntry => ({ + ...base, + id: sourceId, + sourceId, + title, + rating: { + ...base.rating, + band, + score, + dimensions: { ...base.rating.dimensions, australianApplicability, currency }, + }, + }); + const entries = [ + entry("excluded", "Excluded", "excluded", 100, 15, 15), + entry("d", "D", "D", 99, 15, 15), + entry("c", "C", "C", 60, 15, 15), + entry("b-title-z", "Zulu", "B", 80, 13, 8), + entry("b-title-a", "Alpha", "B", 80, 13, 8), + entry("b-currency", "Currency", "B", 80, 13, 15), + entry("b-australian", "Australian", "B", 80, 15, 0), + entry("b-score", "Score", "B", 81, 0, 0), + entry("a", "A", "A", 85, 0, 0), + ]; + expect(entries.sort(compareClinicalSources).map((item) => item.sourceId)).toEqual([ + "a", + "b-score", + "b-australian", + "b-currency", + "b-title-a", + "b-title-z", + "c", + "d", + "excluded", + ]); + }); + + it("parses repeated filters only when their values exist in the catalogue", () => { + const entries = [ + catalogueEntry("one", "One", { topics: ["governance"], publisher: "Publisher One" }), + catalogueEntry("two", "Two", { topics: ["assessment"], publisher: "Publisher Two" }), + ]; + const params = new URLSearchParams([ + ["q", " guide "], + ["band", "A"], + ["band", "invalid"], + ["publisher", "Publisher One"], + ["publisher", "Missing"], + ["topic", "governance"], + ["usedBy", "dictionary"], + ["usedBy", "missing"], + ["sort", "title"], + ]); + expect(parseSourceCatalogueFilters(params, entries)).toEqual({ + q: "guide", + bands: ["A"], + jurisdictions: [], + sourceTypes: [], + publishers: ["Publisher One"], + topics: ["governance"], + lifecycleStatuses: [], + documentStatuses: [], + validationStatuses: [], + usedBy: ["dictionary"], + sort: "title", + }); + }); + + it("filters search to public catalogue fields and derives stable facets", () => { + const entries = [ + catalogueEntry("governance", "Governance guide", { + aliases: ["Local policy"], + publisher: "Publisher One", + topics: ["governance"], + }), + catalogueEntry("assessment", "Assessment guide", { + lifecycleStatus: "inactive", + publisher: "Publisher Two", + topics: ["assessment"], + }), + ]; + expect( + filterAndSortSourceCatalogue(entries, noFilters({ q: "Local policy" })).map((entry) => entry.sourceId), + ).toEqual(["governance"]); + expect(filterAndSortSourceCatalogue(entries, noFilters({ q: "Mental state examination" }))).toEqual([]); + expect(deriveSourceCatalogueFacets(entries)).toEqual({ + total: 2, + australian: 2, + reviewRequired: 0, + inactiveOrExcluded: 1, + topics: [ + { value: "assessment", count: 1 }, + { value: "governance", count: 1 }, + ], + publishers: [ + { value: "Publisher One", count: 1 }, + { value: "Publisher Two", count: 1 }, + ], + }); + }); +}); diff --git a/tests/source-catalogue-providers.test.ts b/tests/source-catalogue-providers.test.ts new file mode 100644 index 0000000000..164b9db224 --- /dev/null +++ b/tests/source-catalogue-providers.test.ts @@ -0,0 +1,313 @@ +import { describe, expect, it, vi } from "vitest"; + +vi.mock("server-only", () => ({})); + +import formsSnapshot from "../data/forms-page-snapshot.json"; +import dsmClinicalContent from "../src/data/dsm-clinical-content.json"; +import therapies from "../src/data/therapies-source.json"; +import { calculators } from "@/components/calculators/calculator-fixtures"; +import { factsheets } from "@/components/factsheets/factsheets-data"; +import { dictionarySources } from "@/lib/dictionary-data"; +import { formulationMechanisms, formulationSourceLibrary } from "@/lib/formulation"; +import { loadMedicationSnapshot } from "@/lib/medication-snapshot"; +import { loadServicesSnapshot } from "@/lib/service-catalog"; +import { authoritativeSources, loadSpecifiersContent } from "@/lib/specifiers-content"; +import { canonicalizeSourceReferences } from "@/lib/sources/catalogue-core"; +import { GOVERNED_SOURCE_HOSTS } from "@/lib/sources/source-url-policy"; +import { + repositorySourceCoverageIssues, + repositorySourceProviders, + repositorySourceReferenceIssues, + repositorySourceReferences, + specifierAuthoritativeSourceReferences, +} from "@/lib/sources/repository-providers"; + +const expectedProviders = { + dictionary: ["src/lib/dictionary-data.ts"], + factsheets: ["src/components/factsheets/factsheets-data.ts"], + formulation: ["src/data/formulation-content.json"], + therapies: ["src/data/therapies-source.json"], + specifiers: ["data/specifiers-content.json"], + forms: ["data/forms-page-snapshot.json"], + mha: ["data/mha-2014-sections.source.json"], + medications: ["data/medications-snapshot.json"], + services: ["data/services-snapshot.json"], + dsm: ["src/data/dsm-clinical-content.json"], + calculators: ["src/components/calculators/calculator-fixtures.ts"], +} as const; + +function provider(id: keyof typeof expectedProviders) { + const match = repositorySourceProviders.find((candidate) => candidate.id === id); + expect(match, `missing ${id} provider`).toBeDefined(); + return match!; +} + +function specifierSourceFamilies() { + const content = loadSpecifiersContent(); + const families = new Set(); + for (const specifier of content.universalSpecifiers) { + if (specifier.review.sourceFamily) families.add(specifier.review.sourceFamily); + } + for (const category of content.categories) { + for (const disorder of category.disorders) { + for (const group of disorder.groups) { + for (const item of group.items) { + if (item.review.sourceFamily) families.add(item.review.sourceFamily); + } + } + } + } + return families; +} + +describe("repository source providers", () => { + it("registers the complete production-owner inventory exactly once", () => { + expect(Object.fromEntries(repositorySourceProviders.map((entry) => [entry.id, entry.sourcePaths]))).toEqual( + expectedProviders, + ); + expect(new Set(repositorySourceProviders.map((entry) => entry.id)).size).toBe(repositorySourceProviders.length); + expect(new Set(repositorySourceProviders.flatMap((entry) => entry.sourcePaths)).size).toBe( + repositorySourceProviders.flatMap((entry) => entry.sourcePaths).length, + ); + }); + + it("pins the 49 currently governed structured source hosts without deriving trust at runtime", () => { + const emittedHosts = new Set( + repositorySourceReferences() + .map((reference) => reference.canonicalUrl) + .filter((value): value is string => Boolean(value)) + .map((value) => new URL(value).hostname), + ); + + expect(GOVERNED_SOURCE_HOSTS).toHaveLength(49); + expect(new Set(GOVERNED_SOURCE_HOSTS)).toEqual(emittedHosts); + }); + + it("returns valid references with traceable application usages from every provider", () => { + for (const entry of repositorySourceProviders) { + const references = entry.references(); + expect(references.length, `${entry.id} returned no references`).toBeGreaterThan(0); + expect( + references.every( + (reference) => + Boolean(reference.usage.modeId) && + Boolean(reference.usage.recordId) && + Boolean(reference.usage.recordLabel) && + Boolean(reference.usage.field), + ), + `${entry.id} returned an untraceable usage`, + ).toBe(true); + } + expect(repositorySourceReferences().every((reference) => reference.usage.recordId && reference.usage.field)).toBe( + true, + ); + }); + + it("captures every current structured owner record automatically", () => { + const dictionaryReferences = provider("dictionary").references(); + expect(new Set(dictionaryReferences.map((reference) => reference.sourceId))).toEqual( + new Set(dictionarySources.map((source) => source.id)), + ); + + const factsheetReferences = provider("factsheets").references(); + expect(factsheetReferences).toHaveLength(factsheets.reduce((total, sheet) => total + sheet.sources.length, 0)); + for (const sheet of factsheets) { + expect(factsheetReferences.filter((reference) => reference.usage.recordId === sheet.slug)).toHaveLength( + sheet.sources.length, + ); + } + + const formulationReferences = provider("formulation").references(); + expect(new Set(formulationReferences.map((reference) => reference.sourceId))).toEqual( + new Set(Object.keys(formulationSourceLibrary)), + ); + for (const mechanism of formulationMechanisms) { + expect( + new Set( + formulationReferences + .filter((reference) => reference.usage.recordId === mechanism.id) + .map((reference) => reference.sourceId), + ), + ).toEqual(new Set(mechanism.sources)); + } + + const specifierReferences = provider("specifiers").references(); + expect(specifierReferences.filter((reference) => reference.canonicalUrl)).toHaveLength( + authoritativeSources().length, + ); + expect( + new Set( + specifierReferences.filter((reference) => reference.referenceText).map((reference) => reference.referenceText), + ), + ).toEqual(specifierSourceFamilies()); + + const formsReferences = provider("forms").references(); + expect(new Set(formsReferences.map((reference) => reference.sourceId))).toEqual( + new Set(formsSnapshot.sourceDocuments.map((document) => document.id)), + ); + for (const form of formsSnapshot.forms) { + expect(formsReferences).toContainEqual( + expect.objectContaining({ + sourceId: form.sourceDocumentId, + usage: { + modeId: "forms", + recordId: form.id, + recordLabel: form.name, + field: "sourceDocumentId", + }, + }), + ); + } + + const medicationReferences = provider("medications").references(); + const medicationSourceRows = loadMedicationSnapshot().flatMap((medication) => + medication.sections.flatMap((section) => + section.rows.filter((row) => section.title === "Sources" || row.key === "Source Review"), + ), + ); + expect(medicationReferences).toHaveLength(medicationSourceRows.length); + + const serviceReferences = provider("services").references(); + const services = loadServicesSnapshot().services; + expect(serviceReferences.filter((reference) => reference.canonicalUrl)).toHaveLength( + services.reduce((total, service) => total + service.public_source_urls.length, 0), + ); + expect(serviceReferences.filter((reference) => reference.referenceText)).toHaveLength( + services.reduce((total, service) => total + service.source_documents.length, 0), + ); + + const dsmReferences = provider("dsm").references(); + expect(dsmReferences).toHaveLength(dsmClinicalContent.diagnoses.length); + expect(new Set(dsmReferences.map((reference) => reference.datasetLocation))).toEqual( + new Set([dsmClinicalContent.source_repository]), + ); + + expect(provider("calculators").references()).toHaveLength(calculators.length); + }); + + it("keeps specifier authoritative-source usage IDs stable across insertion and reordering", () => { + const existingSources = [ + { label: "Source A", url: "https://example.test/source-a" }, + { label: "Source B", url: "https://example.test/source-b" }, + ]; + const changedSources = [ + { label: "Inserted source", url: "https://example.test/inserted" }, + existingSources[1], + existingSources[0], + ]; + const before = new Map( + specifierAuthoritativeSourceReferences(existingSources).map((reference) => [ + reference.canonicalUrl, + reference.usage.recordId, + ]), + ); + const after = new Map( + specifierAuthoritativeSourceReferences(changedSources).map((reference) => [ + reference.canonicalUrl, + reference.usage.recordId, + ]), + ); + + expect(after.get(existingSources[0].url)).toBe(before.get(existingSources[0].url)); + expect(after.get(existingSources[1].url)).toBe(before.get(existingSources[1].url)); + expect([...before.values()].every((recordId) => !/^authoritative-source-\d+$/.test(recordId))).toBe(true); + }); + + it("reports formulation library entries with no mechanism usage", () => { + expect( + repositorySourceCoverageIssues({ + formulationMechanisms: [], + formulationSourceLibrary: { + "orphan-source": { + id: "orphan-source", + title: "Orphan source fixture", + url: "https://example.test/orphan-source", + }, + }, + }), + ).toContain("Formulation source orphan-source has no mechanism usage"); + }); + + it("keeps every provider reference valid at the reusable offline-check seam", () => { + for (const entry of repositorySourceProviders) { + expect(repositorySourceReferenceIssues(entry.id, entry.references())).toEqual([]); + } + }); + + it("rejects HTTPS source URLs with embedded credentials consistently with catalogue canonicalisation", () => { + const credentialUrl = (() => { + const url = new URL("https://example.test/source"); + url.username = "fixture-user"; + url.password = "fixture-pass-not-a-real-secret"; + return url.toString(); + })(); + const credentialReference = { + ...provider("dictionary").references()[0], + canonicalUrl: credentialUrl, + }; + + const issues = repositorySourceReferenceIssues("credential-fixture", [credentialReference]); + expect(issues).toContain("Provider credential-fixture returned unsafe structured URL"); + expect(JSON.stringify(issues)).not.toContain("fixture-user"); + expect(JSON.stringify(issues)).not.toContain("fixture-pass-not-a-real-secret"); + expect(canonicalizeSourceReferences([credentialReference])[0].warnings).toContain("unsafe_location"); + }); + + it("fails closed for unallowlisted hosts and credential-bearing query parameters without echoing values", () => { + const baseReference = provider("dictionary").references()[0]; + const secret = "provider-query-secret"; + const references = [ + { ...baseReference, canonicalUrl: "https://unreviewed-source.example/guidance" }, + { ...baseReference, canonicalUrl: `https://www.ranzcp.org/guidance?X_AMZ_SIGNATURE=${secret}` }, + ]; + + const issues = repositorySourceReferenceIssues("url-policy-fixture", references); + + expect(issues).toEqual([ + "Provider url-policy-fixture returned unsafe structured URL", + "Provider url-policy-fixture returned unsafe structured URL", + ]); + expect(JSON.stringify(issues)).not.toContain("unreviewed-source"); + expect(JSON.stringify(issues)).not.toContain(secret); + }); + + it("accepts only the two current benign provider query forms", () => { + const baseReference = provider("dictionary").references()[0]; + const allowed = [ + { ...baseReference, canonicalUrl: "https://www.health.gov.au/resource?language=en" }, + { ...baseReference, canonicalUrl: "https://www.legislation.wa.gov.au/act?OpenElement" }, + ]; + const rejected = [ + { ...baseReference, canonicalUrl: "https://www.ranzcp.org/guidance?view=summary" }, + { ...baseReference, canonicalUrl: "https://www.health.gov.au/resource?language=en&view=summary" }, + ]; + + expect(repositorySourceReferenceIssues("allowed-query-fixture", allowed)).toEqual([]); + expect(repositorySourceReferenceIssues("rejected-query-fixture", rejected)).toEqual([ + "Provider rejected-query-fixture returned unsafe structured URL", + "Provider rejected-query-fixture returned unsafe structured URL", + ]); + }); + + it("reports malformed structured dates without echoing their raw values", () => { + const malformedDate = "not-a-date-provider-secret"; + const invalidReference = { + ...provider("dictionary").references()[0], + publicationDate: malformedDate, + }; + + const issues = repositorySourceReferenceIssues("date-policy-fixture", [invalidReference]); + + expect(issues).toContain("Provider date-policy-fixture returned an invalid structured date"); + expect(JSON.stringify(issues)).not.toContain(malformedDate); + }); + + it("keeps therapy citation prose as one provisional D-band source per explicit item", () => { + const references = provider("therapies").references(); + const explicitSourceCount = therapies.reduce((total, therapy) => total + therapy.sources.length, 0); + expect(references).toHaveLength(explicitSourceCount); + expect(references.every((reference) => reference.publisher === null && reference.sourceId === null)).toBe(true); + expect(references.every((reference) => reference.validationStatus === "unverified")).toBe(true); + expect(canonicalizeSourceReferences(references).every((entry) => entry.rating.band === "D")).toBe(true); + }); +}); diff --git a/tests/source-document-loader.test.ts b/tests/source-document-loader.test.ts new file mode 100644 index 0000000000..fa0052e651 --- /dev/null +++ b/tests/source-document-loader.test.ts @@ -0,0 +1,212 @@ +import { beforeEach, describe, expect, it, vi } from "vitest"; + +vi.mock("server-only", () => ({})); + +const createSupabaseServerClientMock = vi.hoisted(() => vi.fn()); +const createAdminClientMock = vi.hoisted(() => vi.fn()); + +vi.mock("@/lib/supabase/server", () => ({ + createSupabaseServerClient: createSupabaseServerClientMock, +})); +vi.mock("@/lib/supabase/admin", () => ({ + createAdminClient: createAdminClientMock, +})); + +import { canonicalizeSourceReferences } from "@/lib/sources/catalogue-core"; +import { + documentRowsToSourceReferences, + loadVisibleDocumentSourceReferences, +} from "@/lib/sources/document-source-loader"; + +const metadata = { + source_kind: "document", + source_title: "WA clinical guidance", + publisher: "Armadale Kalamunda Group", + publisher_code: "AKG", + jurisdiction: "Australia/WA", + version: "2", + publication_date: "2025-01-01", + review_date: "2026-01-01", + document_status: "current", + clinical_validation_status: "locally_reviewed", + topics: ["Mood", "Clinical governance"], +}; + +const indexedDocument = { + id: "22222222-2222-4222-8222-222222222222", + owner_id: null, + title: "Fallback document title", + file_name: "fallback.pdf", + status: "indexed", + metadata, + updated_at: "2026-08-30T00:00:00.000Z", +}; + +const registryProjection = { + ...indexedDocument, + id: "33333333-3333-4333-8333-333333333333", + metadata: { ...metadata, source_kind: "registry_record" }, +}; + +const queuedUpload = { + ...indexedDocument, + id: "44444444-4444-4444-8444-444444444444", + status: "queued", +}; + +class QueryDouble { + filters: Array<["eq" | "is", string, unknown]> = []; + orFilter = ""; + rows = [indexedDocument]; + error: { message: string } | null = null; + + eq(column: string, value: unknown) { + this.filters.push(["eq", column, value]); + return this; + } + + is(column: string, value: null) { + this.filters.push(["is", column, value]); + return this; + } + + or(filters: string) { + this.orFilter = filters; + return this; + } + + async order() { + return { data: this.rows, error: this.error }; + } +} + +describe("visible document source projection", () => { + let queryDouble: QueryDouble; + + beforeEach(() => { + queryDouble = new QueryDouble(); + createSupabaseServerClientMock.mockReset(); + createAdminClientMock.mockReset(); + }); + + it("scopes anonymous reads to deliberately public indexed documents", async () => { + const result = await loadVisibleDocumentSourceReferences({ + viewerId: async () => undefined, + query: () => queryDouble as never, + }); + expect(queryDouble.filters).toContainEqual(["is", "owner_id", null]); + expect(queryDouble.filters).toContainEqual(["eq", "metadata->>public_corpus", "true"]); + expect(queryDouble.filters).toContainEqual(["eq", "status", "indexed"]); + expect(result.availability).toBe("available"); + expect(result.references.every((reference) => reference.documentId)).toBe(true); + }); + + it("includes a signed-in owner's documents plus deliberately public documents", async () => { + await loadVisibleDocumentSourceReferences({ + viewerId: async () => "11111111-1111-4111-8111-111111111111", + query: () => queryDouble as never, + }); + expect(queryDouble.orFilter).toContain("owner_id.eq.11111111-1111-4111-8111-111111111111"); + expect(queryDouble.orFilter).toContain("metadata->>public_corpus.eq.true"); + }); + + it("returns only allowlisted catalogue fields and omits ungoverned hosted-document topics", () => { + const [reference] = documentRowsToSourceReferences([ + { + ...indexedDocument, + storage_path: "private/path", + content: "private document text", + metadata: { ...metadata, patient_name: "hidden", raw_notes: "hidden" }, + }, + ]); + expect(reference).toMatchObject({ + documentId: indexedDocument.id, + title: metadata.source_title, + publisher: metadata.publisher, + publisherCode: metadata.publisher_code, + topics: [], + }); + const serialised = JSON.stringify(reference); + expect(serialised).not.toContain("private/path"); + expect(serialised).not.toContain("private document text"); + expect(serialised).not.toContain("patient_name"); + expect(serialised).not.toContain("raw_notes"); + expect(serialised).not.toContain("owner_id"); + }); + + it("keeps missing hosted clinical validation distinct from explicit unverified status", () => { + const [missing, explicit] = documentRowsToSourceReferences([ + { + ...indexedDocument, + id: "55555555-5555-4555-8555-555555555555", + metadata: { ...metadata, clinical_validation_status: undefined }, + }, + { + ...indexedDocument, + id: "66666666-6666-4666-8666-666666666666", + metadata: { ...metadata, clinical_validation_status: "unverified" }, + }, + ]); + + expect(missing.validationStatus).toBe("unknown"); + expect(explicit.validationStatus).toBe("unverified"); + }); + + it("does not project patient names, identifiers, or secret-shaped metadata topics", () => { + const sensitiveTopics = ["Jane Citizen", "MRN-123456", "api_key=super-secret"]; + const [reference] = documentRowsToSourceReferences([ + { + ...indexedDocument, + metadata: { ...metadata, topics: sensitiveTopics }, + }, + ]); + const [entry] = canonicalizeSourceReferences([reference]); + + expect(reference.topics).toEqual([]); + expect(entry.topics).toEqual([]); + const projected = JSON.stringify({ reference, entry }); + for (const sensitiveTopic of sensitiveTopics) expect(projected).not.toContain(sensitiveTopic); + }); + + it("excludes registry projections and non-indexed uploads", () => { + expect(documentRowsToSourceReferences([registryProjection, queuedUpload])).toEqual([]); + }); + + it("links visible documents directly to their encoded document route", () => { + const [entry] = canonicalizeSourceReferences(documentRowsToSourceReferences([indexedDocument])); + expect(entry.canonicalLocation).toEqual({ + kind: "document", + documentId: indexedDocument.id, + href: `/documents/${encodeURIComponent(indexedDocument.id)}`, + }); + }); + + it("reports hosted documents unavailable without leaking partial rows on query errors", async () => { + queryDouble.error = { message: "unavailable" }; + const result = await loadVisibleDocumentSourceReferences({ + viewerId: async () => undefined, + query: () => queryDouble as never, + }); + expect(result).toEqual({ references: [], availability: "unavailable" }); + }); + + it("reports hosted documents unavailable when the default authentication lookup errors", async () => { + createSupabaseServerClientMock.mockResolvedValue({ + auth: { + getUser: async () => ({ + data: { user: null }, + error: { message: "sensitive authentication failure" }, + }), + }, + }); + createAdminClientMock.mockReturnValue({ + from: () => ({ select: () => queryDouble }), + }); + + const result = await loadVisibleDocumentSourceReferences(); + + expect(result).toEqual({ references: [], availability: "unavailable" }); + expect(createAdminClientMock).not.toHaveBeenCalled(); + expect(JSON.stringify(result)).not.toContain("sensitive authentication failure"); + }); +}); diff --git a/tests/source-url-policy.test.ts b/tests/source-url-policy.test.ts new file mode 100644 index 0000000000..aba1c321a6 --- /dev/null +++ b/tests/source-url-policy.test.ts @@ -0,0 +1,37 @@ +import { describe, expect, it } from "vitest"; + +import { safeCanonicalSourceUrl } from "@/lib/sources/source-url-policy"; + +describe("governed source URL query policy", () => { + it.each(["https://www.health.gov.au/resource?language=en", "https://www.legislation.wa.gov.au/act?OpenElement"])( + "allows the current benign query form %s", + (value) => { + expect(safeCanonicalSourceUrl(value)).toBe(value); + }, + ); + + it.each([ + "client_secret", + "refresh_token", + "session_token", + "jwt", + "access_key", + "auth_token", + "X-Amz-Credential", + "X-Amz-Security-Token", + ])("rejects the credential-shaped query key %s", (key) => { + expect(safeCanonicalSourceUrl(`https://www.ranzcp.org/guidance?${key}=sensitive-value`)).toBeNull(); + }); + + it.each([ + "https://www.ranzcp.org/guidance?view=summary", + "https://www.ranzcp.org/guidance?next=https%3A%2F%2Fexample.invalid%2Fsigned%3Ftoken%3Dsecret", + "https://www.health.gov.au/resource?language=english", + "https://www.health.gov.au/resource?language=en&language=fr", + "https://www.health.gov.au/resource?language=en&view=summary", + "https://www.legislation.wa.gov.au/act?OpenElement=1", + "https://www.legislation.wa.gov.au/act?OpenElement&view=summary", + ])("rejects the non-allowlisted query shape %s", (value) => { + expect(safeCanonicalSourceUrl(value)).toBeNull(); + }); +}); diff --git a/tests/sources-mode.dom.test.tsx b/tests/sources-mode.dom.test.tsx new file mode 100644 index 0000000000..3996df80df --- /dev/null +++ b/tests/sources-mode.dom.test.tsx @@ -0,0 +1,314 @@ +/** @vitest-environment jsdom */ + +import { cleanup, fireEvent, render, screen, within } from "@testing-library/react"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; + +import DictionarySourcesRedirect from "@/app/(search-app)/dictionary/sources/page"; +import { SourcesCatalogueClient } from "@/components/sources/sources-catalogue-client"; +import { + SourceDetailPage, + SourcesMethodPage, + SourcesPublishersPage, + SourcesTopicsPage, +} from "@/components/sources/sources-pages"; +import { SOURCE_RATING_WEIGHTS, type ClinicalSourceCatalogueEntry } from "@/lib/sources/catalogue-types"; + +const loadCatalogueMock = vi.hoisted(() => vi.fn()); +const routerReplace = vi.hoisted(() => vi.fn()); +const redirectMock = vi.hoisted(() => vi.fn()); +let currentSearchParams = new URLSearchParams(); + +vi.mock("server-only", () => ({})); +vi.mock("@/lib/sources/load-source-catalogue", () => ({ loadSourceCatalogue: loadCatalogueMock })); +vi.mock("next/navigation", () => ({ + usePathname: () => "/sources", + useRouter: () => ({ replace: routerReplace }), + useSearchParams: () => currentSearchParams, + redirect: redirectMock, + notFound: vi.fn(), +})); + +function sourceEntry( + overrides: Partial & Pick, +): ClinicalSourceCatalogueEntry { + const { id, title, ...rest } = overrides; + return { + id, + sourceId: id, + title, + aliases: [], + version: "1", + publisher: "RANZCP", + publisherCode: "RANZCP", + sourceType: "guideline", + canonicalLocation: { kind: "url", href: "https://www.ranzcp.org/example" }, + geography: { scope: "australian_national", label: "Australia" }, + topics: ["governance"], + publicationDate: "2025-01-01", + reviewDate: "2026-01-01", + expiryDate: null, + documentStatus: "current", + validationStatus: "approved", + contentMode: "link_only", + lifecycleStatus: "active", + supersedes: [], + supersededBy: [], + usedBy: [ + { + modeId: "dictionary", + recordId: "mental-state-examination", + recordLabel: "Mental state examination", + field: "definition", + }, + ], + rating: { + score: 90, + band: "A", + weights: SOURCE_RATING_WEIGHTS, + dimensions: { + accuracyAssurance: 25, + reliability: 20, + evidenceQuality: 20, + currency: 15, + australianApplicability: 10, + traceability: 0, + }, + reasons: ["Accuracy assurance: 25/25"], + }, + warnings: [], + ...rest, + }; +} + +const fixtureEntries: ClinicalSourceCatalogueEntry[] = [ + sourceEntry({ id: "src_a", title: "Zulu Australian guideline" }), + sourceEntry({ + id: "src_d", + title: "Alpha review source", + publisher: "Legacy Publisher", + publisherCode: null, + sourceType: "professional_reference", + canonicalLocation: { kind: "dataset", label: "Structured clinical catalogue" }, + geography: { scope: "international", label: "International" }, + topics: ["assessment"], + documentStatus: "review_due", + validationStatus: "unverified", + usedBy: [{ modeId: "factsheets", recordId: "depression", recordLabel: "Depression", field: "sources" }], + rating: { + score: 45, + band: "D", + weights: SOURCE_RATING_WEIGHTS, + dimensions: { + accuracyAssurance: 5, + reliability: 8, + evidenceQuality: 12, + currency: 8, + australianApplicability: 6, + traceability: 5, + }, + reasons: ["Material identity or verification uncertainty requires review"], + }, + warnings: ["verification_unknown"], + }), +]; + +beforeEach(() => { + currentSearchParams = new URLSearchParams(); + routerReplace.mockReset(); + redirectMock.mockReset(); + loadCatalogueMock.mockReset(); + loadCatalogueMock.mockResolvedValue({ entries: fixtureEntries, hostedDocuments: "unavailable" }); +}); + +afterEach(cleanup); + +describe("Sources catalogue", () => { + it("renders the client-safe catalogue, defaults and truthful degraded state", () => { + render(); + + expect(screen.getByRole("heading", { level: 1, name: "Sources" })).toBeVisible(); + expect(screen.getAllByText("A · Preferred")[0]).toBeVisible(); + expect(screen.getByLabelText("Filter by quality band")).toHaveValue(""); + expect(screen.getByLabelText("Sort sources")).toHaveValue("quality"); + expect(screen.getByRole("status")).toHaveTextContent("2 sources"); + expect(screen.getByText("Hosted document sources are temporarily unavailable")).toBeVisible(); + expect(screen.queryByText(/storage_path|owner_id|patient/i)).not.toBeInTheDocument(); + }); + + it("reads application usage from the URL and updates filters through router.replace", () => { + currentSearchParams = new URLSearchParams("usedBy=dictionary"); + const view = render(); + + expect(screen.getByLabelText("Filter by application usage")).toHaveValue("dictionary"); + expect(screen.getByRole("status")).toHaveTextContent("1 source"); + expect(screen.getAllByText("Zulu Australian guideline").length).toBeGreaterThan(0); + expect(screen.queryByText("Alpha review source")).not.toBeInTheDocument(); + + fireEvent.change(screen.getByLabelText("Filter by quality band"), { target: { value: "D" } }); + expect(routerReplace).toHaveBeenLastCalledWith("/sources?usedBy=dictionary&band=D", { scroll: false }); + + view.unmount(); + currentSearchParams = new URLSearchParams("band=D&publisher=Legacy+Publisher"); + render(); + expect(screen.getByRole("status")).toHaveTextContent("1 source"); + expect(screen.getAllByText("Alpha review source").length).toBeGreaterThan(0); + }); + + it("surfaces and removes every repeated filter value without discarding its siblings", () => { + currentSearchParams = new URLSearchParams( + "band=A&band=D&usedBy=dictionary&usedBy=factsheets&publisher=Legacy+Publisher", + ); + render(); + + expect(screen.getByLabelText("Filter by quality band")).toHaveValue(""); + expect(screen.getByLabelText("Filter by application usage")).toHaveValue(""); + expect(screen.getByRole("button", { name: "Remove quality band: A · Preferred" })).toBeVisible(); + expect(screen.getByRole("button", { name: "Remove quality band: D · Review required" })).toBeVisible(); + expect(screen.getByRole("button", { name: "Remove application usage: Dictionary" })).toBeVisible(); + expect(screen.getByRole("button", { name: "Remove application usage: Factsheets" })).toBeVisible(); + + fireEvent.click(screen.getByRole("button", { name: "Remove quality band: D · Review required" })); + expect(routerReplace).toHaveBeenLastCalledWith( + "/sources?band=A&usedBy=dictionary&usedBy=factsheets&publisher=Legacy+Publisher", + { scroll: false }, + ); + }); + + it("removes a visible comma-delimited filter value while preserving its siblings", () => { + currentSearchParams = new URLSearchParams("band=A%2CD&usedBy=dictionary"); + render(); + + fireEvent.click(screen.getByRole("button", { name: "Remove quality band: D · Review required" })); + + expect(routerReplace).toHaveBeenLastCalledWith("/sources?band=A&usedBy=dictionary", { scroll: false }); + }); + + it("sorts by quality or title and offers a wired reset for empty filters", () => { + const quality = render(); + const qualityRows = within(screen.getByRole("table")).getAllByRole("row").slice(1); + expect(within(qualityRows[0]).getByRole("link")).toHaveTextContent("Zulu Australian guideline"); + + quality.unmount(); + currentSearchParams = new URLSearchParams("sort=title"); + const title = render(); + const titleRows = within(screen.getByRole("table")).getAllByRole("row").slice(1); + expect(within(titleRows[0]).getByRole("link")).toHaveTextContent("Alpha review source"); + + title.unmount(); + currentSearchParams = new URLSearchParams("band=A&publisher=Legacy+Publisher"); + render(); + expect(screen.getByRole("status")).toHaveTextContent("0 sources"); + expect(screen.getByRole("heading", { name: "No sources match these filters" })).toBeVisible(); + fireEvent.click(screen.getByRole("button", { name: "Reset filters" })); + expect(routerReplace).toHaveBeenCalledWith("/sources", { scroll: false }); + }); +}); + +describe("Sources derived pages", () => { + it("links topic and publisher groups back to filtered catalogue results", async () => { + const topics = render(await SourcesTopicsPage()); + expect(screen.getByRole("heading", { level: 1, name: "Topics" })).toBeVisible(); + expect(screen.getByRole("link", { name: /governance/i })).toHaveAttribute("href", "/sources?topic=governance"); + + topics.unmount(); + render(await SourcesPublishersPage()); + expect(screen.getByRole("heading", { level: 1, name: "Publishers" })).toBeVisible(); + expect(screen.getByRole("heading", { level: 2, name: "Australian national" })).toBeVisible(); + expect(screen.getByRole("heading", { level: 3, name: "RANZCP" })).toBeVisible(); + expect(screen.getByRole("heading", { level: 2, name: "International" })).toBeVisible(); + expect(screen.getByRole("heading", { level: 3, name: "Legacy Publisher" })).toBeVisible(); + expect(screen.getByRole("link", { name: /view ranzcp sources/i })).toHaveAttribute( + "href", + "/sources?publisher=RANZCP&jurisdiction=australian_national", + ); + }); + + it("keeps publisher jurisdiction-group counts aligned with their catalogue links", async () => { + loadCatalogueMock.mockResolvedValueOnce({ + entries: [ + fixtureEntries[0], + sourceEntry({ + id: "src_ranzcp_international", + title: "RANZCP international source", + geography: { scope: "international", label: "International" }, + }), + ], + hostedDocuments: "available", + }); + + render(await SourcesPublishersPage()); + + const links = screen.getAllByRole("link", { name: /view ranzcp sources/i }); + expect(links.map((link) => link.getAttribute("href"))).toEqual([ + "/sources?publisher=RANZCP&jurisdiction=australian_national", + "/sources?publisher=RANZCP&jurisdiction=international", + ]); + expect(links).toHaveLength(2); + }); + + it("publishes every weight, threshold and limitation on Method", () => { + render(); + expect(screen.getByRole("heading", { level: 1, name: "Method" })).toBeVisible(); + expect(screen.getByText("Accuracy assurance")).toBeVisible(); + expect(screen.getByText("25 points")).toBeVisible(); + expect(screen.getByText(/A · Preferred.*85–100/)).toBeVisible(); + expect(screen.getByText(/Excluded.*before.*score/i)).toBeVisible(); + expect(screen.getByText(/Australian applicability is bounded/i)).toBeVisible(); + expect(screen.getByText(/Missing fields remain unknown/i)).toBeVisible(); + expect( + screen.getByText( + /Missing publisher, version, dates, jurisdiction, evidence type or validation.*D · Review required/i, + ), + ).toBeVisible(); + expect(screen.getByText(/past expiry.*no current currency credit/i)).toBeVisible(); + expect(screen.getByText(/identified replacement.*excluded/i)).toBeVisible(); + expect(screen.getByText(/not RAG relevance or patient-specific guidance/i)).toBeVisible(); + const definitions = screen.getByRole("region", { name: "Catalogue status definitions" }); + for (const label of [ + "Current", + "Review due", + "Outdated", + "Unknown currentness", + "Approved", + "Locally reviewed", + "Unverified", + "Unknown validation", + "Active", + "Inactive", + "Excluded", + "Indexed content", + "Link only", + "Metadata only", + ]) { + expect(within(definitions).getByText(label)).toBeVisible(); + } + expect( + within(definitions).getByText(/explicit upstream status says the source is due for structured review/i), + ).toBeVisible(); + expect(within(definitions).getByText(/malformed expiry.*currentness remains unknown/i)).toBeVisible(); + expect(within(definitions).getByText(/content can be searched inside the application/i)).toBeVisible(); + }); + + it("shows the three explicit location labels and full traceability on detail", async () => { + render(await SourceDetailPage({ sourceId: "src_a" })); + expect(screen.getByRole("heading", { level: 1, name: "Zulu Australian guideline" })).toBeVisible(); + expect(screen.getByText("Canonical location")).toBeVisible(); + expect(screen.getByText("Geographic location")).toBeVisible(); + expect(screen.getByText("Application location")).toBeVisible(); + expect(screen.getByRole("link", { name: /open canonical source/i })).toHaveAttribute( + "href", + "https://www.ranzcp.org/example", + ); + expect(screen.getByText("Mental state examination")).toBeVisible(); + expect(screen.getByText("Accuracy assurance: 25/25")).toBeVisible(); + }); +}); + +describe("Dictionary Sources compatibility redirect", () => { + it("preserves incoming query values and forces dictionary application usage", async () => { + await DictionarySourcesRedirect({ + searchParams: Promise.resolve({ q: "RANZCP", band: ["A", "D"], usedBy: "factsheets" }), + }); + expect(redirectMock).toHaveBeenCalledWith("/sources?q=RANZCP&band=A&band=D&usedBy=dictionary"); + }); +}); diff --git a/tests/tools-catalog.test.ts b/tests/tools-catalog.test.ts index bd3b9d5345..d1a1fb3770 100644 --- a/tests/tools-catalog.test.ts +++ b/tests/tools-catalog.test.ts @@ -20,11 +20,22 @@ describe("tools catalog", () => { "services", "forms", "calculators", + "source-catalogue", ]) { expect(ids).toContain(staple); } }); + it("exposes Sources as a ready source-backed reference tool", () => { + expect(toolCatalogRecordById("source-catalogue")).toMatchObject({ + title: "Sources", + href: "/sources", + area: "reference", + status: "ready", + sourceBacked: true, + }); + }); + it("links shared-home tools directly to their canonical mode homes", () => { const sharedHomeTools = [ ["differentials", "differentials"], diff --git a/tests/ui-copy.test.ts b/tests/ui-copy.test.ts index 6864918552..de6a77cbac 100644 --- a/tests/ui-copy.test.ts +++ b/tests/ui-copy.test.ts @@ -105,6 +105,11 @@ const EXPECTED_MODE_TITLES: Record< standaloneTitle: "Dictionary", subtitle: "Source-governed psychiatric terms, abbreviations, and distinctions.", }, + sources: { + sharedTitle: "Sources", + standaloneTitle: "Sources", + subtitle: "Clinical source catalogue.", + }, }; describe("ui-copy", () => { @@ -112,7 +117,7 @@ describe("ui-copy", () => { it("covers every declared app mode exactly once", () => { const definedModes = Object.keys(sharedHomePresentation) as AppModeId[]; expect(definedModes.sort()).toEqual([...appModeIds].sort()); - expect(definedModes).toHaveLength(15); + expect(definedModes).toHaveLength(16); }); it.each(appModeIds)("provides non-empty title and subtitle for %s", (modeId) => { @@ -148,6 +153,14 @@ describe("ui-copy", () => { it("pins Therapy title to 'Therapy' (not 'Therapy Compass')", () => { expect(sharedHomePresentation["therapy-compass"].title).toBe("Therapy"); }); + + it("publishes the exact Sources starter suggestions", () => { + expect(sharedHomePresentation.sources.suggestions).toEqual([ + "Australian guidelines", + "RANZCP", + "review required", + ]); + }); }); describe("sharedHomeEmptyState", () => { diff --git a/tests/ui-dictionary.spec.ts b/tests/ui-dictionary.spec.ts index efe2e7676b..0d36690a0d 100644 --- a/tests/ui-dictionary.spec.ts +++ b/tests/ui-dictionary.spec.ts @@ -20,7 +20,6 @@ const routes = [ path: "/dictionary/compare?a=mental-state-examination&b=mini-mental-state-examination", testId: "dictionary-compare-main", }, - { path: "/dictionary/sources", testId: "dictionary-sources-main" }, ] as const; async function blockExternalRequests(page: Page) { diff --git a/tests/ui-mode-nav-density.spec.ts b/tests/ui-mode-nav-density.spec.ts index 4f2625b1c6..60f926cd8a 100644 --- a/tests/ui-mode-nav-density.spec.ts +++ b/tests/ui-mode-nav-density.spec.ts @@ -83,6 +83,7 @@ const MODES = [ { modeId: "therapy-compass", route: "/therapy-compass/search?q=CBT&run=1", items: 5, profile: "extended" }, { modeId: "dsm", route: "/dsm/compare", items: 2, profile: "two-item" }, { modeId: "specifiers", route: "/specifiers/compare", items: 4, profile: "compact-four" }, + { modeId: "sources", route: "/sources?q=RANZCP", items: 4, profile: "balanced-four" }, { modeId: "formulation", route: "/formulation/compare", items: 4, profile: "compact-four" }, { modeId: "differentials", route: "/differentials/diagnoses", items: 4, profile: "balanced-four" }, { modeId: "factsheets", route: "/factsheets/search", items: 2, profile: "two-item" }, diff --git a/tests/ui-sources.spec.ts b/tests/ui-sources.spec.ts new file mode 100644 index 0000000000..1557e124d8 --- /dev/null +++ b/tests/ui-sources.spec.ts @@ -0,0 +1,69 @@ +import AxeBuilder from "@axe-core/playwright"; +import { expect, test, type Page } from "playwright/test"; + +async function blockExternalRequests(page: Page) { + await page.route("**/*", async (route) => { + const url = new URL(route.request().url()); + if ( + (url.protocol === "http:" || url.protocol === "https:") && + !["localhost", "127.0.0.1", "::1", "[::1]"].includes(url.hostname) + ) { + await route.abort("blockedbyclient"); + return; + } + await route.fallback(); + }); +} + +async function expectNoHorizontalOverflow(page: Page) { + const overflow = await page.evaluate( + () => Math.max(document.documentElement.scrollWidth, document.body?.scrollWidth ?? 0) - window.innerWidth, + ); + expect(overflow).toBeLessThanOrEqual(2); +} + +test.beforeEach(async ({ page }) => { + await blockExternalRequests(page); +}); + +test("Dictionary sources redirects into the Sources catalogue", async ({ page }) => { + await page.goto("/dictionary/sources", { waitUntil: "domcontentloaded" }); + await expect(page).toHaveURL(/\/sources\?usedBy=dictionary$/); + await expect(page.getByLabel("Filter by application usage")).toHaveValue("dictionary"); +}); + +test("@critical Sources catalogue filters and opens traceability", async ({ page }) => { + await page.goto("/sources?usedBy=dictionary", { waitUntil: "domcontentloaded" }); + await expect(page.getByRole("heading", { level: 1, name: "Sources" })).toBeVisible(); + await expect(page.getByLabel("Filter by application usage")).toHaveValue("dictionary"); + await page.getByLabel("Filter by quality band").selectOption("D"); + await expect(page.getByRole("status")).toContainText("source"); + await page + .getByRole("link", { name: /view source details/i }) + .first() + .click(); + await expect(page.getByRole("heading", { level: 2, name: "Source locations" })).toBeVisible(); + await expect(page.getByText("Application location")).toBeVisible(); +}); + +test("Sources remains operable at phone width and under accessibility media", async ({ + page, + browserName, +}, testInfo) => { + test.skip(browserName !== "chromium", "forced-colors emulation is Chromium-only"); + await page.setViewportSize({ width: 320, height: 760 }); + await page.emulateMedia({ reducedMotion: "reduce", forcedColors: "active" }); + await page.goto("/sources"); + await expect(page.getByTestId("sources-catalogue-main")).toBeVisible(); + await page.keyboard.press("Tab"); + await expect(page.locator(":focus-visible")).toHaveCount(1); + await expectNoHorizontalOverflow(page); + const axe = await new AxeBuilder({ page }).withTags(["wcag2a", "wcag2aa", "wcag21a", "wcag21aa"]).analyze(); + await testInfo.attach("sources-axe", { + body: JSON.stringify(axe.violations, null, 2), + contentType: "application/json", + }); + expect( + axe.violations.filter((violation) => violation.impact === "critical" || violation.impact === "serious"), + ).toEqual([]); +}); From bb18c3f11ad354763f8a8eb577a922923d77a004 Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Wed, 2 Sep 2026 00:25:00 +0800 Subject: [PATCH 2/3] chore: merge-aware repo-awareness snapshot (sources + main Smart search) --- data/repo-awareness-snapshot.json | 1168 +++++++++++++++-------------- 1 file changed, 605 insertions(+), 563 deletions(-) diff --git a/data/repo-awareness-snapshot.json b/data/repo-awareness-snapshot.json index 49d03e7ede..cc42ee367e 100644 --- a/data/repo-awareness-snapshot.json +++ b/data/repo-awareness-snapshot.json @@ -1,8 +1,8 @@ { "version": "repo-awareness-snapshot-v1", "captured_revision": { - "sha": "075ff1f962cc7e4e39fece581cab4416cc33f3ce", - "committed_at": "2026-09-01T15:33:13Z" + "sha": "a4d600782727ffbd4fc0e899a3c502c5a668bf5e", + "committed_at": "2026-09-01T23:34:27+08:00" }, "routes": { "modes": [ @@ -179,6 +179,11 @@ "file": "src/app/(search-app)/dictionary/search/page.tsx", "area": "product" }, + { + "path": "/dictionary/sources", + "file": "src/app/(search-app)/dictionary/sources/page.tsx", + "area": "product" + }, { "path": "/dictionary/topics", "file": "src/app/(search-app)/dictionary/topics/page.tsx", @@ -1146,11 +1151,6 @@ "file": "src/app/(search-app)/dictionary/browse/page.tsx", "target": "/dictionary/search" }, - { - "path": "/dictionary/sources", - "file": "src/app/(search-app)/dictionary/sources/page.tsx", - "target": "/sources?usedBy=dictionary" - }, { "path": "/differentials", "file": "src/app/(search-app)/differentials/page.tsx", @@ -1461,10 +1461,10 @@ ], "counts": { "modes": 16, - "pages": 204, - "product_pages": 67, + "pages": 205, + "product_pages": 68, "mockup_pages": 137, - "redirects": 18, + "redirects": 17, "api": 60 } }, @@ -3615,6 +3615,11 @@ "section": "superpowers", "catalogued": false }, + { + "path": "docs/superpowers/plans/2026-09-01-native-smart-catalogue-search.md", + "section": "superpowers", + "catalogued": false + }, { "path": "docs/superpowers/plans/2026-09-01-services-safety-provenance.md", "section": "superpowers", @@ -3915,6 +3920,11 @@ "section": "superpowers", "catalogued": false }, + { + "path": "docs/superpowers/specs/2026-09-01-native-smart-catalogue-search-design.md", + "section": "superpowers", + "catalogued": false + }, { "path": "docs/superpowers/specs/2026-09-01-services-safety-provenance-design.md", "section": "superpowers", @@ -4357,9 +4367,9 @@ } ], "counts": { - "documents": 564, + "documents": 566, "catalogued": 111, - "uncatalogued": 453, + "uncatalogued": 455, "sections": 21 } }, @@ -4372,6 +4382,14 @@ }, "review_state": { "records": [ + { + "date": "2026-09-01", + "ref": "codex/smart-local-modes-20260901 (PR #2508)", + "head": "a1e1b973599e9bb301360be90c051986c172670f", + "scope": "PR #2508 native Smart catalogue matching", + "outcome": "Fixed P1 Compare result-order regression; no additional P0-P3 findings.", + "checks": "Focused Vitest 10/10; npm run format; full suite stopped before provider-backed path." + }, { "date": "2026-09-01", "ref": "PR-2504", @@ -4380,6 +4398,30 @@ "outcome": "Replaced inaccessible authenticated-table reads with an independently administrator-gated service-role boundary that filters every query to the verified owner; restored the complete implementation after an intervening placeholder-only commit.", "checks": "Focused developer corpus-health test: 16 passed; explicit owner-filter and non-administrator coverage; diff check." }, + { + "date": "2026-09-01", + "ref": "PR-2504", + "head": "3b1dc7c8bc997a4ea4bac44dc7de01632e676e63", + "scope": "Resolve Codex P1: corpus-health table access", + "outcome": "Verified the authenticated role lacks table SELECT; the administrator-gated server-only service-role path scopes every documents and document_index_quality query to the verified owner, with current access-control documentation.", + "checks": "Focused corpus-health suite: 18 passed; Prettier check passed; schema grants verified; independent review found no runtime access-control defect." + }, + { + "date": "2026-09-01", + "ref": "PR-2507", + "head": "ebb57785958888c2703ccb6cadac76ce344065ee", + "scope": "Run PR sweep: enforce Favourites phone tap-target minimum", + "outcome": "Replaced the blacklist-only target guard with a positive 48px-or-row-wide requirement and mutation fixtures for undersized or implicit controls.", + "checks": "Focused Favourites phone mockup test: 9 passed; diff check." + }, + { + "date": "2026-09-01", + "ref": "PR-2508", + "head": "14a99d0c412a3c53bf92b684c5b7e5b57ca1ccd9", + "scope": "Run PR sweep: prioritise embedded catalogue identities", + "outcome": "Ranked named Factsheet titles or brands and Dictionary terms or abbreviations above related Smart expansion matches in natural-language queries.", + "checks": "Focused Factsheets and Dictionary tests: 35 passed; direct-identity regression coverage; diff check." + }, { "date": "2026-08-31", "ref": "codex/answer-surface-compact-20260830", @@ -4409,7 +4451,7 @@ "ref": "gemini/pr-group-3-ui-a11y-caring-contacts-ward-flow (PR #2479)", "head": "8ff3f26c6e4f5302c1883f940f4cc1b22fbeec5c", "scope": "Run PR sweep: existing unresolved review threads", - "outcome": "0 \u2192 2 threads resolved: useful-actions disclosure semantics, workspace route registration assertion", + "outcome": "0 → 2 threads resolved: useful-actions disclosure semantics, workspace route registration assertion", "checks": "Focused Vitest 18/18; typecheck passed; no provider-backed checks run" }, { @@ -4481,7 +4523,7 @@ "ref": "codex/dsm-search-ux-elevation (PR #2415)", "head": "958a6b4f7c969f07cb118ccc0c581939fd81bcab", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Before: mergeable_state dirty again (main advanced one more commit, #2416, past the prior sweep's merge, re-conflicting the generated repo-awareness snapshot); required CI red on the prior head (5b22edb2) with Production UI (1) failing tests/ui-route-coverage.spec.ts 'DSM home renders responsively and opens comparison' (expected /dsm/compare$ but got /dsm/compare?q=major+depressive, because the prior sweep's merge silently dropped a same-PR fix commit's dropped $ anchor while keeping its other hunks) and PR mergeability failing on the dirty state; 0 unresolved review threads (6 PR comments were all bot rate-limit/housekeeping noise: Codex usage limit, CodeRabbit review limit, Cursor Bugbot limit x2, Supabase preview skip, CI-triage bot). After: merged origin/main resolving the sole conflict (data/repo-awareness-snapshot.json, a generated file) by regenerating via npm run snapshot:repo-awareness rather than hand-editing; separately fixed the real route-coverage regression by dropping the stale $ anchor on the /dsm/compare URL assertion (restoring intended behaviour: Compare now carries q/ids from DSM search, matching this PR's own preserve-filters design) \u2014 both included in merge commit 958a6b4f. No review threads needed action (still zero unresolved). Pushed 958a6b4f; new CI run 33062342217 kicked off on the synced head and was still in progress at time of recording; left for a human or later session to confirm green.", + "outcome": "Before: mergeable_state dirty again (main advanced one more commit, #2416, past the prior sweep's merge, re-conflicting the generated repo-awareness snapshot); required CI red on the prior head (5b22edb2) with Production UI (1) failing tests/ui-route-coverage.spec.ts 'DSM home renders responsively and opens comparison' (expected /dsm/compare$ but got /dsm/compare?q=major+depressive, because the prior sweep's merge silently dropped a same-PR fix commit's dropped $ anchor while keeping its other hunks) and PR mergeability failing on the dirty state; 0 unresolved review threads (6 PR comments were all bot rate-limit/housekeeping noise: Codex usage limit, CodeRabbit review limit, Cursor Bugbot limit x2, Supabase preview skip, CI-triage bot). After: merged origin/main resolving the sole conflict (data/repo-awareness-snapshot.json, a generated file) by regenerating via npm run snapshot:repo-awareness rather than hand-editing; separately fixed the real route-coverage regression by dropping the stale $ anchor on the /dsm/compare URL assertion (restoring intended behaviour: Compare now carries q/ids from DSM search, matching this PR's own preserve-filters design) — both included in merge commit 958a6b4f. No review threads needed action (still zero unresolved). Pushed 958a6b4f; new CI run 33062342217 kicked off on the synced head and was still in progress at time of recording; left for a human or later session to confirm green.", "checks": "npm run lint (clean, gate-receipts recorded pass), npm run typecheck (clean, gate-receipts recorded pass), npm run test -- tests/mode-secondary-navigation.test.ts tests/dsm-compare-chrome.dom.test.tsx tests/dsm-search-empty-state.dom.test.tsx tests/app-modes.test.ts tests/dsm-comparison-page.dom.test.tsx (68 passed, gate-receipts recorded pass). git merge-tree confirmed the only conflict was the generated snapshot file before merging. No provider-backed checks run; hosted CI run 33062342217 in progress as of last observation." }, { @@ -4497,7 +4539,7 @@ "ref": "codex/therapy-compare-phone-ux (PR #2410)", "head": "4042bdd7af523746d4c9b7a9c6a732e36c886b7d", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Before: mergeable_state dirty (real conflict in src/components/dsm/dsm-compare-chrome.tsx vs main's #2409 DSM redesign), CI red (Build/Static PR checks/Production UI x4/Lighthouse all failing on one root-cause TS2783 duplicate-prop typecheck error in the PR's own new test), 0 unresolved review threads (all 5 PR comments were bot noise: Codex/CodeRabbit/Bugbot usage-limit notices and a CI-triage bot comment). After: merged origin/main cleanly (dsm-compare-chrome.tsx conflict resolved by combining HEAD's phoneLayout/slotSummaryLabel props with main's onCommit, verified equivalent since idsCompareHref already null-filters internally), fixed the duplicate actionLabel JSX prop in tests/compare-ids-chrome.dom.test.tsx (removed the redundant explicit prop since chromeProps spread already supplies it and the test asserts nothing about its value), pushed 2 commits (13efa061 merge, 4042bdd7 fix). No review threads needed action. New CI run (33051244071) at 4042bdd7 still in_progress after 30+ min observation window (PR mergeability + PR policy + Safety and config checks + Caring Contacts database already green); Build/Static PR checks/Unit coverage/Production UI x3/Production UI critical/Lighthouse budget not yet settled \u2014 deferred to the user per babysit budget, run: https://github.com/BigSimmo/Database/actions/runs/33051244071", + "outcome": "Before: mergeable_state dirty (real conflict in src/components/dsm/dsm-compare-chrome.tsx vs main's #2409 DSM redesign), CI red (Build/Static PR checks/Production UI x4/Lighthouse all failing on one root-cause TS2783 duplicate-prop typecheck error in the PR's own new test), 0 unresolved review threads (all 5 PR comments were bot noise: Codex/CodeRabbit/Bugbot usage-limit notices and a CI-triage bot comment). After: merged origin/main cleanly (dsm-compare-chrome.tsx conflict resolved by combining HEAD's phoneLayout/slotSummaryLabel props with main's onCommit, verified equivalent since idsCompareHref already null-filters internally), fixed the duplicate actionLabel JSX prop in tests/compare-ids-chrome.dom.test.tsx (removed the redundant explicit prop since chromeProps spread already supplies it and the test asserts nothing about its value), pushed 2 commits (13efa061 merge, 4042bdd7 fix). No review threads needed action. New CI run (33051244071) at 4042bdd7 still in_progress after 30+ min observation window (PR mergeability + PR policy + Safety and config checks + Caring Contacts database already green); Build/Static PR checks/Unit coverage/Production UI x3/Production UI critical/Lighthouse budget not yet settled — deferred to the user per babysit budget, run: https://github.com/BigSimmo/Database/actions/runs/33051244071", "checks": "npx vitest run tests/compare-slot-strip.dom.test.tsx tests/compare-ids-chrome.dom.test.tsx tests/therapy-compare-phone-layout.dom.test.tsx tests/therapy-compare-tray.dom.test.tsx tests/phone-dock-addon-contract.test.ts tests/dsm-comparison-page.dom.test.tsx -- 6 files / 53 passed; npm run typecheck -- passed after fix (5604 input files); npx eslint on touched files -- clean; no provider-backed checks run" }, { @@ -4505,15 +4547,15 @@ "ref": "codex/therapy-compare-phone-ux (PR #2410)", "head": "4af5895f48cca785333272ece41e25bcaccb7441", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Static PR checks failing (check:repo-awareness-snapshot: committed snapshot behind \u2014 review_state differs) -> merged origin/main@603da96 (clean, no conflicts) then regenerated snapshot via npm run snapshot:repo-awareness and committed; 0 unresolved review threads found (none to fix/reply/resolve). Local full gate now green. Note: main advanced again mid-sweep to be65b8a1b (PR #2415, same DSM/compare files) producing a real post-push content conflict \u2014 left unresolved for the user, not auto-resolved.", - "checks": "npm run verify:cheap equivalent set run piecewise: check:repo-awareness-snapshot (fail -> pass after regenerate), full static-pr check chain (34 gates, all pass), npm run lint (pass), npm run typecheck (pass), npm run test (893 files / 10824 tests passed, 4 skipped \u2014 two initially-failing tests (clinical-hazard-controls.test.ts, privacy-readiness-contract.test.ts) were a local shallow-clone ancestry artifact, confirmed pre-existing on plain origin/main and resolved by git fetch --deepen, not a code fix). No provider-backed checks run." + "outcome": "Static PR checks failing (check:repo-awareness-snapshot: committed snapshot behind — review_state differs) -> merged origin/main@603da96 (clean, no conflicts) then regenerated snapshot via npm run snapshot:repo-awareness and committed; 0 unresolved review threads found (none to fix/reply/resolve). Local full gate now green. Note: main advanced again mid-sweep to be65b8a1b (PR #2415, same DSM/compare files) producing a real post-push content conflict — left unresolved for the user, not auto-resolved.", + "checks": "npm run verify:cheap equivalent set run piecewise: check:repo-awareness-snapshot (fail -> pass after regenerate), full static-pr check chain (34 gates, all pass), npm run lint (pass), npm run typecheck (pass), npm run test (893 files / 10824 tests passed, 4 skipped — two initially-failing tests (clinical-hazard-controls.test.ts, privacy-readiness-contract.test.ts) were a local shallow-clone ancestry artifact, confirmed pre-existing on plain origin/main and resolved by git fetch --deepen, not a code fix). No provider-backed checks run." }, { "date": "2026-08-27", "ref": "codex/therapy-compare-phone-ux (PR #2410)", "head": "871df2793ccb63ffe92f70225e8be64e25619da7", "scope": "Resolve merge conflict against origin/main (requested follow-up after Run PR sweep)", - "outcome": "Real content conflict in compare-ids-chrome.tsx, compare-slot-strip.tsx, dsm-compare-chrome.tsx, and tests/ui-route-coverage.spec.ts caused by PR #2415 (already merged) independently reworking DsmCompareChrome to a compact horizontal rail + separate starter-chip row, while this PR added a phoneLayout=hybrid pip-summary/2x2-grid design to the same shared CompareIdsChrome/CompareSlotStrip components. Resolved by merging both prop sets into the shared components (showEmptyState/slotLayout from main plus phoneLayout/slotSummaryLabel from this PR, now coexisting) and, for the one screen both PRs redesigned (DSM compare), keeping origin/main's already-shipped compact-rail design rather than overwriting it \u2014 so this PR's hybrid layout still lands in full for Therapy compare (untouched by #2415), while DSM compare keeps its most recently reviewed design. Regenerated data/repo-awareness-snapshot.json. Pushed as merge commit 871df2793.", + "outcome": "Real content conflict in compare-ids-chrome.tsx, compare-slot-strip.tsx, dsm-compare-chrome.tsx, and tests/ui-route-coverage.spec.ts caused by PR #2415 (already merged) independently reworking DsmCompareChrome to a compact horizontal rail + separate starter-chip row, while this PR added a phoneLayout=hybrid pip-summary/2x2-grid design to the same shared CompareIdsChrome/CompareSlotStrip components. Resolved by merging both prop sets into the shared components (showEmptyState/slotLayout from main plus phoneLayout/slotSummaryLabel from this PR, now coexisting) and, for the one screen both PRs redesigned (DSM compare), keeping origin/main's already-shipped compact-rail design rather than overwriting it — so this PR's hybrid layout still lands in full for Therapy compare (untouched by #2415), while DSM compare keeps its most recently reviewed design. Regenerated data/repo-awareness-snapshot.json. Pushed as merge commit 871df2793.", "checks": "npx vitest run tests/compare-slot-strip.dom.test.tsx tests/compare-ids-chrome.dom.test.tsx tests/dsm-compare-chrome.dom.test.tsx tests/therapy-compare-phone-layout.dom.test.tsx tests/therapy-compare-tray.dom.test.tsx tests/phone-dock-addon-contract.test.ts -- 53 passed; npx tsc --noEmit -- clean; npx eslint on the 4 resolved files -- clean; npm run check:repo-awareness-snapshot -- in step; npx prettier --check on the 4 resolved files -- all match. No provider-backed checks run." }, { @@ -4545,7 +4587,7 @@ "ref": "codex/therapy-pathways-redesign (PR #2413)", "head": "be2d9b0291965258e5933006dc9b914961bb0dc3", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "CI was already green pre-sweep (PR required: success on d3f39c4); branch was already current with main (0 behind), so no drift merge needed. Fixed 3 unresolved CodeRabbit review threads: (1) pathway/step 'linked steps' counts used total steps.length instead of counting only steps with a matched therapySlug \u2014 added pathwayLinkedStepCount() and wired it into pathway-review-label.ts, pathway-picker-sheet.tsx (x2), pathway-step-stack.tsx; (2) ui-therapy-pathways.spec.ts readCautionGeometry substituted +/-Infinity for a missing caution/dock element, masking a broken overlap assertion \u2014 now throws if either is absent; (3) the 'Change pathway' Playwright test only re-clicked the already-active Anxiety pathway row, which could pass with a broken selectPathway \u2014 now selects Mood pathway, asserts the URL/heading changed, then switches back to Anxiety before the anxiety-scoped scroll assertions. All 3 threads replied with commit SHA and resolved.", + "outcome": "CI was already green pre-sweep (PR required: success on d3f39c4); branch was already current with main (0 behind), so no drift merge needed. Fixed 3 unresolved CodeRabbit review threads: (1) pathway/step 'linked steps' counts used total steps.length instead of counting only steps with a matched therapySlug — added pathwayLinkedStepCount() and wired it into pathway-review-label.ts, pathway-picker-sheet.tsx (x2), pathway-step-stack.tsx; (2) ui-therapy-pathways.spec.ts readCautionGeometry substituted +/-Infinity for a missing caution/dock element, masking a broken overlap assertion — now throws if either is absent; (3) the 'Change pathway' Playwright test only re-clicked the already-active Anxiety pathway row, which could pass with a broken selectPathway — now selects Mood pathway, asserts the URL/heading changed, then switches back to Anxiety before the anxiety-scoped scroll assertions. All 3 threads replied with commit SHA and resolved.", "checks": "npx vitest run tests/therapy-pathways-mobile.dom.test.tsx tests/therapy-compass-responsive-contract.test.ts tests/playwright-pr-shards.test.ts tests/therapy-compass-pathways.test.ts -- 34 passed; npm run lint -- exit 0 (gate-receipts pass); npm run typecheck -- exit 0, run foreground twice, gate-receipts recorded pass for typecheck:internal (5613 input files); npm run format -- applied (1 file reformatted, amended into commit); no provider-backed checks run" }, { @@ -4561,7 +4603,7 @@ "ref": "codex/therapy-pathways-redesign (PR #2413)", "head": "f8537abbef36b5e9f72eb1c745f565253a276153", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Before: PR required failing (Static PR checks red on check:repo-awareness-snapshot \u2014 committed data/repo-awareness-snapshot.json review_state was stale after prior sweep's ledger/docs commits); 0 unresolved review threads; branch already contained origin/main (no drift). After: ran npm run snapshot:repo-awareness to regenerate the snapshot, verified npm run check:repo-awareness-snapshot and npm run format:changed pass, committed and pushed f8537ab. All other required jobs (Build, Unit coverage, Production UI critical, Safety and config checks, Production UI shards 1-3, Lighthouse budget) were already green before this fix and untouched by it. No review threads existed to address. No main-sync needed (branch already up to date).", + "outcome": "Before: PR required failing (Static PR checks red on check:repo-awareness-snapshot — committed data/repo-awareness-snapshot.json review_state was stale after prior sweep's ledger/docs commits); 0 unresolved review threads; branch already contained origin/main (no drift). After: ran npm run snapshot:repo-awareness to regenerate the snapshot, verified npm run check:repo-awareness-snapshot and npm run format:changed pass, committed and pushed f8537ab. All other required jobs (Build, Unit coverage, Production UI critical, Safety and config checks, Production UI shards 1-3, Lighthouse budget) were already green before this fix and untouched by it. No review threads existed to address. No main-sync needed (branch already up to date).", "checks": "npm run check:repo-awareness-snapshot (PASS, reproduces prior CI failure then passes after regen); npm run format:changed (PASS); npm run snapshot:repo-awareness (regenerated data/repo-awareness-snapshot.json); no provider-backed checks run" }, { @@ -4577,7 +4619,7 @@ "ref": "ds-hazard-1-2-sweep", "head": "19ee085b1cc952e8c40e893fb2fce99538415259", "scope": "design-system", - "outcome": "Findings \u2014 0 P0/P1; 4 structural P2 (disabled-send border jump, hero leading on composer, --leading-prose on chrome, stale conventions.md per-step type scale); residuals on specifier focus ring and leftover Lucide sizes", + "outcome": "Findings — 0 P0/P1; 4 structural P2 (disabled-send border jump, hero leading on composer, --leading-prose on chrome, stale conventions.md per-step type scale); residuals on specifier focus ring and leftover Lucide sizes", "checks": "read-only origin/main...HEAD token/UI/docs inspection; ledger lookup NOT REVIEWED; no contract gate, browser, or providers" }, { @@ -4601,7 +4643,7 @@ "ref": "update_documentation_structure (PR #2444)", "head": "c619671065422373f746f69bca5f94147767f877", "scope": "PR 2444 review: main sync + CI fix + review thread", - "outcome": "before: PR policy/Static PR checks/Unit coverage failing, 1 unresolved review thread, behind main by 2 commits (clean merge). after: merged origin/main (no conflicts), regenerated docs/site-map.md to drop deleted signed-urls alias route (fixes docs:check-links + site-map.test.ts), fixed CodeRabbit Major finding \u2014 upload error-path storage_cleanup_jobs ledger now carries document_id when document deletion is not confirmed so the janitor live-document guard can protect it, added required PR-body Clinical Governance Preflight + Risk and rollout sections (fixes PR policy check). Thread resolved with fix commit reference.", + "outcome": "before: PR policy/Static PR checks/Unit coverage failing, 1 unresolved review thread, behind main by 2 commits (clean merge). after: merged origin/main (no conflicts), regenerated docs/site-map.md to drop deleted signed-urls alias route (fixes docs:check-links + site-map.test.ts), fixed CodeRabbit Major finding — upload error-path storage_cleanup_jobs ledger now carries document_id when document deletion is not confirmed so the janitor live-document guard can protect it, added required PR-body Clinical Governance Preflight + Risk and rollout sections (fixes PR policy check). Thread resolved with fix commit reference.", "checks": "npm run typecheck (clean), npm run lint (clean), npm run test:focused -- --files src/app/api/upload/route.ts (184 passed), npm run docs:check-links (passed), npm run sitemap:check (passed), npm run format (no changes needed). No provider-backed checks run." }, { @@ -4624,8 +4666,8 @@ "date": "2026-08-26", "ref": "claude/ward-flow-phase-5-p8rwcm", "head": "47b51405bf3938096411895d28a4bba351d7d050", - "scope": "Ward Flow Phase 5 \u2014 bed availability lifecycle, leave beds, discharge board, capacity bands, freshness", - "outcome": "Whole-branch review: approved with findings, 0 P0, 0 P1, 7 P2 \u2014 all seven fixed and mutation-tested. Four earlier automated findings: three fixed, one rejected with reasons.", + "scope": "Ward Flow Phase 5 — bed availability lifecycle, leave beds, discharge board, capacity bands, freshness", + "outcome": "Whole-branch review: approved with findings, 0 P0, 0 P1, 7 P2 — all seven fixed and mutation-tested. Four earlier automated findings: three fixed, one rejected with reasons.", "checks": "npm run test (3 pre-existing failures, identical on clean origin/main); npm run typecheck; npm run lint (eslint cache cleared); prettier --check on all changed files; chromium-mockups ward-management + ward-coordinator + ward-discharges; screenshots at 390/820/1440 on five screens, looked at" }, { @@ -4705,7 +4747,7 @@ "ref": "backup/pr-2333-prelinear-20260824", "head": "7c5bb84e45d6925c6950cf5b96fff3a8cc479a7b", "scope": "pr-ci-fix", - "outcome": "Fixed: prettier format:changed; PR_POLICY_BODY sync for Clinical Governance Preflight; empty commit retriggered PR Policy after body sync race. Review threads already resolved (fb8adf92). Required checks green (PR policy, Static PR, PR required). mergeStateStatus BEHIND vs moving main \u2014 merge-tree clean.", + "outcome": "Fixed: prettier format:changed; PR_POLICY_BODY sync for Clinical Governance Preflight; empty commit retriggered PR Policy after body sync race. Review threads already resolved (fb8adf92). Required checks green (PR policy, Static PR, PR required). mergeStateStatus BEHIND vs moving main — merge-tree clean.", "checks": "vitest:54/54; prettier:pass; pr-policy:pass; static-pr:pass; pr-required:pass" }, { @@ -4777,7 +4819,7 @@ "ref": "claude/browser-test-gate-handoff-d5c1db (PR #2347)", "head": "d3f5edc26b319f5feccebd628fd537855321f33c", "scope": "Run PR sweep: CI fixes (owner closed mid-sweep)", - "outcome": "Before: PR required failing (Static PR checks: stale outstanding-issues snapshot + 3 broken docs-links; PR policy: Clinical Governance Preflight unchecked) and behind main. Fixed: (1) regenerated data/outstanding-issues-snapshot.json via its generator script; (2) added 3 scoped docs-link-checker allowlist entries in scripts/check-docs-links.mjs for historical/quoted-diagnostic path references in the Phase 2B SDD archive docs (verified locally, not a broken link). Synced origin/main in (clean merge-tree) both times. Static PR checks went green after both fixes. PR policy remained red (Clinical Governance Preflight checkboxes require a PR-body edit, outside this sweep's authorization). The PR owner (BigSimmo) then closed the PR at 14:42 UTC for unrelated reasons (auto-merge armed on incomplete work; a known-false workspace-coverage claim; explained in PR comment) \u2014 not an action taken by this sweep. Both fix commits remain on the branch per the owner's own comment (nothing lost).", + "outcome": "Before: PR required failing (Static PR checks: stale outstanding-issues snapshot + 3 broken docs-links; PR policy: Clinical Governance Preflight unchecked) and behind main. Fixed: (1) regenerated data/outstanding-issues-snapshot.json via its generator script; (2) added 3 scoped docs-link-checker allowlist entries in scripts/check-docs-links.mjs for historical/quoted-diagnostic path references in the Phase 2B SDD archive docs (verified locally, not a broken link). Synced origin/main in (clean merge-tree) both times. Static PR checks went green after both fixes. PR policy remained red (Clinical Governance Preflight checkboxes require a PR-body edit, outside this sweep's authorization). The PR owner (BigSimmo) then closed the PR at 14:42 UTC for unrelated reasons (auto-merge armed on incomplete work; a known-false workspace-coverage claim; explained in PR comment) — not an action taken by this sweep. Both fix commits remain on the branch per the owner's own comment (nothing lost).", "checks": "node scripts/generate-outstanding-issues-snapshot.mjs + node scripts/check-outstanding-issues-snapshot.mjs (pass); node scripts/check-docs-links.mjs (pass, 3322 refs resolve); prettier --check scripts/check-docs-links.mjs (pass). No provider-backed checks run." }, { @@ -4785,8 +4827,8 @@ "ref": "claude/review-queue-header-design-of7baq (PR #2338)", "head": "c934541ceca611481073c4b761da98b99545b05a", "scope": "Run PR sweep: drift sync", - "outcome": "No code fix needed; branch was only behind origin/main (clean merge-tree). Merged origin/main and pushed. Both existing review threads already resolved. Remaining CI failure: PR policy blocks on missing Clinical Governance Preflight section (src/lib/mode-secondary-navigation.ts change triggers clinicalRisk) \u2014 left open, PR body edits are out of scope for this sweep.", - "checks": "npx vitest run tests/therapy-compass-pathways.test.ts tests/route-reachability.test.ts tests/therapy-compass-mode-wiring.test.ts tests/therapy-review-regressions.test.ts tests/mode-nav-contract.test.ts tests/mode-secondary-navigation.test.ts tests/therapy-compass-responsive-contract.test.ts \u2014 113 passed; no provider-backed checks run" + "outcome": "No code fix needed; branch was only behind origin/main (clean merge-tree). Merged origin/main and pushed. Both existing review threads already resolved. Remaining CI failure: PR policy blocks on missing Clinical Governance Preflight section (src/lib/mode-secondary-navigation.ts change triggers clinicalRisk) — left open, PR body edits are out of scope for this sweep.", + "checks": "npx vitest run tests/therapy-compass-pathways.test.ts tests/route-reachability.test.ts tests/therapy-compass-mode-wiring.test.ts tests/therapy-review-regressions.test.ts tests/mode-nav-contract.test.ts tests/mode-secondary-navigation.test.ts tests/therapy-compass-responsive-contract.test.ts — 113 passed; no provider-backed checks run" }, { "date": "2026-08-24", @@ -4794,7 +4836,7 @@ "head": "6ef5b3617956ba8e0a4fa69a1953ec51cba1336f", "scope": "Run PR sweep: branch sync", "outcome": "Already fully green (PR required success) before sweep; only action was syncing origin/main in (clean merge-tree, no conflicts) via update_pull_request_branch. All 5 review threads were already resolved by the author. Post-sync CI reconfirmed green (PR required success at run 32741127269).", - "checks": "No local gates run \u2014 no code change, only a merge-from-main sync; CI (Static PR checks, Lint, Typecheck, Unit coverage, Build, Production UI x3, Production UI critical, Lighthouse budget, PR policy, PR required) reran green on GitHub. No provider-backed checks run." + "checks": "No local gates run — no code change, only a merge-from-main sync; CI (Static PR checks, Lint, Typecheck, Unit coverage, Build, Production UI x3, Production UI critical, Lighthouse budget, PR policy, PR required) reran green on GitHub. No provider-backed checks run." }, { "date": "2026-08-24", @@ -4826,23 +4868,23 @@ "head": "1683edfbd66d2e13bee9f7e533e87218ea9237d8", "scope": "Run PR sweep: main sync + conflict resolution", "outcome": "Before: draft mockup PR reported mergeable_state=dirty. git merge-tree confirmed a real conflict, isolated to generated docs/site-map.md (plus a clean auto-merge in src/app/mockups/mockups-layout-client.tsx). No failing CI, no unresolved review threads. Fix: merged origin/main in an isolated worktree, kept ours for site-map.md then regenerated it via npm run sitemap:update (pre-commit doc-sync hook ran clean), pushed the merge commit. After: mergeable_state=blocked pending checks then PR required green at 1683edfb.", - "checks": "npx vitest run tests/answer-chat-redesign-mockups.test.ts tests/answer-chat-redesign-mockups.dom.test.tsx \u2014 2 files, 7 passed. CI (hosted): PR required success at 1683edfb. No provider-backed checks run." + "checks": "npx vitest run tests/answer-chat-redesign-mockups.test.ts tests/answer-chat-redesign-mockups.dom.test.tsx — 2 files, 7 passed. CI (hosted): PR required success at 1683edfb. No provider-backed checks run." }, { "date": "2026-08-24", "ref": "cursor/calculators-show-all-mockups-7ce3 (PR #2337)", "head": "ff09c24260e2616b7b7c7bb12e19572aa03fba85", "scope": "Run PR sweep: CI fix", - "outcome": "Fixed real CI failure: Static PR checks failed on check:design-system-contract arbitraryTracking ratchet \u2014 tracking-[-0.01em] in show-all-chip.tsx switched to the sanctioned tracking-[var(--tracking-display)] token (folds per globals.css letterspacing scale doc). Branch was not behind main (0 behind). Sole open review thread already resolved; no unresolved threads found. PR title/body/head changed mid-sweep via a concurrent author push (Cursor cloud agent) before this fix; re-verified against the latest head before pushing.", - "checks": "npm run check:design-system-contract \u2014 pass (arbitrary tracking 0); npx vitest run tests/calculators-mode.dom.test.tsx tests/consolidated-mode-home-redirect.test.ts tests/favourites-auth-gate.dom.test.tsx tests/calculators-show-all-mockups.dom.test.tsx \u2014 48 passed; npx eslint on changed file \u2014 clean; no provider-backed checks run" + "outcome": "Fixed real CI failure: Static PR checks failed on check:design-system-contract arbitraryTracking ratchet — tracking-[-0.01em] in show-all-chip.tsx switched to the sanctioned tracking-[var(--tracking-display)] token (folds per globals.css letterspacing scale doc). Branch was not behind main (0 behind). Sole open review thread already resolved; no unresolved threads found. PR title/body/head changed mid-sweep via a concurrent author push (Cursor cloud agent) before this fix; re-verified against the latest head before pushing.", + "checks": "npm run check:design-system-contract — pass (arbitrary tracking 0); npx vitest run tests/calculators-mode.dom.test.tsx tests/consolidated-mode-home-redirect.test.ts tests/favourites-auth-gate.dom.test.tsx tests/calculators-show-all-mockups.dom.test.tsx — 48 passed; npx eslint on changed file — clean; no provider-backed checks run" }, { "date": "2026-08-24", "ref": "cursor/dictionary-control-row-polish-4ee0 (PR #2316)", "head": "090c5f274e293fa5209cff6fa1565e2e50fa3c6d", "scope": "Run PR sweep: main sync", - "outcome": "Before: ready-for-review PR behind main (mergeable_state=behind); 2 review threads present, both already resolved (P1 alignment finding fixed in e475f236/5498f030; CodeRabbit letter-chip tap-target finding fixed in 6de85d94) \u2014 no unresolved threads, no new actionable comments. Synced via update_pull_request_branch (clean fast-forward merge of origin/main, no conflicts). After: mergeable_state=blocked pending checks then PR required green at 090c5f27 (all 13 constituent jobs incl. Unit coverage, Build, 3x Production UI, Lighthouse, Static PR checks succeeded).", - "checks": "CI (hosted): PR required success at 090c5f27. No local gate run \u2014 sync-only, no source files changed by the sweep. No provider-backed checks run." + "outcome": "Before: ready-for-review PR behind main (mergeable_state=behind); 2 review threads present, both already resolved (P1 alignment finding fixed in e475f236/5498f030; CodeRabbit letter-chip tap-target finding fixed in 6de85d94) — no unresolved threads, no new actionable comments. Synced via update_pull_request_branch (clean fast-forward merge of origin/main, no conflicts). After: mergeable_state=blocked pending checks then PR required green at 090c5f27 (all 13 constituent jobs incl. Unit coverage, Build, 3x Production UI, Lighthouse, Static PR checks succeeded).", + "checks": "CI (hosted): PR required success at 090c5f27. No local gate run — sync-only, no source files changed by the sweep. No provider-backed checks run." }, { "date": "2026-08-24", @@ -4850,23 +4892,23 @@ "head": "271e506d6e3ca024a9bfefae51c99dc9f669ec93", "scope": "Run PR sweep: main sync", "outcome": "Before: draft mockup PR behind main (mergeable_state=behind), no failing CI, no unresolved review threads. Synced via update_pull_request_branch (clean fast-forward merge of origin/main, no conflicts). After: mergeable_state=clean, latest CI run green (PR required: success).", - "checks": "CI (hosted): PR required success at 271e506d. No local gate run \u2014 sync-only, no source files changed by the sweep. No provider-backed checks run." + "checks": "CI (hosted): PR required success at 271e506d. No local gate run — sync-only, no source files changed by the sweep. No provider-backed checks run." }, { "date": "2026-08-24", "ref": "cursor/dictionary-persistent-filter-band-4ee0 (PR #2341)", "head": "cc99fef611bcb3ed4d7bb2b79434a136b8f61c99", "scope": "Run PR sweep: CI diagnosis + drift sync", - "outcome": "Before: PR required failing (Production UI shard 3 red on an unrelated differentials-compare-queue test); behind main. Diagnosed via job log: failure was in tests/ui-tools.spec.ts differentials compare queue test, unrelated to this PR's dictionary-only diff. Re-ran the failed job on the pre-sync head \u2014 it passed, confirming flake not regression. Synced origin/main in (clean merge-tree) via update_pull_request_branch. Post-sync full CI green (PR required success at run 32741127269). All 4 review threads were already resolved by the author before the sweep; none required action.", - "checks": "No local code changes and no local gates run for this PR \u2014 root cause was CI-side (rerun) and branch drift (sync), both diagnosed/fixed via GitHub. No provider-backed checks run." + "outcome": "Before: PR required failing (Production UI shard 3 red on an unrelated differentials-compare-queue test); behind main. Diagnosed via job log: failure was in tests/ui-tools.spec.ts differentials compare queue test, unrelated to this PR's dictionary-only diff. Re-ran the failed job on the pre-sync head — it passed, confirming flake not regression. Synced origin/main in (clean merge-tree) via update_pull_request_branch. Post-sync full CI green (PR required success at run 32741127269). All 4 review threads were already resolved by the author before the sweep; none required action.", + "checks": "No local code changes and no local gates run for this PR — root cause was CI-side (rerun) and branch drift (sync), both diagnosed/fixed via GitHub. No provider-backed checks run." }, { "date": "2026-08-24", "ref": "cursor/factsheets-topics-page-ec19 (PR #2333)", "head": "7fe94b6198fb8b78674b0b423be57851704f86c7", "scope": "Run PR sweep: CI fix + drift sync", - "outcome": "Fixed real CI failure: legacyTapClasses (h-11/w-11) in factsheets-topics-browse.tsx bumped to h-12/w-12; merged origin/main (clean); a concurrent upstream push (b2c23389d) then rewrote the same component, resolved by merge taking upstream's version (no more -11 class) and regenerating COMPONENTS.md. 4 review threads already resolved, none new. Remaining CI failure: PR policy blocks on missing Clinical Governance Preflight section (src/lib/mode-secondary-navigation.ts triggers clinicalRisk) \u2014 left open, PR body edits are out of scope for this sweep.", - "checks": "npm run check:design-system-contract (incl. design-system-adoption, design-sync-contract) \u2014 pass; npx vitest run tests/factsheets-topics-page.dom.test.tsx tests/factsheets-topics-phone-mockups.test.ts tests/factsheets-data.test.ts tests/design-system-adoption.test.ts tests/mode-secondary-navigation.test.ts \u2014 109 passed; npx eslint on changed file \u2014 clean; no provider-backed checks run" + "outcome": "Fixed real CI failure: legacyTapClasses (h-11/w-11) in factsheets-topics-browse.tsx bumped to h-12/w-12; merged origin/main (clean); a concurrent upstream push (b2c23389d) then rewrote the same component, resolved by merge taking upstream's version (no more -11 class) and regenerating COMPONENTS.md. 4 review threads already resolved, none new. Remaining CI failure: PR policy blocks on missing Clinical Governance Preflight section (src/lib/mode-secondary-navigation.ts triggers clinicalRisk) — left open, PR body edits are out of scope for this sweep.", + "checks": "npm run check:design-system-contract (incl. design-system-adoption, design-sync-contract) — pass; npx vitest run tests/factsheets-topics-page.dom.test.tsx tests/factsheets-topics-phone-mockups.test.ts tests/factsheets-data.test.ts tests/design-system-adoption.test.ts tests/mode-secondary-navigation.test.ts — 109 passed; npx eslint on changed file — clean; no provider-backed checks run" }, { "date": "2026-08-24", @@ -5017,7 +5059,7 @@ "ref": "claude/ed-care-plans-impl-7f44cd (PR #2291)", "head": "620743d434dfcc158811720ca53d09caf9c4b750", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Before: mergeable_state dirty (main-sync merge conflict never attempted \u2014 hard-stopped and reported per clinical-content-conflict policy since the PR branch and main both independently built the care-plan feature after PR #2274 landed), PR mergeability + PR policy both failing, 0 of 6 unresolved P1 review threads addressed, real CI (pr-required) never triggered. After: PR owner (BigSimmo) resolved the main-sync merge conflict live and independently fixed all 6 P1 Codex findings on the branch while this sweep was in progress; this session's own independent fixes for the same 6 findings were reconciled against the owner's landed versions (kept the owner's naming/implementation where duplicated, kept this session's unique patient-plan-print-stale-in-subtree fix which the owner's merge did not touch, removed this session's now-dead-code duplicate blocks e.g. two near-identical withdrawal stale-trigger blocks and two approve-patient-plan-version refusal blocks left by concurrent independent 3-way merges, added 3 new regression tests). mergeable_state now blocked (not dirty) \u2014 no more content conflict. PR mergeability: success. PR policy: still failing (only blocker: PR body Clinical Governance Preflight all 7 boxes unchecked plus advisory warnings on blank Summary/Verification/Risk sections \u2014 PR body left untouched per this sweep's explicit instruction not to edit it). Real CI (pr-required aggregate) triggered for the first time on this PR and was still in progress after 25 minutes of observation (Build, Unit coverage, Static PR checks, Production UI x4, Advisory UI, Lighthouse budget all in_progress; Change scope/Gitleaks/Semgrep/Safety and config checks/GitGuardian all green) \u2014 not yet settled at end of this sweep's observation window. All 6 review threads already resolved by BigSimmo before this session's push landed; nothing left to reply/resolve. 3 commits pushed: 61c6b562 (own fixes), 70e700db (merge #1, resolving owner's first live main-sync push), 620743d4 (merge #2, resolving owner's second live push that independently fixed the exact same contact-guard finding).", + "outcome": "Before: mergeable_state dirty (main-sync merge conflict never attempted — hard-stopped and reported per clinical-content-conflict policy since the PR branch and main both independently built the care-plan feature after PR #2274 landed), PR mergeability + PR policy both failing, 0 of 6 unresolved P1 review threads addressed, real CI (pr-required) never triggered. After: PR owner (BigSimmo) resolved the main-sync merge conflict live and independently fixed all 6 P1 Codex findings on the branch while this sweep was in progress; this session's own independent fixes for the same 6 findings were reconciled against the owner's landed versions (kept the owner's naming/implementation where duplicated, kept this session's unique patient-plan-print-stale-in-subtree fix which the owner's merge did not touch, removed this session's now-dead-code duplicate blocks e.g. two near-identical withdrawal stale-trigger blocks and two approve-patient-plan-version refusal blocks left by concurrent independent 3-way merges, added 3 new regression tests). mergeable_state now blocked (not dirty) — no more content conflict. PR mergeability: success. PR policy: still failing (only blocker: PR body Clinical Governance Preflight all 7 boxes unchecked plus advisory warnings on blank Summary/Verification/Risk sections — PR body left untouched per this sweep's explicit instruction not to edit it). Real CI (pr-required aggregate) triggered for the first time on this PR and was still in progress after 25 minutes of observation (Build, Unit coverage, Static PR checks, Production UI x4, Advisory UI, Lighthouse budget all in_progress; Change scope/Gitleaks/Semgrep/Safety and config checks/GitGuardian all green) — not yet settled at end of this sweep's observation window. All 6 review threads already resolved by BigSimmo before this session's push landed; nothing left to reply/resolve. 3 commits pushed: 61c6b562 (own fixes), 70e700db (merge #1, resolving owner's first live main-sync push), 620743d4 (merge #2, resolving owner's second live push that independently fixed the exact same contact-guard finding).", "checks": "Local only, no provider-backed checks run: npm run typecheck (clean, 4695 files), npm run lint (clean, 4695 files), node scripts/run-vitest.mjs run tests/care-plan-patient-plan.test.ts tests/care-plan-linked-routes.dom.test.tsx tests/care-plan-prototype-state.test.ts tests/care-plan-domain.test.ts tests/care-plan-route-files.test.ts (440 passed), npm run test full suite (8476 passed, 1 skipped, 1 unrelated pre-existing async-timer-after-teardown flake in caring-contact-shell-frame.tsx unrelated to this diff), npx prettier --check on touched files (clean). No eval:rag, eval:quality, eval:retrieval:quality, verify:release, check:supabase-project, or test:live run." }, { @@ -5025,15 +5067,15 @@ "ref": "claude/post-drift-ledger-tidy", "head": "5ff3f0419d6696f59eb638cfbbf4f28c2f964ba6", "scope": "post-drift ledger tidying: close #M54C4N/#056/#3514B7, re-scope #47M1XD, escalate #M6JNR8; read-only staging+production verification", - "outcome": "pass \u2014 three rows closed with quoted evidence (live-drift run 32514326022; staging 211-row parity), #47M1XD advanced with a second production window that strengthened the zero-scan retraction and showed the proposed ANALYZE experiment cannot discriminate (n_mod_since_analyze=0 on four of five tables); owner chose to skip ANALYZE so no production mutation. #231 queue row could NOT be corrected: hand edit and same-PR reconcile both empirically refused by check:ledger-write-discipline, escalated as #M6JNR8 P1", + "outcome": "pass — three rows closed with quoted evidence (live-drift run 32514326022; staging 211-row parity), #47M1XD advanced with a second production window that strengthened the zero-scan retraction and showed the proposed ANALYZE experiment cannot discriminate (n_mod_since_analyze=0 on four of five tables); owner chose to skip ANALYZE so no production mutation. #231 queue row could NOT be corrected: hand edit and same-PR reconcile both empirically refused by check:ledger-write-discipline, escalated as #M6JNR8 P1", "checks": "check:ledger-write-discipline, check:outstanding-issues, check:branch-review-ledger, prettier --check on changed files" }, { "date": "2026-08-22", "ref": "claude/rag-quality-predicate-gap-uw320a", "head": "957b76afa20c4b4667f41cbb0725d71482171228", - "scope": "Packet 2 (#NPQJKP): answer-quality predicate gap \u2014 src/lib/rag/rag-extractive-answer.ts, tests/rag-guidance-wrapper-quality-gate.test.ts, docs/rag-improvement/HANDOVER.md pointer line", - "outcome": "SHIPPED as PR #2285 (draft). Falsification confirmed the premise first: generatedAnswerQualityFailureReason returned null for both captured incoherent answers at their real query classes (medication_dose_risk, document_lookup) against unmodified source. Two corrections to the recorded diagnosis: (1) the gate is NOT unreachable on the grounded extractive path \u2014 the enforcing call is unconditional inside finalizeRagAnswerQualityCore, reached via finalizeAnswer, so NO reachability change was made; only the preformatted-and-grounded early return remains as a bypass and is now pinned by test. (2) the wrapper is not purely laundering \u2014 a first predicate keyed on openingSentenceActionPattern broke the ECT 'places the patient onto BASE' answer pinned by rag-extractive-procedural-artifact, so the shipped predicate rejects only a '>' breadcrumb aimed at a word and a bare coordinated noun list. Placed after the other prose gates so nothing is relabelled; outside the shouldPreserveSourceBackedGeneratedAnswer rescue allowlist. NO ranking, selection, retrieval, prompt or budget change; answerRouteBudgetMs untouched. Live eval-canary pair still owed under owner approval.", + "scope": "Packet 2 (#NPQJKP): answer-quality predicate gap — src/lib/rag/rag-extractive-answer.ts, tests/rag-guidance-wrapper-quality-gate.test.ts, docs/rag-improvement/HANDOVER.md pointer line", + "outcome": "SHIPPED as PR #2285 (draft). Falsification confirmed the premise first: generatedAnswerQualityFailureReason returned null for both captured incoherent answers at their real query classes (medication_dose_risk, document_lookup) against unmodified source. Two corrections to the recorded diagnosis: (1) the gate is NOT unreachable on the grounded extractive path — the enforcing call is unconditional inside finalizeRagAnswerQualityCore, reached via finalizeAnswer, so NO reachability change was made; only the preformatted-and-grounded early return remains as a bypass and is now pinned by test. (2) the wrapper is not purely laundering — a first predicate keyed on openingSentenceActionPattern broke the ECT 'places the patient onto BASE' answer pinned by rag-extractive-procedural-artifact, so the shipped predicate rejects only a '>' breadcrumb aimed at a word and a bare coordinated noun list. Placed after the other prose gates so nothing is relabelled; outside the shouldPreserveSourceBackedGeneratedAnswer rescue allowlist. NO ranking, selection, retrieval, prompt or budget change; answerRouteBudgetMs untouched. Live eval-canary pair still owed under owner approval.", "checks": "verify:pr-local exit 0, all 19 gates completed / none failed (lint, typecheck, test, build, eval:rag:offline, eval:rag:adversarial:offline); a concurrent second invocation exited 75 DATABASE_HEAVY_RUN_ADMISSION_BUSY on self-inflicted lease contention, and a later confirmation re-run hit a PRE-EXISTING unrelated flake (ReferenceError: document is not defined from a 250ms setTimeout in src/components/caring-contacts/mockups/caring-contact-shell-frame.tsx:104 firing after jsdom teardown; 714 files / 8359 tests still passed). typecheck:internal exit 0 on the committed tree. Focused 300/300 across the seven suites exercising this predicate. eval:rag:offline 627/627 and eval:rag:adversarial:offline 25/25, identical before and after with the baseline re-run under GATE_RECEIPTS=refresh. No provider-backed command run; no canary dispatched." }, { @@ -5185,8 +5227,8 @@ "ref": "codex/ward-management-design (PR #2289)", "head": "6e1300fa6dcb31ba63727b9d5b3b52cab0b05cb5", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Before: mergeable_state dirty (PR mergeability + PR policy both failing; real CI never triggered), 3 unresolved P1 review threads. After: all 6 review threads resolved (3 fixed with regression tests + pushed commit 6e1300fa; 3 pre-existing already resolved). mergeable_state remains dirty and was deliberately left unresolved: git merge-tree shows 34 conflicts (14 content, 20 add/add) against origin/main, all traced to PR #2140 (\"Add Ward Flow: synthetic ward/bed-management coordination prototype\", already merged to main) independently re-implementing the same ward-management/legal-detention-workflow feature this PR builds from a much older, unrelated base (zero common history until git fetch --deepen=5000 recovered a real merge-base 752 commits back). This is a genuine duplicate-feature conflict on clinical workflow content (Mental Health Act detention forms, bed/patient placement), not staleness \u2014 hard-stopped per policy rather than resolved with ours/theirs. Real CI (static-pr/pr-required/build/etc.) cannot run until a human resolves this at the product level.", - "checks": "Local only, no provider-backed checks: npx vitest run on 9 touched/related ward-flow test files (84 passed, including 2 new regression tests \u2014 one for the reducer closure/capacity-release fix, one for the provider clock-monotonicity fix, both confirmed to fail against pre-fix code), npx tsc --noEmit -p tsconfig.json (0 errors, full project), npx eslint on all 6 changed files (0 findings), npx prettier --check on all 6 changed files (all formatted). No verify:cheap/verify:pr-local/verify:ui run (diff too large and blocked on unrelated merge conflict; would not have exercised anything beyond the focused tests already run). No eval:rag, eval:quality, eval:retrieval:quality, verify:release, check:supabase-project, test:live, or any other provider-backed gate was run." + "outcome": "Before: mergeable_state dirty (PR mergeability + PR policy both failing; real CI never triggered), 3 unresolved P1 review threads. After: all 6 review threads resolved (3 fixed with regression tests + pushed commit 6e1300fa; 3 pre-existing already resolved). mergeable_state remains dirty and was deliberately left unresolved: git merge-tree shows 34 conflicts (14 content, 20 add/add) against origin/main, all traced to PR #2140 (\"Add Ward Flow: synthetic ward/bed-management coordination prototype\", already merged to main) independently re-implementing the same ward-management/legal-detention-workflow feature this PR builds from a much older, unrelated base (zero common history until git fetch --deepen=5000 recovered a real merge-base 752 commits back). This is a genuine duplicate-feature conflict on clinical workflow content (Mental Health Act detention forms, bed/patient placement), not staleness — hard-stopped per policy rather than resolved with ours/theirs. Real CI (static-pr/pr-required/build/etc.) cannot run until a human resolves this at the product level.", + "checks": "Local only, no provider-backed checks: npx vitest run on 9 touched/related ward-flow test files (84 passed, including 2 new regression tests — one for the reducer closure/capacity-release fix, one for the provider clock-monotonicity fix, both confirmed to fail against pre-fix code), npx tsc --noEmit -p tsconfig.json (0 errors, full project), npx eslint on all 6 changed files (0 findings), npx prettier --check on all 6 changed files (all formatted). No verify:cheap/verify:pr-local/verify:ui run (diff too large and blocked on unrelated merge conflict; would not have exercised anything beyond the focused tests already run). No eval:rag, eval:quality, eval:retrieval:quality, verify:release, check:supabase-project, test:live, or any other provider-backed gate was run." }, { "date": "2026-08-22", @@ -5361,7 +5403,7 @@ "ref": "claude/auto-close-next-servers-7ymzsx", "head": "fbeb67c2e4f8a7e144d790bd3c94129b9c95cf4f", "scope": "scripts/dev-free-port.mjs, scripts/ensure-local-server.mjs, src/lib/local-server-utils.mjs, tests/local-server-utils.test.ts, README.md", - "outcome": "approved \u2014 self-authored PR #2212, idle-timeout self-shutdown for ensure-started background dev servers", + "outcome": "approved — self-authored PR #2212, idle-timeout self-shutdown for ensure-started background dev servers", "checks": "eslint (clean), vitest tests/local-server-utils.test.ts (5 passed), prettier --check . (clean), manual smoke test of idle shutdown against a real next dev boot" }, { @@ -5369,23 +5411,23 @@ "ref": "claude/clever-bohr-w87uiz", "head": "0fcd789a8625f1abfe120cd1a274166948537d71", "scope": "Claude Code web container parity, code half of the PR #2227 split: tiered provisioner, cloud-profile applier, CLAUDE.md/settings/memory snapshot, SessionStart registration, contract doc, 18 tests", - "outcome": "PR #2236 opened (draft), replacing #2227. Vendored skill tree moved to PR #2238 so this diff is 28 files instead of 543; CodeRabbit's 150-file limit is why #2227 received no automated review at all. The applier already guarded skills on existsSync; the test file now states which assertions need the tree and a new test pins that guard, so this PR stands alone. Container tiers plugins/gh/deno/browsers/python remain unexecuted anywhere \u2014 no Linux container was available to run them in, and the first real cloud session is the acceptance test", + "outcome": "PR #2236 opened (draft), replacing #2227. Vendored skill tree moved to PR #2238 so this diff is 28 files instead of 543; CodeRabbit's 150-file limit is why #2227 received no automated review at all. The applier already guarded skills on existsSync; the test file now states which assertions need the tree and a new test pins that guard, so this PR stands alone. Container tiers plugins/gh/deno/browsers/python remain unexecuted anywhere — no Linux container was available to run them in, and the first real cloud session is the acceptance test", "checks": "lint gate-receipts pass 3950 files, typecheck gate-receipts pass 3950 files, npm run test full offline suite 697 files 7694 passed 6 skipped exit 0, vitest tests/claude-cloud-profile.test.ts 16 passed 2 skipped without the tree and 18 passed with it, format:changed whole-tree escalation all files pass, docs:update no drift 254 scripts 255 npm scripts, docs:check-links 2082 refs resolve, check:branch-review-ledger pass, git merge-tree against the #2238 branch exit 0 no conflict" }, { "date": "2026-08-21", "ref": "claude/clever-bohr-w87uiz", "head": "5d4aedb86809debbc277f534eae35fe015e9f5a1", - "scope": "tests/claude-cloud-profile.test.ts \u2014 sandbox HOME for every provisioner spawn so the suite stops reading the machine's real marker/lock directory", + "scope": "tests/claude-cloud-profile.test.ts — sandbox HOME for every provisioner spawn so the suite stops reading the machine's real marker/lock directory", "outcome": "Fixes a false red that landed via PR #2236: the held-lock test planted its fixture in the real ~/.cache/clinical-kb-claude-cloud, so a completed-tier marker short-circuited the deno tier before the code under test ran. Failed on any provisioned container, passed on CI's clean runners, which is how it reached main. HOME override suffices because the provisioner is a shell script; the applier still needs CLAUDE_CONFIG_DIR for the Windows os.homedir() reason. No production code changed. Adds a guard test pinning the isolation", - "checks": "vitest tests/claude-cloud-profile.test.ts in all three states with a real deno.marker on the container \u2014 before 1 failed 22 passed, after with marker present 24 passed, after with marker absent 24 passed; full offline suite 695 files 7726 passed 1 skipped exit 0; lint gate-receipts pass 4365 files; typecheck gate-receipts pass 4365 files; format:changed all files pass" + "checks": "vitest tests/claude-cloud-profile.test.ts in all three states with a real deno.marker on the container — before 1 failed 22 passed, after with marker present 24 passed, after with marker absent 24 passed; full offline suite 695 files 7726 passed 1 skipped exit 0; lint gate-receipts pass 4365 files; typecheck gate-receipts pass 4365 files; format:changed all files pass" }, { "date": "2026-08-21", "ref": "claude/frontend-design-6sl1ft", "head": "8b26a5c4ce836db00e031e2ad3ee3980e8a9d1a9", "scope": "design-review remediation + loose ends + nested-mockup CI scope routing", - "outcome": "applied \u2014 20 review findings resolved or dispositioned, 5 loose ends closed, 1 CI scope gap fixed; 3 architectural items recorded as decisions in TOKENS.md \u00a79 / COMPONENTS.md \u00a70.4", + "outcome": "applied — 20 review findings resolved or dispositioned, 5 loose ends closed, 1 CI scope gap fixed; 3 architectural items recorded as decisions in TOKENS.md §9 / COMPONENTS.md §0.4", "checks": "verify:pr-local exit 0 (28/28 gates after CI-scope widening; 7599 tests passed, 4 skipped, 0 errors; build ok); full suite green with no gh CLI; verify:ui delegated to CI Production UI (playwright revision drift #255, and heavy jobs are draft-gated)" }, { @@ -5393,7 +5435,7 @@ "ref": "claude/frontend-design-6sl1ft", "head": "ca7b187ae74991d3135437c79c8cc41e8db1e567", "scope": "prlanded", - "outcome": "landed clean \u2014 PR #2210 merged 2026-08-21T11:07:02Z by BigSimmo via merge commit ca7b187 (merge method 'merge', not squash); content diff ca7b187..3dde98d empty, 0 of 11 commits orphaned, remote branch auto-deleted", + "outcome": "landed clean — PR #2210 merged 2026-08-21T11:07:02Z by BigSimmo via merge commit ca7b187 (merge method 'merge', not squash); content diff ca7b187..3dde98d empty, 0 of 11 commits orphaned, remote branch auto-deleted", "checks": "git diff --stat ca7b187 3dde98d empty; per-commit ancestry 11/11 reachable from origin/main; final CI green incl. Production UI (1)(2)(3), Production UI critical, Advisory UI, Unit coverage, Build, Static PR checks; Lighthouse mobile-root CLS confirmed as the documented bistable 0.016/0.223 flake, not a diff regression" }, { @@ -5401,7 +5443,7 @@ "ref": "claude/frontend-design-6sl1ft", "head": "eaae8bde3066749f105233c1492d6f044671b91b", "scope": "full-frontend design review remediation: tokens, ward a11y, answer support label, gate gaps", - "outcome": "applied \u2014 20 review findings resolved or dispositioned; 3 architectural items deliberately deferred", + "outcome": "applied — 20 review findings resolved or dispositioned; 3 architectural items deliberately deferred", "checks": "verify:pr-local exit 0 (19/19 gates; 7599 tests passed, 4 skipped, 0 errors; build 1871 pages); verify:ui delegated to CI Production UI (playwright revision drift #255)" }, { @@ -5416,9 +5458,9 @@ "date": "2026-08-21", "ref": "claude/gate-e-verdict-record", "head": "be62c06371039cafec9f4504ca696d1ad2c67be1", - "scope": "docs/rag-improvement/HANDOVER.md \u2014 Gate E blinded-read verdict recorded in the S2 and Gate E rows", + "scope": "docs/rag-improvement/HANDOVER.md — Gate E blinded-read verdict recorded in the S2 and Gate E rows", "outcome": "Docs-only. Owner blinded read complete: v18 4ea310e48 3 / v19 cdfcbaccd 3 / tie 24 / neither 0 across 30 pairs; recorded with its three caveats (after-half is cdfcbaccd not current main; 24/30 pairs byte-identical and v18 20/30 vs v19 21/30 source_only so the tally partly measures the #231 fallback rate; baseline-record section 4 readability confound). #E0N0QC was already resolved on main at 1cc0d2987 by a separate fix, so no ledger close was queued.", - "checks": "verify:pr-local docs scope \u2014 completed check:runtime, check:installed-lock-parity, format:changed, sitemap:check, docs:check-index, docs:check-inventory, docs:check-scripts, docs:check-links, check:branch-review-ledger, check:outstanding-issues, check:ledger-write-discipline; failed: (none); not reached: (none)" + "checks": "verify:pr-local docs scope — completed check:runtime, check:installed-lock-parity, format:changed, sitemap:check, docs:check-index, docs:check-inventory, docs:check-scripts, docs:check-links, check:branch-review-ledger, check:outstanding-issues, check:ledger-write-discipline; failed: (none); not reached: (none)" }, { "date": "2026-08-21", @@ -5426,15 +5468,15 @@ "head": "9d8a03f1ea8f7ff00b5a9766476593c0271315db", "scope": "prlanded", "outcome": "merged clean, content diff empty, no orphaned commits", - "checks": "PR required, Static PR checks, PR policy, PR mergeability, Change scope, Gitleaks, Semgrep, GitGuardian \u2014 all green on head" + "checks": "PR required, Static PR checks, PR policy, PR mergeability, Change scope, Gitleaks, Semgrep, GitGuardian — all green on head" }, { "date": "2026-08-21", "ref": "claude/issues-reconcile-post-2206", "head": "02d1bcaab01f933b8af3eefa3a7f085e95aac661", "scope": "docs(issues): reconcile the queued inbox batch into the canonical ledger (#2218)", - "outcome": "Backfilled record \u2014 PR #2218 merged 2026-08-21 (squash 02d1bcaab01f933b8af3eefa3a7f085e95aac661) with no review record captured at the time. Diff inspected post hoc: 29 immutable inbox requests applied verbatim into docs/outstanding-issues.md plus 2 closures (#VZN8G3 dup of #BSBE9B, #Q5JHBJ archived) verified against the ledger by the PR author; docs-only, classifyPullRequestFiles clinicalRisk:false, no RAG/src/worker/supabase paths touched. Approved by content.", - "checks": "PR-reported: reconciler applied 29/29 requests cleanly; pre-push guard ran check:ledger-write-discipline on pushed commit 42dc0e0f4 with no rejection; Prettier clean on changed markdown; CI static-pr required checks green (merged). Not independently re-run in this session \u2014 docs-truth backfill only." + "outcome": "Backfilled record — PR #2218 merged 2026-08-21 (squash 02d1bcaab01f933b8af3eefa3a7f085e95aac661) with no review record captured at the time. Diff inspected post hoc: 29 immutable inbox requests applied verbatim into docs/outstanding-issues.md plus 2 closures (#VZN8G3 dup of #BSBE9B, #Q5JHBJ archived) verified against the ledger by the PR author; docs-only, classifyPullRequestFiles clinicalRisk:false, no RAG/src/worker/supabase paths touched. Approved by content.", + "checks": "PR-reported: reconciler applied 29/29 requests cleanly; pre-push guard ran check:ledger-write-discipline on pushed commit 42dc0e0f4 with no rejection; Prettier clean on changed markdown; CI static-pr required checks green (merged). Not independently re-run in this session — docs-truth backfill only." }, { "date": "2026-08-21", @@ -5482,7 +5524,7 @@ "head": "653712cbeda0059979e71131e828241f921f17da", "scope": "PR #2250 review-thread sweep: Codex P1/P2 + CodeRabbit findings on the Phase 5 close-out docs and ledger inbox", "outcome": "Fixed and resolved. P1 db-push contradiction removed (db push reserved for authorised staging/recovery); plan-flip and index-units deliverables left explicitly OPEN; never-reset claim qualified to database-wide only; Perth/UTC boundary made explicit; four MD040 fences labelled. Supersedes the c3ca68fa record, whose checks cell compressed the gate output.", - "checks": "verify:pr-local decisive line \u2014 \"PR-local verification summary: - completed: check:runtime, check:installed-lock-parity, format:changed, sitemap:check, docs:check-index, docs:check-inventory, docs:check-scripts, docs:check-links, check:branch-review-ledger, check:outstanding-issues, check:ledger-write-discipline / - failed: (none) / - not reached: (none)\"; format (whole tree, committed)" + "checks": "verify:pr-local decisive line — \"PR-local verification summary: - completed: check:runtime, check:installed-lock-parity, format:changed, sitemap:check, docs:check-index, docs:check-inventory, docs:check-scripts, docs:check-links, check:branch-review-ledger, check:outstanding-issues, check:ledger-write-discipline / - failed: (none) / - not reached: (none)\"; format (whole tree, committed)" }, { "date": "2026-08-21", @@ -5497,8 +5539,8 @@ "ref": "claude/phase-5-closeout", "head": "c3ca68fa7f13e2d7ae6c4c96ccfcafb67a59135a", "scope": "Phase 5 close-out: measurement baselines, staging parity, D4 documentation correction (#316) (supersedes 2026-08-21)", - "outcome": "Supersedes the 2026-08-21 record for the same head. No finding changed: the review outcome stands as self-review with no blocking findings. This record exists solely to satisfy the AGENTS.md rule that evidence is never compressed \u2014 the prior record summarised verify:pr-local as `(11/11, failed: none)`, which paraphrases rather than pastes the gate's decisive line. Raised by CodeRabbit on PR #2250 (comment 3833079990) and accepted. Records are immutable and content-addressed, so the correction is made by appending this superseding record rather than editing the original, per the review-ledger contract.", - "checks": "verify:pr-local \u2014 decisive output verbatim: `- completed: check:runtime, check:installed-lock-parity, format:changed, sitemap:check, docs:check-index, docs:check-inventory, docs:check-scripts, docs:check-links, check:branch-review-ledger, check:outstanding-issues, check:ledger-write-discipline` / `- failed: (none)` / `- not reached: (none)`. check:production-readiness \u2014 `READY: no blocking production-readiness failures.` with `PASS (9)` and `Project: Clinical KB Database (sjrfecxgysukkwxsowpy)`. check:ledger-write-discipline \u2014 `Ledger write discipline passed for 70a050752f97..HEAD.` check:outstanding-issues \u2014 `Outstanding-issues guard passed: 423 rows (67 open, 356 archived)`. format \u2014 whole tree via `npm run format`, result committed before push. live-drift run 32514326022 (workflow_dispatch on main) \u2014 `No unexpected schema drift between live and supabase/schema.sql.` / `Remote migration versions: 211 (read via rpc)` / `Remote-only (Preview blockers): 0`; every step success." + "outcome": "Supersedes the 2026-08-21 record for the same head. No finding changed: the review outcome stands as self-review with no blocking findings. This record exists solely to satisfy the AGENTS.md rule that evidence is never compressed — the prior record summarised verify:pr-local as `(11/11, failed: none)`, which paraphrases rather than pastes the gate's decisive line. Raised by CodeRabbit on PR #2250 (comment 3833079990) and accepted. Records are immutable and content-addressed, so the correction is made by appending this superseding record rather than editing the original, per the review-ledger contract.", + "checks": "verify:pr-local — decisive output verbatim: `- completed: check:runtime, check:installed-lock-parity, format:changed, sitemap:check, docs:check-index, docs:check-inventory, docs:check-scripts, docs:check-links, check:branch-review-ledger, check:outstanding-issues, check:ledger-write-discipline` / `- failed: (none)` / `- not reached: (none)`. check:production-readiness — `READY: no blocking production-readiness failures.` with `PASS (9)` and `Project: Clinical KB Database (sjrfecxgysukkwxsowpy)`. check:ledger-write-discipline — `Ledger write discipline passed for 70a050752f97..HEAD.` check:outstanding-issues — `Outstanding-issues guard passed: 423 rows (67 open, 356 archived)`. format — whole tree via `npm run format`, result committed before push. live-drift run 32514326022 (workflow_dispatch on main) — `No unexpected schema drift between live and supabase/schema.sql.` / `Remote migration versions: 211 (read via rpc)` / `Remote-only (Preview blockers): 0`; every step success." }, { "date": "2026-08-21", @@ -5513,15 +5555,15 @@ "ref": "claude/shadow-runbook-operator-answers", "head": "1fe3c60c94822f61a60e5b61858114274fb8b340", "scope": "docs(worker): answer two of the four B4 operator unknowns from measured evidence (#2228)", - "outcome": "Backfilled record \u2014 PR #2228 merged 2026-08-21 (squash 1fe3c60c94822f61a60e5b61858114274fb8b340) with no review record captured at the time. Diff inspected post hoc: docs/worker-deploy-runbook.md updated with measured Railway variable-change and memory-headroom evidence (read-only lookups only, no mutation), plus a one-line worker/main.ts startup log-message correction (rollback now states set-then-deploy, no behaviour change) and one queued issues:update inbox request. classifyPullRequestFiles clinicalRisk:false; shadow extraction remains default-off everywhere. Approved by content.", - "checks": "PR-reported: npm run docs:check-links passed (2063 references resolve); Prettier clean on both changed files; CI static-pr required checks green (merged). verify:pr-local full and provider-backed gates explicitly not run per PR body (docs/log-message scope). Not independently re-run in this session \u2014 docs-truth backfill only." + "outcome": "Backfilled record — PR #2228 merged 2026-08-21 (squash 1fe3c60c94822f61a60e5b61858114274fb8b340) with no review record captured at the time. Diff inspected post hoc: docs/worker-deploy-runbook.md updated with measured Railway variable-change and memory-headroom evidence (read-only lookups only, no mutation), plus a one-line worker/main.ts startup log-message correction (rollback now states set-then-deploy, no behaviour change) and one queued issues:update inbox request. classifyPullRequestFiles clinicalRisk:false; shadow extraction remains default-off everywhere. Approved by content.", + "checks": "PR-reported: npm run docs:check-links passed (2063 references resolve); Prettier clean on both changed files; CI static-pr required checks green (merged). verify:pr-local full and provider-backed gates explicitly not run per PR body (docs/log-message scope). Not independently re-run in this session — docs-truth backfill only." }, { "date": "2026-08-21", "ref": "claude/specifiers-dead-exports", "head": "569c8fe11192f29728bf9e436e52bd10270f4640", "scope": "src/lib/specifiers-content.ts dead-export removal + outstanding-issues inbox request", - "outcome": "Approved \u2014 9 deleted lines of unreferenced code, no behaviour change; AGENTS.md context-load finding filed as inbox request", + "outcome": "Approved — 9 deleted lines of unreferenced code, no behaviour change; AGENTS.md context-load finding filed as inbox request", "checks": "typecheck exit 0; test:focused src/lib/specifiers-content.ts 2 files / 60 tests passed; prettier --check clean; verify:pr-local NOT run (worktree removed mid-session, no node_modules)" }, { @@ -5576,7 +5618,7 @@ "date": "2026-08-20", "ref": "claude/docling-shadow-extraction-runbook-942862", "head": "47deb7c42e398c39c2337b5e1cd6a5529afc9e40", - "scope": "packet B4 docling shadow extraction Gate F operator runbook (docs only) \u2014 post-review pass", + "scope": "packet B4 docling shadow extraction Gate F operator runbook (docs only) — post-review pass", "outcome": "two-codex-P2-findings-verified-against-code-and-fixed;search-delay-claim-was-wrong-status-set-at-commit;cohort-widening-needs-reindex-stated;two-coderabbit-nits-on-queued-request-fixed;coderabbit-ledger-entry-finding-rejected-invented-scope", "checks": "check:outstanding-issues:pass;prettier:clean;code-verified:commit_document_index_generation-sets-status-before-shadow" }, @@ -5601,7 +5643,7 @@ "ref": "claude/settings-portability-b38ea3", "head": "411ed4c9a92b8d6060d55f696b1fd66f4ede42c5", "scope": "Move project-specific autoMode allow/soft_deny/environment block from user settings to .claude/settings.json", - "outcome": "Clean \u2014 verbatim move, no behaviour change intended; 41 added lines, no removals", + "outcome": "Clean — verbatim move, no behaviour change intended; 41 added lines, no removals", "checks": "tests/claude-code-settings.test.ts + tests/session-start-hook.test.ts (2 files, 100 tests passed); prettier clean; pr-policy risk all false" }, { @@ -5640,17 +5682,17 @@ "date": "2026-08-20", "ref": "PR #2199", "head": "175c641321e58089d452ed76718972b8d7f705ca", - "scope": "PR #2199 on-demand document search \u2014 Codex P2 review-comment resolution", - "outcome": "Fixed: the document-viewer visual-baseline target still declared .document-viewer-composer as a mask, but the composer is no longer rendered until Search document is pressed, and assertMaskSelectors fails loudly on a mask matching zero nodes \u2014 which classify-visual-baseline-outcome.mjs scores as a NON-drift failure, turning the advisory job hard red on every main push. Mask reduced to the sticky header, with the reasoning recorded in the target comment. Reviewed the rest of the diff: stale-response protection holds (closeDocumentSearch clears sourceSearch, whose effect cleanup aborts the in-flight controller before the reset run), focus restoration and Escape are covered by the Chromium journeys.", - "checks": "npm run verify:pr-local: check:runtime, check:installed-lock-parity, format:changed, lint, typecheck all passed; npm run test 692/693 files, 7592 passed, 4 skipped, 1 failed \u2014 tests/guard-push.test.ts 'inFlightCiGuard formats actionable blocked message', byte-identical to origin/main and failing only because gh is absent in this container so inFlightCiGuard fails open before the injected runFetcher is used; CI Unit coverage passed on this head. Browser proof delegated to CI Production UI: local Playwright pins chromium 1234, image ships 1194 (#255)." + "scope": "PR #2199 on-demand document search — Codex P2 review-comment resolution", + "outcome": "Fixed: the document-viewer visual-baseline target still declared .document-viewer-composer as a mask, but the composer is no longer rendered until Search document is pressed, and assertMaskSelectors fails loudly on a mask matching zero nodes — which classify-visual-baseline-outcome.mjs scores as a NON-drift failure, turning the advisory job hard red on every main push. Mask reduced to the sticky header, with the reasoning recorded in the target comment. Reviewed the rest of the diff: stale-response protection holds (closeDocumentSearch clears sourceSearch, whose effect cleanup aborts the in-flight controller before the reset run), focus restoration and Escape are covered by the Chromium journeys.", + "checks": "npm run verify:pr-local: check:runtime, check:installed-lock-parity, format:changed, lint, typecheck all passed; npm run test 692/693 files, 7592 passed, 4 skipped, 1 failed — tests/guard-push.test.ts 'inFlightCiGuard formats actionable blocked message', byte-identical to origin/main and failing only because gh is absent in this container so inFlightCiGuard fails open before the injected runFetcher is used; CI Unit coverage passed on this head. Browser proof delegated to CI Production UI: local Playwright pins chromium 1234, image ships 1194 (#255)." }, { "date": "2026-08-20", "ref": "PR #2201", "head": "44d3cbb41aae5f1b7707d529347ee12dcc0cc44e", - "scope": "PR #2201 drift alignment window record \u2014 Codex P1 review-comment resolution", + "scope": "PR #2201 drift alignment window record — Codex P1 review-comment resolution", "outcome": "Fixed: the status board's active 'Next dispatches' line, the D4 owner-decision entry, the 2026-08-19 'Resolved' paragraph and the pre-window forensics section still instructed coordinators that D4 is OFF and each migration needs its own db push, contradicting the same PR's finding that D4 is unresolved. All four now say to treat a merge as a production deployment until the dashboard toggle is re-verified. Docs only; no code, migration or fixture touched.", - "checks": "npm run verify:pr-local (docs scope): check:runtime, check:installed-lock-parity, format:changed, sitemap:check, docs:check-index/inventory/scripts/links, check:branch-review-ledger, check:outstanding-issues, check:ledger-write-discipline \u2014 all completed, none failed" + "checks": "npm run verify:pr-local (docs scope): check:runtime, check:installed-lock-parity, format:changed, sitemap:check, docs:check-index/inventory/scripts/links, check:branch-review-ledger, check:outstanding-issues, check:ledger-write-discipline — all completed, none failed" }, { "date": "2026-08-19", @@ -5705,7 +5747,7 @@ "ref": "2129", "head": "eb9cb7481674c436464b0a81b560c3c79cc93501", "scope": "RAG eval scorer: readability metric split (fragmentation vs v19-derived length bound), eval_config_version v1->v2, HANDOVER S3 row", - "outcome": "Approved \u2014 evaluation scorer only; no retrieval/ranking/selection/prompt change; RAG impact declared as no behaviour change; pr-policy evaluatePullRequestPolicy ok:true with 7/7 governance items", + "outcome": "Approved — evaluation scorer only; no retrieval/ranking/selection/prompt change; RAG impact declared as no behaviour change; pr-policy evaluatePullRequestPolicy ok:true with 7/7 governance items", "checks": "verify:pr-local heavy scope failed:(none) not-reached:(none) incl lint+typecheck+full unit suite+build; eval:rag:offline 26 suites/623 tests; check:rag:fixtures 36 golden/26 suites; eval:rag:adversarial:offline 24 cases/8 categories/6 canaries + 25 tests, 3 KNOWN_DIVERGENCES still pinned; vitest tests/rag-eval-cases.test.ts 32 passed (27+5 new, mutation-checked)" }, { @@ -5721,7 +5763,7 @@ "ref": "claude/bundle-budget-production-baseline", "head": "f2cb4ec2ce11bb29444c9aca3c0572c603d48e5e", "scope": "bundle-budget.json production baseline refresh + measurement evidence doc + outstanding-issues request", - "outcome": "Approved \u2014 investigated before refreshing: main's +8.03% is diffuse feature growth across 52 of 101 routes with no regression signature and an unchanged lockfile; production baseline moved to the measured 1518033 bytes, route/mockups budgets and tolerances left untouched", + "outcome": "Approved — investigated before refreshing: main's +8.03% is diffuse feature growth across 52 of 101 routes with no regression signature and an unchanged lockfile; production baseline moved to the measured 1518033 bytes, route/mockups budgets and tolerances left untouched", "checks": "two full builds (main 9d832452d and baseline ca788d41) with .next removed each time; baseline reproduced to within 32 bytes of the recorded value; check:bundle-budget passes at the new baseline with all five route budgets and mockups within tolerance; tests/bundle-budget.test.ts 33 passed; outstanding-issues + ledger-write-discipline + docs link guards passed; format clean. Full unit suite, lint and typecheck not run: the diff is one JSON baseline value plus documentation and an inbox request, with no source change and no plausible compile or behaviour path" }, { @@ -5768,7 +5810,7 @@ "date": "2026-08-18", "ref": "claude/clinical-kb-prod-migration-db4aab", "head": "213226eb43f0b9b4dd096b12da3247458212493e", - "scope": "docs/audit/live-drift-forensics-2026-08.md \u00a73.7 \u2014 production window pre-flight found the five 20260818 migrations already applied by the Supabase GitHub integration; db push not run; read-only verification recorded", + "scope": "docs/audit/live-drift-forensics-2026-08.md §3.7 — production window pre-flight found the five 20260818 migrations already applied by the Supabase GitHub integration; db push not run; read-only verification recorded", "outcome": "docs-only; no production writes; findings recorded for coordinator (integration auto-applies merged migrations)", "checks": "verify:pr-local docs route (11 checks, failed: none); supabase migration list; four read-only db queries; live-drift run 32131517648 read" }, @@ -5817,7 +5859,7 @@ "ref": "claude/db-phase3-staging-proof-bodies", "head": "b5d228ad5ada7bbb82624ab0573894974f3aa232", "scope": "db remediation Phase 3 follow-up, final: 20260818113000 applied to staging, 111000/112000 history text refreshed, staging drift = 1 residual (trgm idx); #316 final update (PR #2111)", - "outcome": "Reviewed and handed off; staging proof complete \u2014 zero function mismatches, zero never-created objects, zero table mismatches, single residual document_chunks_content_trgm_idx (Phase 4.4); production window list unchanged", + "outcome": "Reviewed and handed off; staging proof complete — zero function mismatches, zero never-created objects, zero table mismatches, single residual document_chunks_content_trgm_idx (Phase 4.4); production window list unchanged", "checks": "staging def_hash for the three functions equal manifest/live; four history rows md5 = repo; check:outstanding-issues passed; docs:check-links passed; earlier gates on this branch unchanged" }, { @@ -5864,7 +5906,7 @@ "date": "2026-08-18", "ref": "claude/db-remediation-phase-1-2-19e4de", "head": "8329d0f02ff1394a65cea6946b786030549563c1", - "scope": "docs-only: Phase 1.2 RPC divergence dossier (docs/audit/live-drift-forensics-2026-08.md \u00a71.2) + one #316 inbox update; PR #2087", + "scope": "docs-only: Phase 1.2 RPC divergence dossier (docs/audit/live-drift-forensics-2026-08.md §1.2) + one #316 inbox update; PR #2087", "outcome": "self-review complete: all ten match_* def_hash mismatches classified attribute-only (SET work_mem; 4 mirror-stale, 6 live-ahead), zero repo-ahead, zero UNCLASSIFIED; read-only connector session, no RPC/migration/RAG code changed", "checks": "verify:pr-local (docs scope) failed:(none); docs:check-links 1826 resolve; check:outstanding-issues 348 rows guard passed; ledger-write-discipline passed; format committed" }, @@ -5881,7 +5923,7 @@ "ref": "claude/db-remediation-phase4-indexes-a1661a", "head": "5d3dca4dd7a0593a35e6d639144092dee6609256", "scope": "Phase 4 index restoration: 20 concurrent index builds + 2 concurrent drops on production, 3 fail-fast guard migrations, search_schema_health required_indexes 22->30, schema.sql mirror, regenerated drift manifest, staging parity, forensics evidence", - "outcome": "PASS \u2014 20/20 indexes rebuilt indisvalid+indisready with canonical definitions, 2 orphans dropped per the repo chain, live-drift 32171070287 shows missing_live 20->0 and unexpected_live 2->0, staging drift green (was 19). Two escalations recorded not absorbed: PITR is not enabled on production, and no migration_history allowlist entry was earned (empty intersection with the 15 no-statements versions)", + "outcome": "PASS — 20/20 indexes rebuilt indisvalid+indisready with canonical definitions, 2 orphans dropped per the repo chain, live-drift 32171070287 shows missing_live 20->0 and unexpected_live 2->0, staging drift green (was 19). Two escalations recorded not absorbed: PITR is not enabled on production, and no migration_history allowlist entry was earned (empty intersection with the 15 no-statements versions)", "checks": "check:migration-role; vitest supabase-schema + search-health-index-coverage + migration-history-guards + drift-detection + migration-history-placeholders + hosted-migration-role-guard (6 files, 109 tests); drift:manifest; check:rag:fixtures (36 golden cases); check:medication-interactions; check:medication-lexicon-report; verify:pr-local all stages pass except two load-induced timeouts (codex-cloud-setup, document-viewer-page-virtualization) that pass in isolation and are unrelated to this diff" }, { @@ -5922,7 +5964,7 @@ "head": "189df34d69c01fe08f17df5e49dc0cf2ca37d9c6", "scope": "Run PR sweep: CI fix + threads + drift", "outcome": "Before: all required checks already green (PR required success), 0 unresolved review threads, 3 bot-only PR comments (Codex usage limit, Supabase no-op, CodeRabbit rate limit) needing no action. Branch was behind main (mergeable_state: behind). Action: synced via GitHub update-branch API (clean merge, no conflicts) -> new head 189df34d69c01fe08f17df5e49dc0cf2ca37d9c6. After: fresh CI running on synced head, no code changes made, no threads to resolve.", - "checks": "No local gates run \u2014 PR already had npm run lint/typecheck/test/verify:ui results in its own description and no code was touched by this sweep; only a GitHub-side branch sync was performed. No provider-backed checks run." + "checks": "No local gates run — PR already had npm run lint/typecheck/test/verify:ui results in its own description and no code was touched by this sweep; only a GitHub-side branch sync was performed. No provider-backed checks run." }, { "date": "2026-08-18", @@ -5952,8 +5994,8 @@ "date": "2026-08-18", "ref": "claude/eval-canary-protocol-docs-01bb49", "head": "3e9905d0ac9d88f22dc88d41639399ae69237cf0", - "scope": "docs/rag-behaviour/safeguards.md, docs/rag-improvement/README.md \u2014 eval-canary pair protocol trigger mechanics and bisection lessons (ledger #TYJ0XP)", - "outcome": "approved \u2014 docs-only, no code/behaviour change", + "scope": "docs/rag-behaviour/safeguards.md, docs/rag-improvement/README.md — eval-canary pair protocol trigger mechanics and bisection lessons (ledger #TYJ0XP)", + "outcome": "approved — docs-only, no code/behaviour change", "checks": "verify:pr-local (docs-scoped: format:changed, sitemap:check, docs:check-index, docs:check-inventory, docs:check-scripts, docs:check-links, check:branch-review-ledger, check:outstanding-issues, check:ledger-write-discipline) all passed" }, { @@ -6000,7 +6042,7 @@ "date": "2026-08-18", "ref": "claude/header-redesign-mockups-3ms5kn", "head": "8083a20d6a3496ed154b927157bd621735886795", - "scope": "Dictionary Browse header round two \u2014 letter dropdown + Abbreviations in Filters (design scratch)", + "scope": "Dictionary Browse header round two — letter dropdown + Abbreviations in Filters (design scratch)", "outcome": "approved", "checks": "verify:pr-local all 18 steps completed / none failed, check:bundle-budget within tolerance, Chromium dark+light screenshot review" }, @@ -6026,7 +6068,7 @@ "head": "33ec22afd7b23dfc89fdf836fc80cc4a97c7a065", "scope": "remove caveat footer from every mode home", "outcome": "self-review clean; all mode-home caveat footers removed, dead reserve/props/helper deleted", - "checks": "verify:pr-local pass on merged head (673 files / 7281 tests, build, lint, typecheck, offline RAG evals); verify:ui not run \u2014 playwright chromium 1234 vs installed 1194 (#255)" + "checks": "verify:pr-local pass on merged head (673 files / 7281 tests, build, lint, typecheck, offline RAG evals); verify:ui not run — playwright chromium 1234 vs installed 1194 (#255)" }, { "date": "2026-08-18", @@ -6034,22 +6076,22 @@ "head": "40b92d2d6f41d0f9fadc8c4840737ffae1f34c5d", "scope": "mode home footers + dictionary command surface", "outcome": "self-review clean; footers removed on user instruction, dictionary example ticket added", - "checks": "verify:pr-local pass (673 files / 7276 tests); verify:ui not run \u2014 playwright chromium 1234 vs installed 1194 (#255), delegated to CI" + "checks": "verify:pr-local pass (673 files / 7276 tests); verify:ui not run — playwright chromium 1234 vs installed 1194 (#255), delegated to CI" }, { "date": "2026-08-18", "ref": "claude/home-pages-cleanup-qeh5fr (PR #2139)", "head": "49875287ead7a15069224174d68f57b44c220e3d", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Branch already current with origin/main (base sha a9552eb4 == main tip; PR includes its own 'Merge branch main' commit) \u2014 no drift/conflict, so the #2112 shared-mode-home/composer overlap did not materialize and no merge or resolution was needed. 0 unresolved review threads (only bot usage-limit/skip comments present, non-actionable). All completed required CI checks green as of last observation (Static PR checks, Build, Production UI critical, Safety and config checks, Change scope, Unit coverage all success; zero failures across 25 check runs); Production UI (1)/(2)/(3) and Lighthouse budget were still in_progress after ~25 min observation window with no failure signal \u2014 left running, no code changes needed or made. No commits pushed this sweep.", + "outcome": "Branch already current with origin/main (base sha a9552eb4 == main tip; PR includes its own 'Merge branch main' commit) — no drift/conflict, so the #2112 shared-mode-home/composer overlap did not materialize and no merge or resolution was needed. 0 unresolved review threads (only bot usage-limit/skip comments present, non-actionable). All completed required CI checks green as of last observation (Static PR checks, Build, Production UI critical, Safety and config checks, Change scope, Unit coverage all success; zero failures across 25 check runs); Production UI (1)/(2)/(3) and Lighthouse budget were still in_progress after ~25 min observation window with no failure signal — left running, no code changes needed or made. No commits pushed this sweep.", "checks": "GitHub check-runs API polled for HEAD 4987528 (twice, ~5 min apart): no failing required job observed. No local gates run (nothing to fix/verify). No provider-backed checks run." }, { "date": "2026-08-18", "ref": "claude/issues-capture-h5a-residual-ulid-lookup", "head": "5c9b69a7e6bd2a3f2a1f5abac1a19a71a1cd153b", - "scope": "two immutable outstanding-issues inbox requests (P3 issue: H5a residual after G1; P3 rec: ledger writer id-scheme test gap) \u2014 no product code", - "outcome": "approved \u2014 inbox-request files only; canonical ledger untouched, applied later by issues:reconcile", + "scope": "two immutable outstanding-issues inbox requests (P3 issue: H5a residual after G1; P3 rec: ledger writer id-scheme test gap) — no product code", + "outcome": "approved — inbox-request files only; canonical ledger untouched, applied later by issues:reconcile", "checks": "verify:pr-local light docs scope, all 11 selected stages green (format:changed, docs link/index/inventory/scripts, branch-review-ledger, outstanding-issues, ledger-write-discipline); build/test correctly skipped as non-build-affecting; request JSON content verified incl. escaping" }, { @@ -6057,7 +6099,7 @@ "ref": "claude/issues-reconcile-2026-08-18-evening", "head": "79b4d8df0c37a580935904bdeed04e14aa23b0d8", "scope": "issues ledger reconciliation (88 queued inbox requests: database-remediation set + PR #2105 done resolutions)", - "outcome": "clean \u2014 reconciler applied all 88 queued requests with 10 cancellation decisions, refused none; no request adjudicated, edited or deleted by hand; diff is 1 canonical file + 88 renames", + "outcome": "clean — reconciler applied all 88 queued requests with 10 cancellation decisions, refused none; no request adjudicated, edited or deleted by hand; diff is 1 canonical file + 88 renames", "checks": "verify:pr-local (11/11 gates, 0 failed, 0 unreached); check:outstanding-issues (365 rows, 48 open, 0 pending / 339 applied); check:ledger-write-discipline (ce702ba68c12..HEAD); docs:check-links (1901 refs); format (whole tree, unchanged)" }, { @@ -6065,7 +6107,7 @@ "ref": "claude/issues-reconcile-2026-08-18-evening", "head": "ed19e1435049e284088c0e8d042465004390c4de", "scope": "prlanded", - "outcome": "clean \u2014 PR #2120 merged as squash ed19e143; two-dot content diff against branch tip 0771039f is empty, all 90 files landed including the review record, no orphaned late commit from the auto-merge race", + "outcome": "clean — PR #2120 merged as squash ed19e143; two-dot content diff against branch tip 0771039f is empty, all 90 files landed including the review record, no orphaned late commit from the auto-merge race", "checks": "git diff --stat ed19e143 0771039f (empty); ledger record 6b6d74c4 present on main; check:outstanding-issues on main 4575cf57 (365 rows, 48 open, 0 pending / 339 applied)" }, { @@ -6073,7 +6115,7 @@ "ref": "claude/issues-reconcile-2026-08-19", "head": "b393cdd530e81d6bfbdc15c495d870b57c73f01b", "scope": "Serialized reconcile of 21 queued outstanding-issues inbox requests (PR #2168)", - "outcome": "approved \u2014 documentation-only; canonical diff equals the recorded reconciliation transaction", + "outcome": "approved — documentation-only; canonical diff equals the recorded reconciliation transaction", "checks": "check:outstanding-issues passed (392 rows, 57 open); check:ledger-write-discipline passed b400b138f8c1..HEAD; format:changed clean; inbox 0 pending / 391 applied" }, { @@ -6089,7 +6131,7 @@ "ref": "claude/ledger-issues-reconcile-945d0a", "head": "dd47bbe7e402e203e3d094127d1955ea0b650d4f", "scope": "docs/outstanding-issues-inbox ledger queueing", - "outcome": "PR #2130: queued 7 immutable ledger requests (done #DP6M3G, update #231 re-grade P1->P2, done #BTVMVK/#ND10QT as duplicates, 3 new P3 recs). No canonical ledger edit \u2014 reconciliation deferred to a dedicated follow-up PR because check:ledger-write-discipline cannot pass a same-PR add+reconcile.", + "outcome": "PR #2130: queued 7 immutable ledger requests (done #DP6M3G, update #231 re-grade P1->P2, done #BTVMVK/#ND10QT as duplicates, 3 new P3 recs). No canonical ledger edit — reconciliation deferred to a dedicated follow-up PR because check:ledger-write-discipline cannot pass a same-PR add+reconcile.", "checks": "check:outstanding-issues passed (16 pending, 339 applied); check:ledger-write-discipline passed for 53438ae4392a..HEAD; prettier --check passed" }, { @@ -6114,7 +6156,7 @@ "head": "1cffafbc172fc22625aa3cba62d5d685b7720f25", "scope": "Run PR sweep: CI fix + threads + drift", "outcome": "Before: PR mergeability/PR policy transiently failed (self-healed on retry, no real conflict); Production UI (3) failed 3 Chromium specs (ui-specifiers.spec.ts mobile composer, 2x ui-tools.spec.ts stale /differentials and /services route assertions) caused by this PR's own consolidated-mode-home routing change, not main drift. Fixed: updated the 3 stale test assertions to match the new /differentials/search, /?mode=services, and /specifiers/search routes already established elsewhere in this PR's own diff. After: fixes pushed, fresh CI re-running. Still blocked on a blank Clinical Governance Preflight in the PR body (human-owned, not auto-fillable) and a real Lighthouse TBT regression pattern matching known main-wide drift from a prior merge.", - "checks": "npx tsc --noEmit (clean), npx eslint tests/ui-tools.spec.ts tests/ui-specifiers.spec.ts (clean), npx prettier --write (no changes needed); Playwright not run locally (browser revision mismatch, chromium-1194 vs CI's 1234) \u2014 delegated to CI Production UI. No provider-backed checks run." + "checks": "npx tsc --noEmit (clean), npx eslint tests/ui-tools.spec.ts tests/ui-specifiers.spec.ts (clean), npx prettier --write (no changes needed); Playwright not run locally (browser revision mismatch, chromium-1194 vs CI's 1234) — delegated to CI Production UI. No provider-backed checks run." }, { "date": "2026-08-18", @@ -6153,14 +6195,14 @@ "ref": "claude/post-reconcile-review-2026-08-18", "head": "cd5fe0f4026c43af78ab0f80f78d661e88faedc0", "scope": "retire stale visual-register instructions in issues/ledger skills + AGENTS.md; queue reconcile-serialization follow-up", - "outcome": "clean \u2014 three instruction surfaces no longer point at the ISSUES-LIST.html artifact #338 retired; check:skills regression introduced and fixed within the diff (220-word canonical budget)", + "outcome": "clean — three instruction surfaces no longer point at the ISSUES-LIST.html artifact #338 retired; check:skills regression introduced and fixed within the diff (220-word canonical budget)", "checks": "verify:pr-local (22/22 gates, 0 failed, 0 unreached); test:ci-workflows 325 passed; check:skills exit 0 (was 1 mid-change, baseline re-measured); format (whole tree)" }, { "date": "2026-08-18", "ref": "claude/rag-d4-reconcile-inbox", "head": "d1d75055396cff3ea15c6ef6c45d9363440b4175", - "scope": "issues:reconcile (17 requests) + HANDOVER G1/S1d/S1c/S2 rows + COORDINATION \u00a77 (docs-only)", + "scope": "issues:reconcile (17 requests) + HANDOVER G1/S1d/S1c/S2 rows + COORDINATION §7 (docs-only)", "outcome": "single fresh-base reconcile; 0 pending afterwards; G1/S1c/governance rows closed", "checks": "check:outstanding-issues 0 pending/234 applied; check:ledger-write-discipline passed 981d85de0301..HEAD; verify:pr-local docs scope" }, @@ -6185,7 +6227,7 @@ "ref": "claude/refresh-therapy-visual-baseline", "head": "3d74403292d3b340a01de24008d23ea91c71a755", "scope": "Refresh all six Linux visual baselines from hosted-CI artifact visual-baseline-32189416778 (main @ 9b1e7248) plus provenance and regenerated adoption manifest", - "outcome": "Approved \u2014 all six actual renders opened and reviewed before adopting; no source changed; provenance reviewerType:human is overstated for an automated pass and is flagged in the PR for owner confirmation", + "outcome": "Approved — all six actual renders opened and reviewed before adopting; no source changed; provenance reviewerType:human is overstated for an automated pass and is flagged in the PR for owner confirmation", "checks": "adopt-visual-baselines --write (6/6 replaced, capture kind refresh); check:design-system-adoption (54 components, 82 roots); vitest tests/adopt-visual-baselines.test.ts 4 passed; prettier --check provenance.json clean. No broader gate: PNG/JSON-only diff with no changed source failure path" }, { @@ -6225,8 +6267,8 @@ "ref": "claude/schema-work-mem-codify-6200f1", "head": "3e73b8bd43a689b9c6f8c83b9cbfddede0bb231b", "scope": "supabase migrations, schema.sql (PR #2106 Phase 3 codification review)", - "outcome": "Reviewed via supabase-schema-guardian: signatures, ordering, idempotency, schema.sql/migration consistency, RAG-impact claim, and guard-migration contract all verified correct against the diff. Fixed one concern (forensics runbook offered mark-applied-by-CLI as equal to db push for three migrations shipping no validation guard \u2014 narrowed to require db push and forbid migration repair) and added SET LOCAL lock_timeout/statement_timeout to the two migrations taking ACCESS EXCLUSIVE locks on hot tables (documents, ingestion_jobs, document_chunks), matching the 20260804110240 pattern. No schema.sql or function-body change from this review; no live Supabase access.", - "checks": "check:migration-role passed; vitest tests/migration-history-guards+hosted-migration-role-guard+supabase-schema+drift-detection+search-health-index-coverage+guard-push.test.ts 141/141 passed; prettier --check on the edited doc passed; npm run format whole-tree no-op; drift:manifest Docker replay not run (Docker daemon unavailable in this sandbox) \u2014 CI Migration replay + Unit coverage + Static PR checks + PR required all green on the prior head and these edits are additive SQL/prose only" + "outcome": "Reviewed via supabase-schema-guardian: signatures, ordering, idempotency, schema.sql/migration consistency, RAG-impact claim, and guard-migration contract all verified correct against the diff. Fixed one concern (forensics runbook offered mark-applied-by-CLI as equal to db push for three migrations shipping no validation guard — narrowed to require db push and forbid migration repair) and added SET LOCAL lock_timeout/statement_timeout to the two migrations taking ACCESS EXCLUSIVE locks on hot tables (documents, ingestion_jobs, document_chunks), matching the 20260804110240 pattern. No schema.sql or function-body change from this review; no live Supabase access.", + "checks": "check:migration-role passed; vitest tests/migration-history-guards+hosted-migration-role-guard+supabase-schema+drift-detection+search-health-index-coverage+guard-push.test.ts 141/141 passed; prettier --check on the edited doc passed; npm run format whole-tree no-op; drift:manifest Docker replay not run (Docker daemon unavailable in this sandbox) — CI Migration replay + Unit coverage + Static PR checks + PR required all green on the prior head and these edits are additive SQL/prose only" }, { "date": "2026-08-18", @@ -6241,7 +6283,7 @@ "ref": "claude/search-recovery-rail", "head": "7510216c672f293d26b8fdfe04a9ed3fd286b7f6", "scope": "SearchResultsEmptyState rail restyle + desktop tap floor restore (PR #2147)", - "outcome": "approved \u2014 presentation-only; no copy, testid, heading-level, live-region or handler change; band untouched", + "outcome": "approved — presentation-only; no copy, testid, heading-level, live-region or handler change; band untouched", "checks": "typecheck 0 errors; eslint+prettier+format:changed clean; 10 DOM files/168 tests passed; chromium ui-accessibility 16 passed; full verify:ui not completed (lock contention + host exit)" }, { @@ -6249,7 +6291,7 @@ "ref": "claude/services-navigation-removal-7bnknn", "head": "ba279bdd0b2fdc5d4dfa2c88dd30d57ee94be330", "scope": "src/components/services/services-navigator-page.tsx (referral progress stepper phone centering)", - "outcome": "PR #2103 opened \u2014 verify:pr-local complete (7091 tests, build, lint, typecheck, RAG fixtures, medication checks all passed)", + "outcome": "PR #2103 opened — verify:pr-local complete (7091 tests, build, lint, typecheck, RAG fixtures, medication checks all passed)", "checks": "verify:pr-local" }, { @@ -6265,7 +6307,7 @@ "ref": "claude/settings-development-section (PR #2109)", "head": "5bda0941ea2b257af23f569a25e7659bcebcdf40", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Before: Static PR checks failing (design-system-contract ratchet \u2014 legacyShadowAliases at settings-dialog.tsx increased 3 -> 4 via var(--shadow-soft) in the new Development section), 0 unresolved review threads, branch 1 commit behind main (clean merge-tree). After: synced origin/main into the branch via update_pull_request_branch (no conflicts, base now 5ae2bb6e), fixed the shadow-alias regression by switching to shadow-[var(--e2),var(--shadow-inset)] (same pattern as account-setup-dialog.tsx), pushed b1f9dac6..5bda0941. No review threads existed to action.", + "outcome": "Before: Static PR checks failing (design-system-contract ratchet — legacyShadowAliases at settings-dialog.tsx increased 3 -> 4 via var(--shadow-soft) in the new Development section), 0 unresolved review threads, branch 1 commit behind main (clean merge-tree). After: synced origin/main into the branch via update_pull_request_branch (no conflicts, base now 5ae2bb6e), fixed the shadow-alias regression by switching to shadow-[var(--e2),var(--shadow-inset)] (same pattern as account-setup-dialog.tsx), pushed b1f9dac6..5bda0941. No review threads existed to action.", "checks": "npm run check:design-system-contract -> 'Design-system contract passed'; node scripts/run-vitest.mjs run tests/settings-dialog-actions.dom.test.tsx tests/client-secret-surface.test.ts -> 'Test Files 2 passed (2) / Tests 13 passed (13)'; npx tsc -p tsconfig.typecheck.json --noEmit -> exit 0 no diagnostics; npx eslint settings-dialog.tsx -> exit 0; npx prettier --check settings-dialog.tsx -> 'All matched files use Prettier code style!'; no provider-backed checks run" }, { @@ -6273,31 +6315,31 @@ "ref": "claude/settings-development-section (PR #2141)", "head": "2e7325681c2fdb0909baba6709ca64bfe5f61692", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "No unresolved review threads (0 threads; only bot noise: Codex/CodeRabbit usage-limit notices, Supabase branching skip). Required CI (pr-required: changes/static-pr/safety/coverage/build/ui-critical/db-reset-verify) has never run on this head because mergeable_state is dirty and GitHub cannot build the merge ref (only pull_request_target PR-mergeability/PR-policy/GitGuardian ran). git merge-tree origin/main shows real content conflicts in src/components/clinical-dashboard/settings-dialog.tsx and tests/settings-dialog-actions.dom.test.tsx: this PR's first commit (34af56a6, feat(settings): add a gated Development section...) duplicates already-merged main commit bf85de98 (PR #2109, same title/feature, landed 2026-08-18 20:36 UTC, ~20 min after this PR opened) with only a cosmetic shadow-token diff. This is a semantically ambiguous product-history conflict (near-duplicate commit vs a since-merged PR), not a mechanical one (no lockfile/generated/adjacent-hunk fix applies) \u2014 per run-pr guardrails, skipped drift resolution rather than merge --abort/wholesale ours-theirs. No commits pushed, no branch state changed. Left for human: decide whether to drop/rebase the duplicate first commit (keeping only the second commit 2e732568 adding src/app/mockups/development/page.tsx) or close #2141 as superseded by #2109 \u2014 related to PR #2135 (Development mockup page) handled in parallel by another agent.", - "checks": "git merge-tree --write-tree origin/main origin/claude/settings-development-section (conflict detected, non-mutating); mcp__github__pull_request_read get/get_status/get_check_runs/get_review_comments/get_comments; npm run ledger:lookup (NOT REVIEWED at this head, confirmed pre-action). No provider-backed gates run. No local build/lint/test run \u2014 no code fix was attempted since the blocking issue is an unresolved product-history conflict, not a reproducible CI failure." + "outcome": "No unresolved review threads (0 threads; only bot noise: Codex/CodeRabbit usage-limit notices, Supabase branching skip). Required CI (pr-required: changes/static-pr/safety/coverage/build/ui-critical/db-reset-verify) has never run on this head because mergeable_state is dirty and GitHub cannot build the merge ref (only pull_request_target PR-mergeability/PR-policy/GitGuardian ran). git merge-tree origin/main shows real content conflicts in src/components/clinical-dashboard/settings-dialog.tsx and tests/settings-dialog-actions.dom.test.tsx: this PR's first commit (34af56a6, feat(settings): add a gated Development section...) duplicates already-merged main commit bf85de98 (PR #2109, same title/feature, landed 2026-08-18 20:36 UTC, ~20 min after this PR opened) with only a cosmetic shadow-token diff. This is a semantically ambiguous product-history conflict (near-duplicate commit vs a since-merged PR), not a mechanical one (no lockfile/generated/adjacent-hunk fix applies) — per run-pr guardrails, skipped drift resolution rather than merge --abort/wholesale ours-theirs. No commits pushed, no branch state changed. Left for human: decide whether to drop/rebase the duplicate first commit (keeping only the second commit 2e732568 adding src/app/mockups/development/page.tsx) or close #2141 as superseded by #2109 — related to PR #2135 (Development mockup page) handled in parallel by another agent.", + "checks": "git merge-tree --write-tree origin/main origin/claude/settings-development-section (conflict detected, non-mutating); mcp__github__pull_request_read get/get_status/get_check_runs/get_review_comments/get_comments; npm run ledger:lookup (NOT REVIEWED at this head, confirmed pre-action). No provider-backed gates run. No local build/lint/test run — no code fix was attempted since the blocking issue is an unresolved product-history conflict, not a reproducible CI failure." }, { "date": "2026-08-18", "ref": "claude/therapy-compass-convergence-2iufoh (PR #2131)", "head": "847ff291b55a69cff1029648754d316a79ca1bef", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "No drift (0 behind main, base sha matches origin/main exactly) and no CI fixes needed: all required checks green (PR required, Static PR checks, PR policy, PR mergeability, GitGuardian, Semgrep, Gitleaks all success; heavy jobs correctly skipped for doc-only scope). 1 unresolved review thread (CodeRabbit P3 nit: format / placeholders as code in the immutable record file) \u2014 replied declining the direct edit because the record filename is sha256(row) per reviewRecordPath() and check-branch-review-ledger.mjs asserts filename==hash(content), so hand-editing would desync the content-addressing invariant; left open for a human --supersede decision, not resolved.", - "checks": "mcp__github__pull_request_read get/get_status/get_check_runs/get_files/get_comments/get_review_comments (live); git fetch + git rev-list --left-right --count origin/main...origin/claude/therapy-compass-convergence-2iufoh (0 behind); no local gates run \u2014 no code change made, no CI fix required; no provider-backed checks run" + "outcome": "No drift (0 behind main, base sha matches origin/main exactly) and no CI fixes needed: all required checks green (PR required, Static PR checks, PR policy, PR mergeability, GitGuardian, Semgrep, Gitleaks all success; heavy jobs correctly skipped for doc-only scope). 1 unresolved review thread (CodeRabbit P3 nit: format / placeholders as code in the immutable record file) — replied declining the direct edit because the record filename is sha256(row) per reviewRecordPath() and check-branch-review-ledger.mjs asserts filename==hash(content), so hand-editing would desync the content-addressing invariant; left open for a human --supersede decision, not resolved.", + "checks": "mcp__github__pull_request_read get/get_status/get_check_runs/get_files/get_comments/get_review_comments (live); git fetch + git rev-list --left-right --count origin/main...origin/claude/therapy-compass-convergence-2iufoh (0 behind); no local gates run — no code change made, no CI fix required; no provider-backed checks run" }, { "date": "2026-08-18", "ref": "claude/therapy-mode-consistency-a466b0", "head": "092633eb7479b21796790a33b0ff7a3a7d4cf05c", "scope": "prlanded", - "outcome": "Landed correctly. PR #2122 squash-merged as 092633eb; verified by content, not ancestry: two-dot 'git diff --stat 092633eb 7733eb8c' is empty, so nothing was orphaned by the auto-merge race. The pre-merge sync of main into the branch was also proven clean \u2014 its tree hash equalled git merge-tree's automatic result exactly, so no hand resolution could have silently reverted content (the failure mode #324 describes). Branch reports 13 ahead of main, which is the squash artifact, not unlanded work. Remote head deleted by GitHub on merge; four inbox requests ride on main awaiting issues:reconcile.", - "checks": "git diff --stat empty; merge-tree hash equality on the pre-merge sync; post-merge verify:cheap green \u2014 Test Files 673 passed (673), Tests 7275 passed | 4 skipped (7279), Design-system contract passed (784 production files), hosted migration-role guard passed" + "outcome": "Landed correctly. PR #2122 squash-merged as 092633eb; verified by content, not ancestry: two-dot 'git diff --stat 092633eb 7733eb8c' is empty, so nothing was orphaned by the auto-merge race. The pre-merge sync of main into the branch was also proven clean — its tree hash equalled git merge-tree's automatic result exactly, so no hand resolution could have silently reverted content (the failure mode #324 describes). Branch reports 13 ahead of main, which is the squash artifact, not unlanded work. Remote head deleted by GitHub on merge; four inbox requests ride on main awaiting issues:reconcile.", + "checks": "git diff --stat empty; merge-tree hash equality on the pre-merge sync; post-merge verify:cheap green — Test Files 673 passed (673), Tests 7275 passed | 4 skipped (7279), Design-system contract passed (784 production files), hosted migration-role guard passed" }, { "date": "2026-08-18", "ref": "claude/therapy-mode-consistency-a466b0", "head": "244accbde60c5b39f9a91c7f2096053a2f2c5a65", "scope": "Therapy Compass shared-component convergence B3/C/D: control recipes to shared Button, 16 card surfaces to card-recipes cardSurface/heroCard, six page headers to shared PageHeader, plus two strengthened responsive-contract assertions", - "outcome": "Approved for review as PR #2122 \u2014 19 button call sites converted with per-screen one-filled-command checks, all 16 card surfaces converged (compare table scroll frame deliberately excluded as a frame not a card), six of nine h1 converted (detail hero, patient-handout title and placeholder hero left; PageHeader renders a header element that print CSS hides unconditionally). therapyBtn retained: still the affordance for ~20 non-Button raw call sites. Ratchets fell, none rose.", + "outcome": "Approved for review as PR #2122 — 19 button call sites converted with per-screen one-filled-command checks, all 16 card surfaces converged (compare table scroll frame deliberately excluded as a frame not a card), six of nine h1 converted (detail hero, patient-handout title and placeholder hero left; PageHeader renders a header element that print CSS hides unconditionally). therapyBtn retained: still the affordance for ~20 non-Button raw call sites. Ratchets fell, none rose.", "checks": "eslint clean; tsc --noEmit clean; verify:pr-local Test Files 673 passed (673), Tests 7274 passed | 4 skipped (7278); build re-run standalone exit 0 after BUILD_REFUSED_DEV_SERVER; check:bundle-budget all routes within tolerance; verify:ui 447 passed (20.4m) on Playwright-matched Chromium 1234; check:design-system-contract passed" }, { @@ -6305,7 +6347,7 @@ "ref": "claude/therapy-modes-visibility-bb37d2", "head": "9b4b3056b1f4ef7355e8947d6b210dee63de182e", "scope": "Therapy production visibility: remove devOnly gate, route-layout not-found gate and production review filter; add catalogue review notice + needsReviewCount; retire PLAYWRIGHT_OFFLINE_MODE bypass; update pinning contracts", - "outcome": "Approved \u2014 reachability now disclosed rather than gated; per-record reviewStatus badges retained on every surface; single-commit revert restores all three gates", + "outcome": "Approved — reachability now disclosed rather than gated; per-record reviewStatus badges retained on every surface; single-commit revert restores all three gates", "checks": "verify:pr-local (docs/ledger/lint/typecheck passed; test failed only on unrelated load-flaky tests/codex-cloud-setup.test.ts, which passes in isolation at HEAD and with the change); build from wiped .next compiled successfully with all 9 therapy routes; check:rag:fixtures, check:medication-interactions, check:medication-lexicon-report passed; focused therapy+route-reachability contracts 77 passed; eslint+tsc clean; dev-server route 200s. verify:ui not run - coordinator heavy lock held by another worktree" }, { @@ -6321,7 +6363,7 @@ "ref": "codex/caring-contact-linked-mockup", "head": "fde840e6cdddc823245f1c9f239a51aa1951f93c", "scope": "Caring Contact linked prototype: 13 mockup routes, 17 mockup components, docs/caring-contacts, 6 test files, playwright/package script registration, mockups bundle-budget baseline", - "outcome": "Approved for draft PR \u2014 mockup-only scope, no production route/API/library change; merged up to main and re-verified", + "outcome": "Approved for draft PR — mockup-only scope, no production route/API/library change; merged up to main and re-verified", "checks": "verify:pr-local (lint, typecheck, docs/ledger guards passed); vitest 7033 passed / 4 failed, all four cleared as pre-existing or full-suite contention (session-start-hook fails identically on untouched origin/main; other three pass in isolation); next build compiled; bundle-budget production within tolerance, mockups baseline refreshed 296.0->370.2 KiB; check:rag:fixtures 36 cases; medication interaction + lexicon checks passed; post-sync lint + typecheck exit 0" }, { @@ -6329,7 +6371,7 @@ "ref": "codex/chat-dictionary-ultimate-dictionary-ultimate", "head": "3a8271bd7a9aa13b2a323cd29e84f294de211690", "scope": "Dictionary mode: 8 production routes, 96-entry governed catalogue, shared search/filter lib, launcher/ModeNav/universal-search/tools-catalogue integration, design-system adoption manifests", - "outcome": "Approved for draft PR with one declared red gate \u2014 production bundle budget +10.5% (main alone is +7.8% of a 2026-08-13 baseline; this branch adds 33.9 KiB across 11 dictionary-exclusive chunks). Baseline deliberately not refreshed; decision left to review", + "outcome": "Approved for draft PR with one declared red gate — production bundle budget +10.5% (main alone is +7.8% of a 2026-08-13 baseline; this branch adds 33.9 KiB across 11 dictionary-exclusive chunks). Baseline deliberately not refreshed; decision left to review", "checks": "verify:pr-local (lint, typecheck, docs/ledger guards passed); vitest 6990 passed / 2 failed, both cleared (private-access-routes passes in isolation 145/145; session-start-hook fails identically on untouched origin/main); next build compiled; check:client-bundle-secrets passed; check:bundle-budget FAIL on production bucket (documented in PR body), routes and mockups within tolerance; check:rag:fixtures 36 cases; medication interaction + lexicon checks passed; post-sync lint + typecheck exit 0" }, { @@ -6345,8 +6387,8 @@ "ref": "codex/ward-management-design (PR #2140)", "head": "d7f5b76e29aa2ca489c3f3401f19bd18508e462f", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "No fix applied \u2014 branch history is unrelated to main (git merge-base/merge-tree fails: 'refusing to merge unrelated histories', root commits differ entirely). GitHub cannot build refs/pull/2140/merge, so pull_request (ci.yml/pr-required) never ran; only pull_request_target jobs ran (PR mergeability: failure \u2014 real merge conflict; PR policy: failure \u2014 Clinical Governance Preflight unchecked, 7/7 boxes empty in template). 0 unresolved review threads (only bot rate-limit/ignored notices). Left for human: branch needs re-basing/re-creation onto main or history investigation \u2014 out of scope for mechanical sweep; PR body also needs governance section completed by author, which this session may not edit.", - "checks": "git fetch/merge-base/merge-tree (local, offline); mcp__github__pull_request_read get/get_status/get_check_runs/get_review_comments/get_comments; mcp__github__actions_list + get_job_logs on both failing workflow runs. No provider-backed checks (build/test/eval) run \u2014 no code fix was possible or attempted." + "outcome": "No fix applied — branch history is unrelated to main (git merge-base/merge-tree fails: 'refusing to merge unrelated histories', root commits differ entirely). GitHub cannot build refs/pull/2140/merge, so pull_request (ci.yml/pr-required) never ran; only pull_request_target jobs ran (PR mergeability: failure — real merge conflict; PR policy: failure — Clinical Governance Preflight unchecked, 7/7 boxes empty in template). 0 unresolved review threads (only bot rate-limit/ignored notices). Left for human: branch needs re-basing/re-creation onto main or history investigation — out of scope for mechanical sweep; PR body also needs governance section completed by author, which this session may not edit.", + "checks": "git fetch/merge-base/merge-tree (local, offline); mcp__github__pull_request_read get/get_status/get_check_runs/get_review_comments/get_comments; mcp__github__actions_list + get_job_logs on both failing workflow runs. No provider-backed checks (build/test/eval) run — no code fix was possible or attempted." }, { "date": "2026-08-18", @@ -6369,7 +6411,7 @@ "ref": "dependabot/github_actions/github-actions-6d70da7aad (PR #2011)", "head": "bb5e4d1158639d678c75c8fd85f5e3fd608e2936", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Ledger throttle showed NOT REVIEWED at cda7ff21b. Found the substantive fix (claude-code-action pin v1.0.187->v1.0.193 allowlisted in scripts/github-action-pins.mjs) was already present at that head from a prior sweep commit 907ca970; checks were already green (Static PR checks/PR required/PR policy all success). Branch was 25 commits behind main; local merge tripped the pre-push ledger-write-discipline guard on the far-behind old remote tip (guardBaseForRange uses the branch's prior remote SHA for a fast-forward push, not mainMergeBase), so synced via authenticated GitHub update-branch API (human identity BigSimmo) instead of a local push, landing cleanly at bb5e4d115. Zero unresolved review threads (get_review_comments returned 0); the one PR comment is a stale 2026-08-17 ci-triage bot note superseded by the later fix commit, no reply needed. No conflicts, no code changes beyond the dependency-bump PR's own prior content. CI re-triggered on the new head and left running (not babysat) \u2014 Static PR checks/Semgrep/GitGuardian in_progress at handoff, PR mergeability and PR policy already green.", + "outcome": "Ledger throttle showed NOT REVIEWED at cda7ff21b. Found the substantive fix (claude-code-action pin v1.0.187->v1.0.193 allowlisted in scripts/github-action-pins.mjs) was already present at that head from a prior sweep commit 907ca970; checks were already green (Static PR checks/PR required/PR policy all success). Branch was 25 commits behind main; local merge tripped the pre-push ledger-write-discipline guard on the far-behind old remote tip (guardBaseForRange uses the branch's prior remote SHA for a fast-forward push, not mainMergeBase), so synced via authenticated GitHub update-branch API (human identity BigSimmo) instead of a local push, landing cleanly at bb5e4d115. Zero unresolved review threads (get_review_comments returned 0); the one PR comment is a stale 2026-08-17 ci-triage bot note superseded by the later fix commit, no reply needed. No conflicts, no code changes beyond the dependency-bump PR's own prior content. CI re-triggered on the new head and left running (not babysat) — Static PR checks/Semgrep/GitGuardian in_progress at handoff, PR mergeability and PR policy already green.", "checks": "npm run check:github-actions (pass), npm run check:ci-scope (pass), npm run check:pr-policy (pass); npm run check:ledger-write-discipline (pass, base=origin/main); local git merge-tree confirmed clean merge; no provider-backed checks run" }, { @@ -6449,7 +6491,7 @@ "ref": "gemini/therapy-compass-and-tooling-hardening (PR #2159)", "head": "f135f22cde36acbb3c9ab7d018565545708bb81c", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Before: real (git merge-tree confirmed) merge conflicts against origin/main in docs/launch-operator-runbook.md (stale search-health-index text vs the fix already merged via #2155) and docs/rag-evaluation.md (add/add \u2014 main independently gained the base doc while this branch extended it with a RAG Improvement Programme Board section; main's content was an exact prefix of this branch's version). Resolved: kept main's already-fixed runbook line, kept this branch's superset rag-evaluation.md content (main's text preserved verbatim as a prefix, extension section retained). Both playwright.config.ts and design-system docs auto-merged clean. After: merge commit pushed; typecheck clean; tests/design-system-adoption.test.ts 51/51 passed.", + "outcome": "Before: real (git merge-tree confirmed) merge conflicts against origin/main in docs/launch-operator-runbook.md (stale search-health-index text vs the fix already merged via #2155) and docs/rag-evaluation.md (add/add — main independently gained the base doc while this branch extended it with a RAG Improvement Programme Board section; main's content was an exact prefix of this branch's version). Resolved: kept main's already-fixed runbook line, kept this branch's superset rag-evaluation.md content (main's text preserved verbatim as a prefix, extension section retained). Both playwright.config.ts and design-system docs auto-merged clean. After: merge commit pushed; typecheck clean; tests/design-system-adoption.test.ts 51/51 passed.", "checks": "npx tsc --noEmit (clean), npx vitest run tests/design-system-adoption.test.ts (51 passed), diff verification that main's rag-evaluation.md content survived as an exact prefix. No provider-backed checks run." }, { @@ -6512,7 +6554,7 @@ "date": "2026-08-17", "ref": "claude/correct-056-staging-gap", "head": "6188086e6056c23aa0f7fe1655345c47e0068784", - "scope": "docs/outstanding-issues-inbox \u2014 #056 staging migration gap correction", + "scope": "docs/outstanding-issues-inbox — #056 staging migration gap correction", "outcome": "Remeasured read-only: staging ikoiolksxqxfxgiyqpnu holds 166 migrations (latest 20260719055623) against 192 repo files with 16 after that version, so the gap is 26 not 24 and the post-cutoff count is 16 not 14. Delta is new work landing on main, not a new defect, but the chain grows while the row stays open. Row now instructs re-measuring at window start rather than trusting its own figures.", "checks": "verify:pr-local (11 completed, 0 failed)" }, @@ -6521,7 +6563,7 @@ "ref": "claude/database-coordination-chat-9c0730", "head": "cef640f25aeee9b1fd8fc6c95a351ff1a6c348d3", "scope": "docs/database-remediation-coordination.md board re-baseline (#316), PR #2044", - "outcome": "coordinator self-review: docs-only, anchor corrected #312\u2192#316, board rebuilt from main record", + "outcome": "coordinator self-review: docs-only, anchor corrected #312→#316, board rebuilt from main record", "checks": "prettier --check pass; docs:check-links 1799 refs resolve" }, { @@ -6562,7 +6604,7 @@ "head": "77a631e960b55ef1c563ad85f6d4fc5551e1c98c", "scope": "theme-transition timer race in use-theme.ts causing Vitest unhandled-error failures", "outcome": "Fixed: guarded the 200ms theme-transitioning callback against a torn-down document and tracked/cleared the timer handle so rapid switches cannot end a later transition early", - "checks": "verify:pr-local exit 0 (649 files/6968 tests, no Errors line); red-green proved \u2014 new spec reproduces ReferenceError: document is not defined against the unfixed file (2 failed), passes 3/3 with the fix" + "checks": "verify:pr-local exit 0 (649 files/6968 tests, no Errors line); red-green proved — new spec reproduces ReferenceError: document is not defined against the unfixed file (2 failed), passes 3/3 with the fix" }, { "date": "2026-08-17", @@ -6585,15 +6627,15 @@ "ref": "claude/g1-rag-document-context-qn9ubx", "head": "f59b358d5ddba2480c585196b262afe1f4181632", "scope": "packet G1 document_context provenance tag + ledger issueRowFingerprint display-id fix + two queued G1 closures (supersedes the f5f146a record: two further commits landed on this branch)", - "outcome": "approved \u2014 G1 is a provenance tag only, deriveConfidence and synthetic_similarity_count unchanged and pinned; ledger fix restores issues:done for ULID-backed rows with null-safety preserved; no retrieval behaviour change, no canary per owner decision 2026-08-17 Option B", + "outcome": "approved — G1 is a provenance tag only, deriveConfidence and synthetic_similarity_count unchanged and pinned; ledger fix restores issues:done for ULID-backed rows with null-safety preserved; no retrieval behaviour change, no canary per owner decision 2026-08-17 Option B", "checks": "verify:pr-local all 18 stages green at this head; full unit 642 files / 6879 passed 4 skipped; eval:rag:offline 36 golden 25 suites 603/603; 4 G1 pins + 3 ledger pins mutation-checked" }, { "date": "2026-08-17", "ref": "claude/g1-rag-document-context-qn9ubx", "head": "f5f146a497a4ed04fc1db99b7b8f90a00a1cea30", - "scope": "packet G1 \u2014 document_context similarity_origin provenance tag (types.ts, answer-stream-contract.ts, rag-row-contracts.ts, rag.ts telemetry export) + 4 discriminating pins + H5a/HANDOVER docs", - "outcome": "approved \u2014 provenance tag only; deriveConfidence and synthetic_similarity_count unchanged and pinned; no retrieval behaviour change, no canary per owner decision 2026-08-17 Option B", + "scope": "packet G1 — document_context similarity_origin provenance tag (types.ts, answer-stream-contract.ts, rag-row-contracts.ts, rag.ts telemetry export) + 4 discriminating pins + H5a/HANDOVER docs", + "outcome": "approved — provenance tag only; deriveConfidence and synthetic_similarity_count unchanged and pinned; no retrieval behaviour change, no canary per owner decision 2026-08-17 Option B", "checks": "vitest 5 touched suites 58/58; full unit 642 files / 6879 passed 4 skipped; eval:rag:offline 36 golden 25 suites 603/603; check:rag:fixtures; verify:pr-local all 18 stages green (lint, typecheck, test, build, eval:rag:offline); 4 pins mutation-checked" }, { @@ -6601,7 +6643,7 @@ "ref": "claude/ledger-212-tranche-4-worker-q3y6i4", "head": "0e6e58ca4ac59768658ae4ad5b37a1266a09109b", "scope": "worker/row-contracts.ts, worker/main.ts, tests/worker-row-contract.test.ts", - "outcome": "approved \u2014 no defects found; concurrency/lease fencing, schema-constraint-backed contract pins, and safe-logging discipline all verified", + "outcome": "approved — no defects found; concurrency/lease fencing, schema-constraint-backed contract pins, and safe-logging discipline all verified", "checks": "npx vitest run tests/worker-row-contract.test.ts (28 passed); npx tsc -p tsconfig.json --noEmit (0 errors)" }, { @@ -6626,7 +6668,7 @@ "head": "edc17cc5f059868d31bf7c523be68d8b6449ecae", "scope": "Run PR sweep: babysit", "outcome": "No action needed. New PR discovered mid-sweep (opened by the owner during this sweep). CI green (PR required success), mergeable_state clean, not behind main, no review threads.", - "checks": "No local checks run \u2014 nothing to fix, CI already green." + "checks": "No local checks run — nothing to fix, CI already green." }, { "date": "2026-08-17", @@ -6673,7 +6715,7 @@ "ref": "claude/packet-s6-docling-lab-d6foa6", "head": "798725d04c85070f90c7496c5c7808713dd2d2a5", "scope": "eval/docling isolated Docling lab benchmark harness + Gate B decision-record template (packet S6/B3, PR #2057)", - "outcome": "PR #2057 open \u2014 harness only, no benchmark verdict; hard boundaries respected (worker/extractors/database untouched)", + "outcome": "PR #2057 open — harness only, no benchmark verdict; hard boundaries respected (worker/extractors/database untouched)", "checks": "verify:pr-local heavy plan failed:(none); check:docling-lab passed (36 fixtures/10 hostile/6 canaries); docling-lab-contract test 20/20; check:github-actions passed; legacy engine smoke 46 docs 10/10 hostile contained canary-clean" }, { @@ -6714,7 +6756,7 @@ "head": "6f1624386306abbf52b327a7abb8922b3a7778eb", "scope": "Run PR sweep: babysit", "outcome": "No action needed. CI was mid-run at first snapshot (Unit coverage in progress); left to settle rather than mutating. Re-checked: all required checks (PR required, Static PR checks, Unit coverage, Safety and config checks, PR policy) now green. Not behind main. No review threads.", - "checks": "No local checks run \u2014 nothing to fix, CI already green." + "checks": "No local checks run — nothing to fix, CI already green." }, { "date": "2026-08-17", @@ -6728,7 +6770,7 @@ "date": "2026-08-17", "ref": "claude/rag-d3-s5-followups", "head": "60e61bb9b89e2a62cefa7e89e8f6497c09e8a900", - "scope": "docs/rag-improvement S5 follow-ups: HANDOVER S5/S2 rows, COORDINATION \u00a77, 4 inbox requests (docs-only)", + "scope": "docs/rag-improvement S5 follow-ups: HANDOVER S5/S2 rows, COORDINATION §7, 4 inbox requests (docs-only)", "outcome": "docs-only; S5 landed; follow-ups queued", "checks": "verify:pr-local docs scope" }, @@ -6768,7 +6810,7 @@ "date": "2026-08-17", "ref": "claude/regrade-322-warfarin", "head": "5259f388992a1ed5f9d3ab757ccf40b21705326d", - "scope": "docs/outstanding-issues-inbox \u2014 #322 re-grade to P1 on traced evidence", + "scope": "docs/outstanding-issues-inbox — #322 re-grade to P1 on traced evidence", "outcome": "Traced data/medication-interaction-index.json and src/lib/medication-interactions.ts. The row's 'ZERO in common' claim is wrong - rows 0 and 2 are shared. Real defect is complementary incompleteness: warfarin-vka holds the CRITICAL CYP2C9 inducers row (carbamazepine, St John's Wort) and warfarin-anticoagulant holds the HIGH NSAID/Aspirin/SSRI row (12 counterparties, 6 SSRIs); neither holds the other's. Resolution is per-slug via INDEX.bySlug with no union (medication-interactions.ts:207,241), so which record is opened determines the warnings shown, and both display as Warfarin. Re-graded P2 to P1. Structural finding only; clinical correctness and the merge/delete/relabel decision left to the clinician.", "checks": "verify:pr-local (11 completed, 0 failed)" }, @@ -6793,7 +6835,7 @@ "ref": "claude/s1-rag-mitigation-231-86c182", "head": "6ddd45e5fd0725638c55684ca85833ddf78560c4", "scope": "RAG answer-verification faithfulness fixes (#231 S1): markdown-emphasis atom folding + claim-support wrap reflow, tests, HANDOVER S1 row", - "outcome": "PR #2022 open \u2014 rung 1 mitigation; residuals recorded (unbudgeted strong retry timeout, directive-normativity, topic dilution)", + "outcome": "PR #2022 open — rung 1 mitigation; residuals recorded (unbudgeted strong retry timeout, directive-normativity, topic dilution)", "checks": "eval:rag:offline 583/583; check:production-readiness READY; verify:pr-local heavy scope green except 2 pre-existing host-env unit failures reproduced at merge-base d02767184; 8 pre-fix + 5 post-fix owner-approved live probes" }, { @@ -6937,7 +6979,7 @@ "ref": "dependabot/docker/docker-images-263a700181 (PR #2013)", "head": "eb1874db74b9be0a2657e3913ab41003f402deb0", "scope": "Run PR sweep: CI diagnosis", - "outcome": "Not fixed \u2014 genuine incompatibility, not a bug: bumping the Dockerfile base image to node 26-bookworm-slim ships Node v26.7.0, but the repo's engine-strict floor pins Node >=24.15.0 <25 (AGENTS.md), so npm ci fails EBADENGINE in the container build. Needs an owner decision (reject the bump, or a deliberate repo-wide Node 26 migration), not a sweep-scoped code change. Left untouched; no review threads.", + "outcome": "Not fixed — genuine incompatibility, not a bug: bumping the Dockerfile base image to node 26-bookworm-slim ships Node v26.7.0, but the repo's engine-strict floor pins Node >=24.15.0 <25 (AGENTS.md), so npm ci fails EBADENGINE in the container build. Needs an owner decision (reject the bump, or a deliberate repo-wide Node 26 migration), not a sweep-scoped code change. Left untouched; no review threads.", "checks": "Diagnosed from CI job logs only (Container images / build-and-verify); no local reproduction attempted (Docker build), no provider-backed checks run." }, { @@ -6962,7 +7004,7 @@ "head": "1fb8035b9fdf6617705dd386f33158f20a3c334a", "scope": "Run PR sweep: drift sync", "outcome": "CI already green. Was behind main by 6 commits; synced via authenticated update-branch. No code fix needed, no review threads.", - "checks": "No local checks run \u2014 dependency-bump PR, CI already validated before sync; no provider-backed checks run." + "checks": "No local checks run — dependency-bump PR, CI already validated before sync; no provider-backed checks run." }, { "date": "2026-08-17", @@ -6986,14 +7028,14 @@ "head": "7df44e5c19c904247e0d0d1de40d338223820a95", "scope": "Run PR sweep: drift sync", "outcome": "CI already green (Static PR checks/Unit coverage/Build/Container images all success). Was behind main by 6 commits; synced via authenticated update-branch. No code fix needed, no review threads.", - "checks": "No local checks run \u2014 dependency-bump PR, CI already validated before sync; no provider-backed checks run." + "checks": "No local checks run — dependency-bump PR, CI already validated before sync; no provider-backed checks run." }, { "date": "2026-08-17", "ref": "gemini/clinical-data-lexicon-integrity (PR #2029)", "head": "1f903da31d9befb0cadebd7704447284d3c95bba", "scope": "Run PR sweep: threads + drift", - "outcome": "Partially fixed. Fixed 1 CodeRabbit review thread: tests/therapy-compass-pathways.test.ts modality-absence predicate incorrectly used '&& therapy.modality != null', letting a modality:null record slip past the field-removal assertion \u2014 changed to key-presence-only per the reviewer's own suggested diff. Was behind main by 3 commits; synced. NOT fixed, needs owner attention: (1) PR policy check fails \u2014 this diff regenerates data/medication-interaction-index.json (clinical-risk per classifyPullRequestFiles) but the PR body has no '## Clinical Governance Preflight' section; cannot fix by editing the PR body per Run PR guardrails. (2) This PR's TCAs dothiepin->dosulepin fix duplicates PR #2015 (claude/p1-318-lexicon-slug-and-guards), which already landed the same fix plus mutation-tested guards and full clinical governance documentation \u2014 flagging for owner triage rather than guessing which should win.", + "outcome": "Partially fixed. Fixed 1 CodeRabbit review thread: tests/therapy-compass-pathways.test.ts modality-absence predicate incorrectly used '&& therapy.modality != null', letting a modality:null record slip past the field-removal assertion — changed to key-presence-only per the reviewer's own suggested diff. Was behind main by 3 commits; synced. NOT fixed, needs owner attention: (1) PR policy check fails — this diff regenerates data/medication-interaction-index.json (clinical-risk per classifyPullRequestFiles) but the PR body has no '## Clinical Governance Preflight' section; cannot fix by editing the PR body per Run PR guardrails. (2) This PR's TCAs dothiepin->dosulepin fix duplicates PR #2015 (claude/p1-318-lexicon-slug-and-guards), which already landed the same fix plus mutation-tested guards and full clinical governance documentation — flagging for owner triage rather than guessing which should win.", "checks": "docs:check-links passed after sync. Test fix not locally re-run (no Node 24/vitest install in this sandbox); verified by hand-tracing against the reviewer's own executed verification script. No provider-backed checks run." }, { @@ -7009,7 +7051,7 @@ "ref": "gemini/design-tokens-source-contracts (PR #2031)", "head": "faa22eb3262d3951e398bbda6aa08108c8c574bc", "scope": "Run PR sweep: CI diagnosis", - "outcome": "Not fixed \u2014 diagnosed a real, measured Lighthouse regression that needs design/browser review, not a blind sweep fix: 'Lighthouse budget' job failed with mobile-root CLS 0.236 vs baseline 0.013 (+0.223, tolerance +/-0.02), confirmed on 2/3 samples, no other route regressed. The only functional diff in this PR is the mode-nav icon size migration (h-[1.0625rem] w-[1.0625rem] i.e. 17px -> size-icon-md i.e. --spacing-icon-md = 16px, in mode-nav.tsx and nav-slot-ink.tsx); everything else is test-helper refactors. That is the only plausible cause but a 1px icon-size change producing an 11x-over-tolerance CLS spike needs actual browser-rendered root-causing (hydration timing, a paint reflow this sandbox's headless-less environment cannot observe) before touching a protected icon-scale token, not a guess. No review threads. Was behind main by 2 commits at snapshot; left unsynced since there is nothing to push yet.", + "outcome": "Not fixed — diagnosed a real, measured Lighthouse regression that needs design/browser review, not a blind sweep fix: 'Lighthouse budget' job failed with mobile-root CLS 0.236 vs baseline 0.013 (+0.223, tolerance +/-0.02), confirmed on 2/3 samples, no other route regressed. The only functional diff in this PR is the mode-nav icon size migration (h-[1.0625rem] w-[1.0625rem] i.e. 17px -> size-icon-md i.e. --spacing-icon-md = 16px, in mode-nav.tsx and nav-slot-ink.tsx); everything else is test-helper refactors. That is the only plausible cause but a 1px icon-size change producing an 11x-over-tolerance CLS spike needs actual browser-rendered root-causing (hydration timing, a paint reflow this sandbox's headless-less environment cannot observe) before touching a protected icon-scale token, not a guess. No review threads. Was behind main by 2 commits at snapshot; left unsynced since there is nothing to push yet.", "checks": "Diagnosed from the CI job log for the Lighthouse budget job only; no local Chromium/Lighthouse available in this sandbox to reproduce. No provider-backed checks run." }, { @@ -7017,8 +7059,8 @@ "ref": "gemini/test-infra-tooling-hardening (PR #2030)", "head": "7bcd354401fb2cd4f5b3f328c3f61765db03cace", "scope": "Run PR sweep: threads + drift", - "outcome": "Fixed 5 of 6 CodeRabbit review threads (3 Major, 2 Minor): (1) findBranchTouchedRowIds() in check-ledger-stamp-retention.mjs only iterated commit-side rows and compared 3 of 7 fields, so a deleted ledger row was never marked touched \u2014 now iterates the union of base/commit IDs and compares raw+section. (2) checkLedgerStampRetention() silently reported ok:true/0-touched on an unresolvable merge-base instead of failing closed \u2014 now returns an explicit error, and the CLI path prints it before touching lostCount/lost. (3) readExpectedBrowserRevisions() in check-playwright-browser-revision.mjs silently omitted a browser family missing a revision instead of failing \u2014 now fails closed for chromium/firefox/webkit, with a new regression test. (4) tests/search-route-round-trip-budget.test.ts's non-vacuity guard asserted counter.total()>0 (also counts rate-limit/metadata/telemetry RPCs) instead of the two actual retrieval RPC names. (5) Added the missing check-ledger-stamp-retention.mjs entry to docs/scripts-index.md. Declined 1 finding (--filter option) as a false positive \u2014 no docstring, --help text, doc, or test anywhere advertises a --filter option for this script; replied asking the reviewer/owner to point at the source if one exists, left that thread open. CI was mid-run at first snapshot (Container images + 2 Production UI jobs in progress); pushed once assembled rather than mutating mid-run. Not behind main.", - "checks": "node scripts/check-ledger-stamp-retention.mjs --self-test passed; live run + deliberately-bad --base ref confirmed fail-closed behavior. node scripts/check-docs-links.mjs and update-docs-inventory.mjs --check passed. Vitest additions (2 new tests) not locally run (no Node 24/vitest install in this sandbox) \u2014 left for CI to verify. No provider-backed checks run." + "outcome": "Fixed 5 of 6 CodeRabbit review threads (3 Major, 2 Minor): (1) findBranchTouchedRowIds() in check-ledger-stamp-retention.mjs only iterated commit-side rows and compared 3 of 7 fields, so a deleted ledger row was never marked touched — now iterates the union of base/commit IDs and compares raw+section. (2) checkLedgerStampRetention() silently reported ok:true/0-touched on an unresolvable merge-base instead of failing closed — now returns an explicit error, and the CLI path prints it before touching lostCount/lost. (3) readExpectedBrowserRevisions() in check-playwright-browser-revision.mjs silently omitted a browser family missing a revision instead of failing — now fails closed for chromium/firefox/webkit, with a new regression test. (4) tests/search-route-round-trip-budget.test.ts's non-vacuity guard asserted counter.total()>0 (also counts rate-limit/metadata/telemetry RPCs) instead of the two actual retrieval RPC names. (5) Added the missing check-ledger-stamp-retention.mjs entry to docs/scripts-index.md. Declined 1 finding (--filter option) as a false positive — no docstring, --help text, doc, or test anywhere advertises a --filter option for this script; replied asking the reviewer/owner to point at the source if one exists, left that thread open. CI was mid-run at first snapshot (Container images + 2 Production UI jobs in progress); pushed once assembled rather than mutating mid-run. Not behind main.", + "checks": "node scripts/check-ledger-stamp-retention.mjs --self-test passed; live run + deliberately-bad --base ref confirmed fail-closed behavior. node scripts/check-docs-links.mjs and update-docs-inventory.mjs --check passed. Vitest additions (2 new tests) not locally run (no Node 24/vitest install in this sandbox) — left for CI to verify. No provider-backed checks run." }, { "date": "2026-08-17", @@ -7304,7 +7346,7 @@ "date": "2026-08-15", "ref": "claude/capture-ongoing-drop-question", "head": "367ef8e1414a3ebf81102884fa48298f16068093", - "scope": "docs/outstanding-issues-inbox \u2014 capture the unreconciled drift count", + "scope": "docs/outstanding-issues-inbox — capture the unreconciled drift count", "outcome": "Queued one P1 add request: check:drift reported missing_live 21 (2026-08-09) then 20 (2026-08-14) despite two indexes being restored between, so the expected figure was 19; the gap is consistent with an ongoing drop mechanism. Recorded as inference not fact. Carries a stop rule against beginning the restoration window until resolved. Filed as add rather than a #316 update to avoid colliding with the #316 update already queued in PR #1970.", "checks": "verify:pr-local (11 completed, 0 failed)" }, @@ -7313,7 +7355,7 @@ "ref": "claude/capture-ongoing-drop-question", "head": "8aead5c4fa3ed588f63860b3dc96f54ba415da44", "scope": "required base sync through main 17402395", - "outcome": "Approved \u2014 required main update merged; prior drift-inference review remains applicable with no PR-path conflict", + "outcome": "Approved — required main update merged; prior drift-inference review remains applicable with no PR-path conflict", "checks": "git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed" }, { @@ -7329,7 +7371,7 @@ "ref": "claude/db-remediation-phase-0-wfaiyl", "head": "1a8f7ae02c2bd7aa22e51edfb3b4a7b249ede578", "scope": "required base sync through main 17402395", - "outcome": "Approved \u2014 required main update merged; prior ledger guard remediation review remains applicable with no PR-path conflict", + "outcome": "Approved — required main update merged; prior ledger guard remediation review remains applicable with no PR-path conflict", "checks": "git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed" }, { @@ -7362,7 +7404,7 @@ "head": "6de09c409645cd854438c819250aa668b661568e", "scope": "DS gate 2: interactiveTapFloorDeclarations ratchet closing the h-10 case, plus GATES.md figure corrections (#265)", "outcome": "Gate 2 closed for new use; gate 8 stopped deliberately with the reason recorded; gate 7 untouched", - "checks": "verify:pr-local all 17 selected gates passed \u2014 unit suite 607 files / 6585 passed, 4 skipped; check:design-system-contract mutation-verified (interactiveTapFloorDeclarations increased from 41 to 42 plus the per-path line); check:gate-manifest OK at 35 gates / 32 static; no Chromium available (chromium-1194 vs pinned 1234, #255/#312) so no browser gate was claimed" + "checks": "verify:pr-local all 17 selected gates passed — unit suite 607 files / 6585 passed, 4 skipped; check:design-system-contract mutation-verified (interactiveTapFloorDeclarations increased from 41 to 42 plus the per-path line); check:gate-manifest OK at 35 gates / 32 static; no Chromium available (chromium-1194 vs pinned 1234, #255/#312) so no browser gate was claimed" }, { "date": "2026-08-15", @@ -7378,7 +7420,7 @@ "head": "41a1bd73749564954d7bf11143fd6541402f7691", "scope": "Tighten seven design-system ratchets to measured values after the #1982-#1986 merges", "outcome": "17 units of stale headroom removed; no metric relaxed", - "checks": "check:design-system-contract passed at the tightened values (sub-floor min-heights 40, edge conflicts 19, legacy shadow aliases 114); mutation-verified \u2014 min-h-9 on the shortlist Clear button now fails 'increased from 40 to 41' plus the per-path line, which the old pin of 43 allowed silently; check:gate-manifest OK; verify:pr-local 17 gates, unit suite 611 files / 6647 passed" + "checks": "check:design-system-contract passed at the tightened values (sub-floor min-heights 40, edge conflicts 19, legacy shadow aliases 114); mutation-verified — min-h-9 on the shortlist Clear button now fails 'increased from 40 to 41' plus the per-path line, which the old pin of 43 allowed silently; check:gate-manifest OK; verify:pr-local 17 gates, unit suite 611 files / 6647 passed" }, { "date": "2026-08-15", @@ -7386,7 +7428,7 @@ "head": "02672320db5a0b5b57b589e8d19d19c8c66483d4", "scope": "Favourites search-led workspace: retire marketing H1 and library nav, live in-place filter, dashboard band (#164)", "outcome": "Shipped; no P0-P2 findings", - "checks": "verify:pr-local all 10 selected gates passed \u2014 unit suite 607 files / 6584 passed, 4 skipped; check:design-system-contract passed with edgeOwnershipConflicts 25 to 24 from the deleted nav module; UI delegated to CI Production UI \u2014 chromium-1194 vs pinned 1234 (#255/#312)" + "checks": "verify:pr-local all 10 selected gates passed — unit suite 607 files / 6584 passed, 4 skipped; check:design-system-contract passed with edgeOwnershipConflicts 25 to 24 from the deleted nav module; UI delegated to CI Production UI — chromium-1194 vs pinned 1234 (#255/#312)" }, { "date": "2026-08-15", @@ -7417,7 +7459,7 @@ "ref": "claude/ledger-review-triage-yi63ao", "head": "02d2e7fc839cf370b512f66b255d5f9e9b42f377", "scope": "required base sync through main 17402395", - "outcome": "Approved \u2014 required main update merged; previous ledger issue-closure verification remains applicable with no PR-path conflict", + "outcome": "Approved — required main update merged; previous ledger issue-closure verification remains applicable with no PR-path conflict", "checks": "git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed" }, { @@ -7457,7 +7499,7 @@ "ref": "claude/rag-zod-hardening-tranche2", "head": "1a59ce0b128fbdabb9a24c3ea95c1123299693f3", "scope": "RAG row-contract CI follow-up: optional-signal assertion narrowing", - "outcome": "Fixed P1 \u2014 explicit local mismatch catches preserve both logged optional-signal degradation and TypeScript row narrowing", + "outcome": "Fixed P1 — explicit local mismatch catches preserve both logged optional-signal degradation and TypeScript row narrowing", "checks": "CI typecheck failure reproduced from exact-head log; git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed; local Vitest unavailable because node_modules/vitest is absent" }, { @@ -7465,7 +7507,7 @@ "ref": "claude/rag-zod-hardening-tranche2", "head": "20304ddc703fdc6913e1b62ad532b552ff919dac", "scope": "RAG row-contract tranche 2: optional signal shape-mismatch degradation; merged main", - "outcome": "Approved with P1 fix \u2014 malformed optional embedding-field/index-unit rows are logged and degrade to no signal candidates, preserving chunk retrieval; no ranking, ordering, or clinical-output contract changed", + "outcome": "Approved with P1 fix — malformed optional embedding-field/index-unit rows are logged and degrade to no signal candidates, preserving chunk retrieval; no ranking, ordering, or clinical-output contract changed", "checks": "manual adversarial control-flow review; git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed; targeted Vitest blocked: node_modules/vitest absent" }, { @@ -7473,7 +7515,7 @@ "ref": "claude/rag-zod-hardening-tranche2", "head": "671b0b99f7fdd33e83e5fa55a29470690c9243f2", "scope": "RAG row-contract tranche 2 P2: unconstrained JSON provenance acceptance", - "outcome": "Fixed P2 \u2014 index-unit source_span and metadata accept all JSON allowed by the database; non-object provenance is safely omitted from record-only downstream consumers", + "outcome": "Fixed P2 — index-unit source_span and metadata accept all JSON allowed by the database; non-object provenance is safely omitted from record-only downstream consumers", "checks": "manual adversarial review; focused scalar/array contract regression added; git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed; targeted Vitest blocked: node_modules/vitest absent" }, { @@ -7513,7 +7555,7 @@ "ref": "claude/rag-zod-hardening-tranche2", "head": "f4bc9033d5482922de60681d764eb5e6c6ebb73f", "scope": "rag-candidate-sources.ts signal-row Zod contracts (ledger #212 tranche 2) + 2 ledger captures", - "outcome": "Approved \u2014 3 unchecked RPC-result casts replaced with validated assertions; similarity_origin item deliberately excluded as a clinical-output behaviour change; no ranking/ordering/scoring logic touched", + "outcome": "Approved — 3 unchecked RPC-result casts replaced with validated assertions; similarity_origin item deliberately excluded as a clinical-output behaviour change; no ranking/ordering/scoring logic touched", "checks": "verify:pr-local all 18 steps green, zero failures; contract + rag-imputation-contract pins 21 passed; typecheck exit 0" }, { @@ -7544,8 +7586,8 @@ "date": "2026-08-15", "ref": "claude/services-search-redesign-163", "head": "d007d4a11a0d7b52283fe0088583259ef27c0264", - "scope": "Services bookmark readiness \u2014 correcting the 216a72e4 record", - "outcome": "PRIOR RECORD WAS FALSE. Record 216a72e4 claimed 'Fix service bookmark readiness and mutation race' at head 720e7027a9f08e518eb6344e74dfde35d78d5981. That object does not exist in this repository (git cat-file fails; not an ancestor of the branch) and src/components/services/ was byte-identical between 285e12d3c939 and the then-remote tip 87e7fcc2 \u2014 no fix had landed. The named defect was real and is fixed here instead", + "scope": "Services bookmark readiness — correcting the 216a72e4 record", + "outcome": "PRIOR RECORD WAS FALSE. Record 216a72e4 claimed 'Fix service bookmark readiness and mutation race' at head 720e7027a9f08e518eb6344e74dfde35d78d5981. That object does not exist in this repository (git cat-file fails; not an ancestor of the branch) and src/components/services/ was byte-identical between 285e12d3c939 and the then-remote tip 87e7fcc2 — no fix had landed. The named defect was real and is fixed here instead", "checks": "git cat-file -t on the claimed head: object does not exist; git diff 285e12d..87e7fcc2 -- src/components/services/: empty; new DOM regression test mutation-verified (reverting the gate fails it); focused vitest 12/12; typecheck clean" }, { @@ -7553,8 +7595,8 @@ "ref": "claude/services-search-redesign-163", "head": "f9391318605f4a2cf743cc7a6b3448b61a8296d4", "scope": "Services search results: progressive referral rail, compact rows, favourites bookmark (#163)", - "outcome": "Shipped; row re-measured as half-stale before building \u2014 no P0-P2 findings", - "checks": "verify:pr-local all 10 selected gates passed (runtime, lock parity, format:changed, lint, typecheck, test, build, rag fixtures, medication interactions, lexicon report); focused vitest 22/22 across services scope-empty-state, services regressions audit, band adoption, route reachability; check:design-system-contract passed at 25 edge conflicts unchanged; UI delegated to CI Production UI \u2014 chromium-1194 vs pinned 1234 (#255/#312)" + "outcome": "Shipped; row re-measured as half-stale before building — no P0-P2 findings", + "checks": "verify:pr-local all 10 selected gates passed (runtime, lock parity, format:changed, lint, typecheck, test, build, rag fixtures, medication interactions, lexicon report); focused vitest 22/22 across services scope-empty-state, services regressions audit, band adoption, route reachability; check:design-system-contract passed at 25 edge conflicts unchanged; UI delegated to CI Production UI — chromium-1194 vs pinned 1234 (#255/#312)" }, { "date": "2026-08-15", @@ -7570,7 +7612,7 @@ "head": "22aa7c627e4d3ce220c741d4246d998956249fd2", "scope": "Guarded source-slice test windows: shared helper plus three migrations (#1985)", "outcome": "Shipped; closes a silent-pass class in the contract tests, remainder queued", - "checks": "verify:pr-local all 9 selected gates passed \u2014 unit suite 6608 passed / 4 skipped; helper's own test pins the raw idiom returning out-of-window content; migrated files re-run green (17/17, 23/23)" + "checks": "verify:pr-local all 9 selected gates passed — unit suite 6608 passed / 4 skipped; helper's own test pins the raw idiom returning out-of-window content; migrated files re-run green (17/17, 23/23)" }, { "date": "2026-08-15", @@ -7617,7 +7659,7 @@ "ref": "codex/calculators-mode", "head": "9dc3891ee8bc30a35fdb203607cdd984d3a24cc3", "scope": "calculator command-surface P1/P2 follow-up: suggestion submit and footer ownership docs", - "outcome": "Fixed P1/P2 \u2014 selected calculator suggestions pass their exact text into navigation; chrome ownership docs no longer describe calculators as page-owned footers", + "outcome": "Fixed P1/P2 — selected calculator suggestions pass their exact text into navigation; chrome ownership docs no longer describe calculators as page-owned footers", "checks": "manual control-flow review; focused DOM regression added; git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed; focused Vitest blocked: node_modules/vitest absent" }, { @@ -7625,7 +7667,7 @@ "ref": "codex/calculators-mode", "head": "bbf2207102a0b40b5ba048e8e9a04f37add9bf2c", "scope": "required base sync through main 3824095", - "outcome": "Approved \u2014 required main update merged after calculator command follow-ups; no PR-path conflict", + "outcome": "Approved — required main update merged after calculator command follow-ups; no PR-path conflict", "checks": "git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed" }, { @@ -7633,7 +7675,7 @@ "ref": "codex/calculators-mode", "head": "d8fde21e65ce010b72bc56f1e57334cdfac764c5", "scope": "required base sync through main 17402395", - "outcome": "Approved \u2014 required main update merged; prior calculator-mode review remains applicable with no PR-path conflict", + "outcome": "Approved — required main update merged; prior calculator-mode review remains applicable with no PR-path conflict", "checks": "git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed" }, { @@ -7657,7 +7699,7 @@ "ref": "codex/differential-results-ui-20260814", "head": "8bba4d60586c102a8d42e208c7bd73fb0b52046b", "scope": "Differentials results evidence-state, clinical-cue, and ranking presentation", - "outcome": "Fixed three validated P2 findings: evidence-gated best-match success styling, clinical-cue-only labels, and A\u2013Z display rank.", + "outcome": "Fixed three validated P2 findings: evidence-gated best-match success styling, clinical-cue-only labels, and A–Z display rank.", "checks": "git diff --check; direct Node source-contract assertions; targeted Vitest attempted but unavailable because this isolated worktree has no node_modules/vitest" }, { @@ -7673,7 +7715,7 @@ "ref": "codex/differential-results-ui-20260814", "head": "cc68da45cf37c5fbb6e588106e9d3bf8ab8004c3", "scope": "required base sync through main 17402395", - "outcome": "Approved \u2014 required main update merged; prior focused UI review remains applicable with no PR-path conflict", + "outcome": "Approved — required main update merged; prior focused UI review remains applicable with no PR-path conflict", "checks": "git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed" }, { @@ -7777,7 +7819,7 @@ "ref": "codex/fix-documents-without-live-images", "head": "a42f45955ad8595ccd17ac4fea2ea0d6fd2c2f3f", "scope": "required base sync through main 17402395", - "outcome": "Approved \u2014 required main update merged; prior document-cover repair review remains applicable with no PR-path conflict", + "outcome": "Approved — required main update merged; prior document-cover repair review remains applicable with no PR-path conflict", "checks": "git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed" }, { @@ -7817,7 +7859,7 @@ "ref": "codex/medication-info-header-20260814", "head": "9c1bfe7154eb36e890b4d4e8d61d83da7ba6c926", "scope": "required base sync through main 17402395", - "outcome": "Approved \u2014 required main update merged; prior focused medication-header review remains applicable with no PR-path conflict", + "outcome": "Approved — required main update merged; prior focused medication-header review remains applicable with no PR-path conflict", "checks": "git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed" }, { @@ -7897,7 +7939,7 @@ "ref": "codex/pwa-install-polish-20260815", "head": "c6d8c2829ddd2fc52441a3696aed56fbd0262917", "scope": "required base sync through main 17402395", - "outcome": "Approved \u2014 required main update merged; prior PWA lifecycle review and style-inventory repair remain applicable with no PR-path conflict", + "outcome": "Approved — required main update merged; prior PWA lifecycle review and style-inventory repair remain applicable with no PR-path conflict", "checks": "git diff --check; ci-change-scope self-test; ledger/inbox/outstanding/discipline guards passed" }, { @@ -8008,7 +8050,7 @@ "date": "2026-08-14", "ref": "claude/archive-inflight-verified", "head": "2b44e8085ac0e356d43a3180527da2d92cb4af66", - "scope": "docs/outstanding-issues-inbox \u2014 retire stale IN FLIGHT annotations", + "scope": "docs/outstanding-issues-inbox — retire stale IN FLIGHT annotations", "outcome": "Verified 11 IN FLIGHT rows against code on main. Archived 8 as delivered (#178 #209 #221 #233 #234 #235 #237 #238) with file:line evidence, 1 as intentional-by-design (#245). Kept #150 open (account state, not code-verifiable) and #162 open (PR #1839 genuinely still open). Queued as immutable inbox requests.", "checks": "verify:pr-local (11 completed, 0 failed)" }, @@ -8016,7 +8058,7 @@ "date": "2026-08-14", "ref": "claude/capture-drift-phase1-evidence", "head": "00f5612ccf982441cf98ec6ca1c51d68ba2add6a", - "scope": "docs/audit/live-drift-forensics-2026-08.md + inbox \u2014 Phase 1.2/1.3 evidence capture", + "scope": "docs/audit/live-drift-forensics-2026-08.md + inbox — Phase 1.2/1.3 evidence capture", "outcome": "Filled 1.2 (was Pending): 93 functions compared, 0 missing/0 extra/16 mismatches, 6 proven normalization noise, 10 real and UNCLASSIFIED, confirming #316's figure of 10. Extended 1.3: 210 repo vs 192 live indexes, 20 still absent after the incident repair, zero invalid indexes, all five creating migrations recorded executed DDL. Root cause left unestablished. #316/#248 queued as inbox requests. Read-only throughout; no writes to the database.", "checks": "verify:pr-local (11 completed, 0 failed)" }, @@ -8024,7 +8066,7 @@ "date": "2026-08-14", "ref": "claude/correct-rejected-closures", "head": "e4372b5b4e1e382ec28b79e326a0ae1f2a9901ba", - "scope": "docs/outstanding-issues-inbox \u2014 corrections for rejected closures and stale #231", + "scope": "docs/outstanding-issues-inbox — corrections for rejected closures and stale #231", "outcome": "Queued 4 update requests. #235/#237/#238 record the rejected closure, its reason, and a Stop rule naming the evidence class that must not be reused; all three drop the stale IN FLIGHT prefix (PRs #1841/#1842 merged). #231 records that scripts/probe-generation-quality.ts now exists (a3bc4da) and PR #1861 was adjudicated superseded for phase 1, so the row no longer asks for an instrument that exists.", "checks": "verify:pr-local (11 completed, 0 failed; first run correctly failed check:ledger-write-discipline on uncommitted edits)" }, @@ -8057,7 +8099,7 @@ "ref": "claude/disabled-button-accessibility-piclvr (PR #1928)", "head": "1988c762dfa763a38ec1b95cc9855b0db47f2054", "scope": "PR #1928 heavy review: outstanding-issues inbox count accuracy (docs only)", - "outcome": "P2 fixed \u2014 durable summary corrected from four controls to four groups covering nine controls; no other actionable defects; no unresolved review threads", + "outcome": "P2 fixed — durable summary corrected from four controls to four groups covering nine controls; no other actionable defects; no unresolved review threads", "checks": "manual adversarial source pass; JSON parse + schema/count assertions; exact-head PR required CI green before fix; no provider-backed gates run" }, { @@ -8065,7 +8107,7 @@ "ref": "claude/fetch-stream-catch-cleanup", "head": "53ed54137fde3cb5ee7f8e177d85ba0f177593c6", "scope": "empty catch disposition (src/lib/theme.ts, src/app/layout.tsx) + new tests/empty-catch-disposition.test.ts contract guard + issues:done request for #213", - "outcome": "Approved \u2014 3 bare catches dispositioned with inline comments; no behaviour change. Finding: all 3 were inline-script storage/cookie reads, not fetch/stream swallowing as #213 described; the genuine fetch/stream catches were already dispositioned. New raw-source-text contract test guards the population (0 bare, 21 total).", + "outcome": "Approved — 3 bare catches dispositioned with inline comments; no behaviour change. Finding: all 3 were inline-script storage/cookie reads, not fetch/stream swallowing as #213 described; the genuine fetch/stream catches were already dispositioned. New raw-source-text contract test guards the population (0 bare, 21 total).", "checks": "verify:pr-local (all gates pass except pre-existing check:medication-lexicon-report, inputs byte-identical to origin/main); npm run test 602 files / 6511 passed / 4 skipped; new contract test 2 passed" }, { @@ -8073,8 +8115,8 @@ "ref": "claude/fetch-stream-catch-cleanup", "head": "f05c2d58fc70465a52cbb23306179b5420c3a95c", "scope": "empty catch disposition + contract guard + regenerated docs/medication-interaction-lexicon-review.md", - "outcome": "Approved \u2014 supersedes the 53ed541 record after adding the lexicon-report regeneration. 3 bare catches dispositioned inline (no behaviour change); finding recorded that all 3 were inline-script storage/cookie reads, not the fetch/stream swallowing #213 described. Lexicon report drift was pre-existing on main and a pure re-wrap (whitespace-normalised files are byte-identical); classifyPullRequestFiles reports clinicalRisk false with or without it.", - "checks": "verify:pr-local on final head: failed (none) \u2014 all 18 gates pass including check:medication-lexicon-report; npm run test 602 files / 6511 passed / 4 skipped" + "outcome": "Approved — supersedes the 53ed541 record after adding the lexicon-report regeneration. 3 bare catches dispositioned inline (no behaviour change); finding recorded that all 3 were inline-script storage/cookie reads, not the fetch/stream swallowing #213 described. Lexicon report drift was pre-existing on main and a pure re-wrap (whitespace-normalised files are byte-identical); classifyPullRequestFiles reports clinicalRisk false with or without it.", + "checks": "verify:pr-local on final head: failed (none) — all 18 gates pass including check:medication-lexicon-report; npm run test 602 files / 6511 passed / 4 skipped" }, { "date": "2026-08-14", @@ -8097,8 +8139,8 @@ "ref": "claude/ledger-merge-loss-finding", "head": "7a8d57da01b3221c61c87d2f14ace392ab33fb67", "scope": "ledger merge-loss finding", - "outcome": "PR #1937 \u2014 one immutable inbox request (P2 issue) recording that a queued outstanding-issues request was created on a branch and never reached main through that branch's squash. Verified before writing: the request's own remedies had already shipped on main independently (hook guards CLAUDE_ENV_FILE; check:runtime names the hook), so the request was NOT re-queued verbatim \u2014 a re-queue would have opened an already-resolved row. The row filed instead is about the undetected loss itself. Docs-only; no source changes.", - "checks": "npm run verify:pr-local \u2014 failed: (none), 11 checks completed; ledger inbox check passed: 76 pending request(s), 19 applied" + "outcome": "PR #1937 — one immutable inbox request (P2 issue) recording that a queued outstanding-issues request was created on a branch and never reached main through that branch's squash. Verified before writing: the request's own remedies had already shipped on main independently (hook guards CLAUDE_ENV_FILE; check:runtime names the hook), so the request was NOT re-queued verbatim — a re-queue would have opened an already-resolved row. The row filed instead is about the undetected loss itself. Docs-only; no source changes.", + "checks": "npm run verify:pr-local — failed: (none), 11 checks completed; ledger inbox check passed: 76 pending request(s), 19 applied" }, { "date": "2026-08-14", @@ -8129,16 +8171,16 @@ "ref": "claude/ledger-process-tooling-50uqfc", "head": "93365d6e4e496c233e629d85a572f3feb08513cf", "scope": "outstanding-issues reconciliation of 35 queued requests (fresh base 0011a058)", - "outcome": "PR #1956 \u2014 one serial reconciliation transaction from a fresh origin/main base, restarting the branch after its previous PR (#1944) merged as squash 372cb13f. 35 requests applied: 17 done, 7 add, 6 update, 5 cancel; ledger 328 to 334 rows, 115 to 99 open. Machine-generated and machine-verified end to end; no request or canonical row was hand-edited. Includes the five requests PR #1944 left pending: closes #313, carries #211 forward with a re-measured 1,445 errors while keeping its deprioritisation and P3 priority, records #168 and #258 without closing either, and opens #335. One request deliberately not re-filed: cancel a8783c79, whose target 0e47904b was already consumed by the reconcile in PR #1936, making it invalid; nothing lost because the surviving #211 update folds its text forward. Visual HTML register NOT refreshed \u2014 its PowerShell refresh script is a Windows path unavailable in this Linux container; Markdown source is current, artifact is stale.", - "checks": "npm run verify:pr-local \u2014 11 gates completed, 0 failed; npm run check:ledger-write-discipline printed \"Ledger write discipline passed for 0011a058fd1d..HEAD\", independently recomputing the transaction; check:outstanding-issues 334 rows (99 open, 235 archived), unique ids, next-id=337 above the highest, 0 pending requests, 129 applied; the pre-existing check:medication-lexicon-report failure seen on PR #1944 is gone, confirming PR #1941 fixed it at source. Note: run before committing, check:ledger-write-discipline correctly REFUSED to report a verdict and named every uncommitted request file \u2014 the guard PR #1944 shipped, working on the first real reconciliation after it landed." + "outcome": "PR #1956 — one serial reconciliation transaction from a fresh origin/main base, restarting the branch after its previous PR (#1944) merged as squash 372cb13f. 35 requests applied: 17 done, 7 add, 6 update, 5 cancel; ledger 328 to 334 rows, 115 to 99 open. Machine-generated and machine-verified end to end; no request or canonical row was hand-edited. Includes the five requests PR #1944 left pending: closes #313, carries #211 forward with a re-measured 1,445 errors while keeping its deprioritisation and P3 priority, records #168 and #258 without closing either, and opens #335. One request deliberately not re-filed: cancel a8783c79, whose target 0e47904b was already consumed by the reconcile in PR #1936, making it invalid; nothing lost because the surviving #211 update folds its text forward. Visual HTML register NOT refreshed — its PowerShell refresh script is a Windows path unavailable in this Linux container; Markdown source is current, artifact is stale.", + "checks": "npm run verify:pr-local — 11 gates completed, 0 failed; npm run check:ledger-write-discipline printed \"Ledger write discipline passed for 0011a058fd1d..HEAD\", independently recomputing the transaction; check:outstanding-issues 334 rows (99 open, 235 archived), unique ids, next-id=337 above the highest, 0 pending requests, 129 applied; the pre-existing check:medication-lexicon-report failure seen on PR #1944 is gone, confirming PR #1941 fixed it at source. Note: run before committing, check:ledger-write-discipline correctly REFUSED to report a verdict and named every uncommitted request file — the guard PR #1944 shipped, working on the first real reconciliation after it landed." }, { "date": "2026-08-14", "ref": "claude/ledger-process-tooling-50uqfc", "head": "d36914a79fa4304273429aab0d7f271010f3bb96", "scope": "ledger process tooling bundle (#313 dirty-tree gate, 829597d4 merge-loss detector, #211/#168/#258 plans)", - "outcome": "PR #1944 \u2014 five separate commits, each independently revertible. Two code items: check-ledger-write-discipline.mjs now refuses a verdict while a governed ledger path is dirty (gated on default HEAD so guard-push.mjs explicit --head and clean CI are unaffected); new scripts/audit-merge-loss.mjs advisory blob-comparison sweep, exits 0 and asks for human confirmation, not wired into CI or verify:cheap by design. Three docs-only plans. Found and fixed during build: the shared git() helper trim() was corrupting porcelain status parsing, and JSDoc types were needed to stop TS inferring never[] for the classifier landings parameter. Noted: classifyPullRequestFiles reports operationalRisk true solely from the package.json script entry.", - "checks": "npm run verify:pr-local \u2014 18 gates completed, 1 failed: check:medication-lexicon-report, reproduced identically in a clean detached worktree at origin/main d47aa6d so pre-existing and not caused here; tests/ledger-write-discipline.test.ts 9 passed; tests/merge-loss-audit.test.ts 14 passed; both script self-tests passed; audit:merge-loss --since 6 independently rediscovered the acf78bf casualties #1803/#1800/#1804/#1796/#1811" + "outcome": "PR #1944 — five separate commits, each independently revertible. Two code items: check-ledger-write-discipline.mjs now refuses a verdict while a governed ledger path is dirty (gated on default HEAD so guard-push.mjs explicit --head and clean CI are unaffected); new scripts/audit-merge-loss.mjs advisory blob-comparison sweep, exits 0 and asks for human confirmation, not wired into CI or verify:cheap by design. Three docs-only plans. Found and fixed during build: the shared git() helper trim() was corrupting porcelain status parsing, and JSDoc types were needed to stop TS inferring never[] for the classifier landings parameter. Noted: classifyPullRequestFiles reports operationalRisk true solely from the package.json script entry.", + "checks": "npm run verify:pr-local — 18 gates completed, 1 failed: check:medication-lexicon-report, reproduced identically in a clean detached worktree at origin/main d47aa6d so pre-existing and not caused here; tests/ledger-write-discipline.test.ts 9 passed; tests/merge-loss-audit.test.ts 14 passed; both script self-tests passed; audit:merge-loss --since 6 independently rediscovered the acf78bf casualties #1803/#1800/#1804/#1796/#1811" }, { "date": "2026-08-14", @@ -8152,7 +8194,7 @@ "date": "2026-08-14", "ref": "claude/ledger-reconcile-batch-1", "head": "00c09a30f91427b3154b64812b73294847265778", - "scope": "docs/outstanding-issues.md + inbox \u2014 serial reconciliation of 75 queued requests", + "scope": "docs/outstanding-issues.md + inbox — serial reconciliation of 75 queued requests", "outcome": "Applied 63 active mutations (14 add, 23 done, 26 update) plus 6 cancellation decisions. Ledger 115 open/199 archived -> 106/222; inbox 0 pending/94 applied. Verified zero live same-target collisions before applying, since planRequestBatch dedupes on request UUID not canonical row id.", "checks": "issues:reconcile --dry-run; verify:pr-local (11 completed, 0 failed); check:ledger-write-discipline" }, @@ -8160,7 +8202,7 @@ "date": "2026-08-14", "ref": "claude/ledger-reconcile-batch-2", "head": "af68b3271922656ef97312dae513a3f6906aec76", - "scope": "docs/outstanding-issues.md + inbox \u2014 second serial reconciliation of 35 queued requests", + "scope": "docs/outstanding-issues.md + inbox — second serial reconciliation of 35 queued requests", "outcome": "Applied 25 active mutations (13 done, 6 add, 6 update) plus 5 cancellation decisions. Ledger 106 open/222 archived -> 99/235; inbox 0 pending/129 applied. Three closures queued in PR #1940 (#235 #237 #238) were cancelled by review and stay open: each asked for visual or browser proof and had been closed on executable evidence. Zero live same-target collisions verified before applying.", "checks": "issues:reconcile --dry-run; verify:pr-local (11 completed, 0 failed); check:ledger-write-discipline" }, @@ -8168,8 +8210,8 @@ "date": "2026-08-14", "ref": "claude/ledger-reconcile-batch-3", "head": "be94fbbb31843f4593783b9ca388ee0526b74e84", - "scope": "docs/outstanding-issues.md + inbox \u2014 reconcile the four rejected-closure corrections", - "outcome": "Applied 4 update requests from PR #1957, no cancellations, zero live collisions. #235/#237/#238 now carry the rejected closure, its reason and a Stop rule naming the evidence class; #231 records the probe script and the #1861 adjudication. Row counts unchanged at 99 open/235 archived by design \u2014 detail rewrites, not archives. Inbox 0 pending/133 applied.", + "scope": "docs/outstanding-issues.md + inbox — reconcile the four rejected-closure corrections", + "outcome": "Applied 4 update requests from PR #1957, no cancellations, zero live collisions. #235/#237/#238 now carry the rejected closure, its reason and a Stop rule naming the evidence class; #231 records the probe script and the #1861 adjudication. Row counts unchanged at 99 open/235 archived by design — detail rewrites, not archives. Inbox 0 pending/133 applied.", "checks": "issues:reconcile --dry-run; verify:pr-local (11 completed, 0 failed); check:ledger-write-discipline" }, { @@ -8209,7 +8251,7 @@ "ref": "claude/rag-zod-hardening-tranche1", "head": "0fded0878b6f8e35ef50b8c97a63af6e78e1f716", "scope": "rag.ts retrieval RPC row Zod shape contract (ledger #212 tranche 1)", - "outcome": "Approved \u2014 4 unchecked as SearchResult[] casts on retrieval RPC rows replaced with assertRetrievalRows; no ranking/ordering/scoring logic touched", + "outcome": "Approved — 4 unchecked as SearchResult[] casts on retrieval RPC rows replaced with assertRetrievalRows; no ranking/ordering/scoring logic touched", "checks": "verify:pr-local (all steps green except pre-existing check:medication-lexicon-report staleness on main); test 602 files/6517 passed; typecheck exit 0; eval:rag:offline 36 golden cases 23 suites, 579 passed" }, { @@ -8344,8 +8386,8 @@ "date": "2026-08-14", "ref": "PR #1965 (claude/playwright-browser-revision-check)", "head": "24e8fd040949564e2c07fccfe6d243e386815b6e", - "scope": "scripts/check-playwright-browser-revision.mjs, tests/check-playwright-browser-revision.test.ts \u2014 ledger #312 fix", - "outcome": "authored \u2014 verified real Chromium binary presence check on disk; reproduced original false-OK bug live against this session's /opt/pw-browsers container (chromium-1194 present, pinned revision 1234 missing)", + "scope": "scripts/check-playwright-browser-revision.mjs, tests/check-playwright-browser-revision.test.ts — ledger #312 fix", + "outcome": "authored — verified real Chromium binary presence check on disk; reproduced original false-OK bug live against this session's /opt/pw-browsers container (chromium-1194 present, pinned revision 1234 missing)", "checks": "verify:pr-local (runtime, lock-parity, format, lint, typecheck, test 602 files/6518 passed/4 skipped, rag:fixtures, medication-interactions PASS; medication-lexicon-report pre-existing unrelated FAIL); focused vitest check-playwright-browser-revision.test.ts 10/10, playwright-browser-preflight.test.ts 12/12" }, { @@ -8465,7 +8507,7 @@ "ref": "PR-1959", "head": "428fa8772198817e17ef6330c63f7f5e47e090b0", "scope": "PR #1959 base-preserving reconciliation review", - "outcome": "Required base sync resolved the sole ledger conflict with main: all four inbox requests were already applied upstream; preserved main\u2019s newer #231 evidence and retained the existing immutable historical record.", + "outcome": "Required base sync resolved the sole ledger conflict with main: all four inbox requests were already applied upstream; preserved main’s newer #231 evidence and retained the existing immutable historical record.", "checks": "docs link check passed: 1776 repo path references resolve; Ledger inbox check passed: 12 pending request(s), 138 applied; branch-review-ledger self-test passed; Branch review ledger guard passed: 880 live table records + 1206 archived + 92 immutable; verify:pr-local unavailable: tsx/cli absent from isolated worktree (Node v24.14.0)." }, { @@ -8473,7 +8515,7 @@ "ref": "PR-1961", "head": "ed6ad9a0f81b079568534db78283fec93b956c67", "scope": "PR #1961 base-preserving reconciliation sync", - "outcome": "Required base sync retained the current canonical ledger: all 35 reconciliation records and the #310 correction were already present upstream; preserved only the branch\u2019s new pending Prettier-version-trap request.", + "outcome": "Required base sync retained the current canonical ledger: all 35 reconciliation records and the #310 correction were already present upstream; preserved only the branch’s new pending Prettier-version-trap request.", "checks": "docs link check passed: 1775 repo path references resolve; Ledger inbox check passed: 23 pending request(s), 138 applied; branch-review-ledger self-test passed; Branch review ledger guard passed: 880 live table records + 1206 archived + 99 immutable; verify:pr-local unavailable: tsx/cli absent from isolated worktree (Node v24.14.0)." }, { @@ -8489,7 +8531,7 @@ "ref": "PR-1964", "head": "1dfc0c9b984152f6518060712ab050311f3f77c9", "scope": "vitest.config.mts, docs/maturity-backlog-workorders.md (ledger #192 / maturity X6 coverage floors)", - "outcome": "APPROVED \u2014 coverage-threshold re-ratchet, no RAG/clinical behaviour change; verify:pr-local green except pre-existing unrelated check:medication-lexicon-report staleness", + "outcome": "APPROVED — coverage-threshold re-ratchet, no RAG/clinical behaviour change; verify:pr-local green except pre-existing unrelated check:medication-lexicon-report staleness", "checks": "test:coverage,verify:pr-local" }, { @@ -8512,7 +8554,7 @@ "date": "2026-08-13", "ref": "claude/design-issues-triage-wnr7k9", "head": "615893b24fa2be21e245ef1e47ae2fa1e2e12981", - "scope": "docs/outstanding-issues-inbox \u2014 #210 correction", + "scope": "docs/outstanding-issues-inbox — #210 correction", "outcome": "Corrected #210: typecheck half already fixed by tsconfig.typecheck.json; the prescribed tsconfig.json include edit is reverted by Next (type-paths.js:34-36 + writeConfigurationDefaults.js:305-315). Remaining Playwright-isolated-tsconfig half recorded as not proven end-to-end. Queued as immutable inbox request.", "checks": "verify:pr-local (all 11 completed, 0 failed)" }, @@ -8521,7 +8563,7 @@ "ref": "claude/disabled-button-accessibility-piclvr", "head": "c73bba958e26e706c4957c886c9974ffcf330943", "scope": "outstanding-issues inbox request capturing the four placeholder controls #291 left native (docs only)", - "outcome": "authored \u2014 PR #1928 opened", + "outcome": "authored — PR #1928 opened", "checks": "verify:pr-local 11/11 completed, none failed; check:outstanding-issues; check:ledger-write-discipline (re-run post-commit); prettier --check clean" }, { @@ -8577,7 +8619,7 @@ "ref": "claude/ledger-tasks-fable-xhl7xb", "head": "6f1cd23a34dca2fa3ae9d676d4dace46fd779d3a", "scope": "ledger intake: merge-loss capture (4 inbox requests)", - "outcome": "clean \u2014 additive JSON intake only, no canonical ledger edit", + "outcome": "clean — additive JSON intake only, no canonical ledger edit", "checks": "verify:pr-local (all 11 gates, none failed); dry-apply of 23 pending requests against origin/main" }, { @@ -8969,7 +9011,7 @@ "ref": "claude/design-issues-triage-wnr7k9", "head": "586012639565e4d3306b44361ebc5a3bdb3024ad", "scope": "Land PR #1838 ledger sweep; close #147 mobile CLS by measurement", - "outcome": "Merge resolved as union (main renumbered #302/#303 to #306/#307 \u2014 not lost, correcting an earlier claim); #306/#307 archived as already-delivered. #147 archived on two identical offline Lighthouse runs: mobile CLS 0.035/0.000/0.013/0.081/0.000, all under 0.1, cause fixed by PR #1616 not this session. #118 updated (browser drift 141-vs-151, wider than recorded); new #308 for desktop /documents/search CLS 0.119", + "outcome": "Merge resolved as union (main renumbered #302/#303 to #306/#307 — not lost, correcting an earlier claim); #306/#307 archived as already-delivered. #147 archived on two identical offline Lighthouse runs: mobile CLS 0.035/0.000/0.013/0.081/0.000, all under 0.1, cause fixed by PR #1616 not this session. #118 updated (browser drift 141-vs-151, wider than recorded); new #308 for desktop /documents/search CLS 0.119", "checks": "verify:pr-local 10/10 green; check:outstanding-issues 121 open/185 archived; verify:lighthouse x2 (gate ungraded on browser drift, measurements valid)" }, { @@ -9201,7 +9243,7 @@ "ref": "PR #1888 (claude/filter-contract-factsheets-pr-d)", "head": "95515078031b4bd29d90f05986dc5eb3a36ce660", "scope": "factsheets category counts, filter-contract correction, desktop-rail exception decision", - "outcome": "Filter contract PR D \u2014 corrected the earlier false claim that factsheets' category presets discard the query and need eviction (searchHref preserves q); kept the desktop rail as real Link elements rather than converging to SegmentedControl because /factsheets/search is a genuine server-rendered searchParams route, recorded as a documented exception in filter-contract.md; added per-query category counts to both breakpoints from one shared options array. verify:pr-local full green pre- and post-merge; bundle budget within tolerance; UI proved with pinned-Chromium Playwright (11/11) and the updated ui-smoke.spec.ts factsheets test against a real build. /issues #170 updated to correct its own stale factsheets claim.", + "outcome": "Filter contract PR D — corrected the earlier false claim that factsheets' category presets discard the query and need eviction (searchHref preserves q); kept the desktop rail as real Link elements rather than converging to SegmentedControl because /factsheets/search is a genuine server-rendered searchParams route, recorded as a documented exception in filter-contract.md; added per-query category counts to both breakpoints from one shared options array. verify:pr-local full green pre- and post-merge; bundle budget within tolerance; UI proved with pinned-Chromium Playwright (11/11) and the updated ui-smoke.spec.ts factsheets test against a real build. /issues #170 updated to correct its own stale factsheets claim.", "checks": "verify:pr-local (green), check:bundle-budget (within tolerance), lint, typecheck, full vitest (564/564 post-merge), targeted Playwright (1/1) + manual browser script (11/11)" }, { @@ -9289,8 +9331,8 @@ "ref": "claude/codex-m4c-retire-shadow-nliak3", "head": "448a0d084c4cd2cda6153dd7f03dcb67c43a8df0", "scope": "DS Track A2 (#261): retire --shadow-focus; composer focus onto sanctioned outline; contract guard; baseline ratchet; design-system docs + ledger", - "outcome": "Approved \u2014 PR #1807. Token deleted in both themes; .chat-composer-shell-delta:focus-within uses outline 2px var(--focus) at offset 2px and no longer overrides box-shadow. Reach premise corrected: 0 of 37 production routes render the class (only /mockups/calculators-search). legacyShadowAliases 127->125, globals.css pin 3->1.", - "checks": "check:design-system-contract PASS; design-token-contract.test.ts PASS + mutation-verified both ways; verify:pr-local PASS except pre-existing tests/pr-handoff-stop.test.ts failure baselined on untouched base e8b61d8; build PASS; check:rag:fixtures PASS (36 cases); Chromium look both themes on the mockup route (inspection only, rev 1194 vs pinned 1234 #255); verify:ui/verify:phone-chrome NOT run \u2014 delegated to CI" + "outcome": "Approved — PR #1807. Token deleted in both themes; .chat-composer-shell-delta:focus-within uses outline 2px var(--focus) at offset 2px and no longer overrides box-shadow. Reach premise corrected: 0 of 37 production routes render the class (only /mockups/calculators-search). legacyShadowAliases 127->125, globals.css pin 3->1.", + "checks": "check:design-system-contract PASS; design-token-contract.test.ts PASS + mutation-verified both ways; verify:pr-local PASS except pre-existing tests/pr-handoff-stop.test.ts failure baselined on untouched base e8b61d8; build PASS; check:rag:fixtures PASS (36 cases); Chromium look both themes on the mockup route (inspection only, rev 1194 vs pinned 1234 #255); verify:ui/verify:phone-chrome NOT run — delegated to CI" }, { "date": "2026-08-11", @@ -9393,7 +9435,7 @@ "ref": "codex/visual-baseline-advisory-pr", "head": "6bc57714c36bc6d027561bb8f5f8b00bb92524b2", "scope": "PR #1791 babysit unblock", - "outcome": "fixed Production UI formulation Clear\u2192Draft flake settle; classified visual drift vs non-drift failures", + "outcome": "fixed Production UI formulation Clear→Draft flake settle; classified visual drift vs non-drift failures", "checks": "test:ci-workflows 263; classify-visual-baseline-outcome+ci-cache-safety 40" }, { @@ -9457,7 +9499,7 @@ "ref": "cursor/smarter-meds-search-9c1b (PR #1785)", "head": "88dbdd80ede81ec6062ffebae79244703d495a99", "scope": "PR #1785 unblock/fix", - "outcome": "before: BEHIND/MERGEABLE behind-but-clean (merge-tree clean, behind 2/ahead 9); tip 88dbdd80 required CI green; \u2192 after: late merged origin/main once (#1793/#1794); merge-tree clean; behind 0; no required-CI code fixes; no provider-backed checks", + "outcome": "before: BEHIND/MERGEABLE behind-but-clean (merge-tree clean, behind 2/ahead 9); tip 88dbdd80 required CI green; → after: late merged origin/main once (#1793/#1794); merge-tree clean; behind 0; no required-CI code fixes; no provider-backed checks", "checks": "git merge-tree clean; npm run format; prior tip CI green; no provider-backed checks run" }, { @@ -9465,7 +9507,7 @@ "ref": "cursor/smarter-meds-search-9c1b (PR #1785)", "head": "a4f57500f6b16a4616e1f84c126c2f787a40766b", "scope": "PR #1785 unblock/fix", - "outcome": "before: DIRTY/CONFLICTING behind-but-clean (merge-tree clean, behind 3/ahead 8); prior tip a4f57500 CI green; 0 unresolved threads \u2192 after: merged origin/main once (sync-only); merge-tree clean; behind 0; no CI/thread code fixes; focused meds tests 201 passed", + "outcome": "before: DIRTY/CONFLICTING behind-but-clean (merge-tree clean, behind 3/ahead 8); prior tip a4f57500 CI green; 0 unresolved threads → after: merged origin/main once (sync-only); merge-tree clean; behind 0; no CI/thread code fixes; focused meds tests 201 passed", "checks": "git merge-tree clean; npm run format; npm run test:focused meds/route/universal-search 201 passed; no provider-backed checks run" }, { @@ -9473,7 +9515,7 @@ "ref": "PR #1788", "head": "aaeb54630fde2c05efe9a90eda13fbb92cc933c0", "scope": "Run PR sweep", - "outcome": "Static PR maintainability: extracted useAnswerThreadBootstrap (ClinicalDashboard 4144\u21924106); merged origin/main (#1794/#1795)", + "outcome": "Static PR maintainability: extracted useAnswerThreadBootstrap (ClinicalDashboard 4144→4106); merged origin/main (#1794/#1795)", "checks": "check:maintainability-budgets pass; vitest bootstrap+storage 17; tsc clean; CI pending after push" }, { @@ -9545,7 +9587,7 @@ "ref": "claude/disabled-button-accessibility-piclvr", "head": "722abdb780c715c0a89df268ed48f6c741ffd569", "scope": "disabled-placeholder buttons -> aria-disabled + inert handler (25 sites, 13 components); controlDisabled/therapy recipe aria-disabled styling; require-button-wiring redundantDisabledPair gate; wiring-conventions contract rewrite (settles #291)", - "outcome": "authored \u2014 PR #1778 opened", + "outcome": "authored — PR #1778 opened", "checks": "lint (uncached, exit 0); typecheck; test 5878 passed/1 pre-existing root-env failure in pr-handoff-stop; build; check:rag:fixtures 36 golden cases; prettier --check clean; verify:ui not run (no browser in container)" }, { @@ -9625,7 +9667,7 @@ "ref": "claude/m2-ds-gates-blocking", "head": "d204c6f7c84a5e7de3f28061121fda68e7d28670", "scope": "M2 design-system gates: #264 + gate 4 of #265", - "outcome": "ready-to-merge; supersedes the 8ed66a05 row \u2014 the tap-floor defect renumbered #289 to #291 after main claimed #289/#290, and main was merged in", + "outcome": "ready-to-merge; supersedes the 8ed66a05 row — the tap-floor defect renumbered #289 to #291 after main claimed #289/#290, and main was merged in", "checks": "post-merge ds-contract PASS (colour-only 4, numerals 2, inversions 0) against main's new #1765/#1766 component code; outstanding-issues guard PASS 289 rows next-id=292; ledger guard PASS 774 rows; format clean" }, { @@ -9633,7 +9675,7 @@ "ref": "claude/m2-ds-gates-blocking", "head": "e8447b042088998d34af750df72a946b1f074b97", "scope": "M2 design-system gates: #264 + gate 4 of #265", - "outcome": "ready-to-merge; supersedes the d204c6f7 row \u2014 seven review findings fixed, copilot-swe-agent commits merged keeping the safer numeral classifier, tap-floor defect renumbered #291 to #293 after main claimed #291/#292", + "outcome": "ready-to-merge; supersedes the d204c6f7 row — seven review findings fixed, copilot-swe-agent commits merged keeping the safer numeral classifier, tap-floor defect renumbered #291 to #293 after main claimed #291/#292", "checks": "ds-contract PASS (colour-only 4, numerals 2, inversions 0); 11 reviewer cases probe-verified; mutation-verified incl. opacity and arbitrary-filter forms; lint 0; tsc 0 errors; format clean; outstanding-issues guard PASS 291 rows next-id=294 no ids deleted; ledger guard PASS 775 rows" }, { @@ -9642,7 +9684,7 @@ "head": "7bac3bd762b381cb25c9b2a15ef3bb7223d15b16", "scope": "PR #1780 review-and-fix", "outcome": "fixed P2 ratchet bypasses (arbitrary-property classes, CSS-consumer exemption anti-rot, modern CSS zero units); Bugbot clean; merge-tree clean; required CI was green on prior tip", - "checks": "vitest design-system-contract-utils 32/32; check:design-system-contract; mutation CSS-exemption fail\u2192restore; verify:cheap PASS (549 files / 5933 tests); verify:pr-local stages PASS (test flake in design-system-adoption timed out once then 51/51 + full test 549/549 + check:rag:fixtures PASS); no provider gates" + "checks": "vitest design-system-contract-utils 32/32; check:design-system-contract; mutation CSS-exemption fail→restore; verify:cheap PASS (549 files / 5933 tests); verify:pr-local stages PASS (test flake in design-system-adoption timed out once then 51/51 + full test 549/549 + check:rag:fixtures PASS); no provider gates" }, { "date": "2026-08-09", @@ -9650,7 +9692,7 @@ "head": "95221ef4235abd9544158b07b8b8569f00c9ec78", "scope": "PR #1780 review-and-fix", "outcome": "fixed P2 ratchet bypasses (arbitrary-property classes, CSS-consumer exemption anti-rot, modern CSS zero units); Bugbot clean; merge-tree clean; required CI was green on prior tip", - "checks": "vitest design-system-contract-utils 32/32; check:design-system-contract; mutation CSS-exemption fail\u2192restore; verify:cheap PASS (549 files / 5933 tests); verify:pr-local stages PASS (test flake in design-system-adoption timed out once then 51/51 + full test 549/549 + check:rag:fixtures PASS); no provider gates" + "checks": "vitest design-system-contract-utils 32/32; check:design-system-contract; mutation CSS-exemption fail→restore; verify:cheap PASS (549 files / 5933 tests); verify:pr-local stages PASS (test flake in design-system-adoption timed out once then 51/51 + full test 549/549 + check:rag:fixtures PASS); no provider gates" }, { "date": "2026-08-09", @@ -9785,7 +9827,7 @@ "ref": "cursor/therapy-card-densify-e975", "head": "3db839a6bb1f5b45fc55bb732d21b30551a506b0", "scope": "therapy search ResultCard densify (gap, tags, favourite, actions, match cells)", - "outcome": "pass \u2014 denser cards; band gap fixed; single-row prioritized tags; heart top-right; 3-col actions; summarised cells", + "outcome": "pass — denser cards; band gap fixed; single-row prioritized tags; heart top-right; 3-col actions; summarised cells", "checks": "unit 35/35; verify:pr-local pass; ensure visual phone+desktop pass" }, { @@ -9881,7 +9923,7 @@ "ref": "claude/document-viewer-optimization-tu8tnj (PR #1741)", "head": "8d01991217f56d40666e31e13547202c2a8df8f2", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Production UI PDF position fail + DIRTY \u2192 merged main; removed redundant relative on document-frame-controls; CI re-running", + "outcome": "Production UI PDF position fail + DIRTY → merged main; removed redundant relative on document-frame-controls; CI re-running", "checks": "test:focused document-frame 16 passed; playwright smoke PDF-first mobile 1 passed; no provider-backed checks" }, { @@ -9889,7 +9931,7 @@ "ref": "claude/document-viewer-optimization-tu8tnj (PR #1754)", "head": "41b4bccf7d7229920c33344bec0d46e0f2e48b97", "scope": "heavy review-and-fix", - "outcome": "CONFLICT merge-tree on docs/outstanding-issues.md resolved: kept main #285 (Node/jsdom floor) + renumbered authorizationHeader trap to #286, next-id=287; merged origin/main; 1 unresolved review thread (comments 403 \u2014 skipped); no product code change", + "outcome": "CONFLICT merge-tree on docs/outstanding-issues.md resolved: kept main #285 (Node/jsdom floor) + renumbered authorizationHeader trap to #286, next-id=287; merged origin/main; 1 unresolved review thread (comments 403 — skipped); no product code change", "checks": "check:outstanding-issues PASS (284 rows, next-id=287); prettier --check docs/outstanding-issues.md PASS; ledger:dedupe none; no provider-backed checks" }, { @@ -9913,7 +9955,7 @@ "ref": "claude/ds-baseline-workflow (PR #1743)", "head": "753898f4982be38c3b3d11495caf3d30236b16a3", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "3 Codex threads (2 P1+1 P2) \u2192 partial refresh + refresh provenance + mask settle; threads disposition via later head", + "outcome": "3 Codex threads (2 P1+1 P2) → partial refresh + refresh provenance + mask settle; threads disposition via later head", "checks": "vitest adopt-visual-baselines 3 + design-system-adoption 51; no provider-backed checks" }, { @@ -9937,7 +9979,7 @@ "ref": "claude/ds-doc-corrections", "head": "534405600dca67317b4d60266cda03ec95f028e7", "scope": "M1 stranded doc corrections (docs/outstanding-issues.md #262/#266, docs/design-system/COMPONENTS.md TextField row + section 4)", - "outcome": "authored and handed off as PR #1719; every inherited figure re-measured against origin/main rather than copied forward, and the stranded version's 'eight shadow tokens, focus 2' claim was found wrong \u2014 LEGACY_SHADOW_ALIAS matches seven tokens and has never included focus", + "outcome": "authored and handed off as PR #1719; every inherited figure re-measured against origin/main rather than copied forward, and the stranded version's 'eight shadow tokens, focus 2' claim was found wrong — LEGACY_SHADOW_ALIAS matches seven tokens and has never included focus", "checks": "check:outstanding-issues pass (274 rows, unique ids, no ids deleted from base); prettier --check . pass whole-tree; legacyShadowAliases re-measured 228 via the contract's own analyzers; docs-only diff so no unit/lint/typecheck/browser gate applies" }, { @@ -9952,7 +9994,7 @@ "date": "2026-08-08", "ref": "claude/ds-tap-and-linkaction", "head": "6916c80526603514d91bd29d224959dd420af59c", - "scope": "M5 LinkAction tone refusal plus re-measured corrections to outstanding-issues #270, #118 and #269 \u2014 final reviewed head, adds the tone?: never fix, its type-contract test and both regenerated manifests", + "scope": "M5 LinkAction tone refusal plus re-measured corrections to outstanding-issues #270, #118 and #269 — final reviewed head, adds the tone?: never fix, its type-contract test and both regenerated manifests", "outcome": "PR #1720, superseding the 824c1b74a record. Codex found the Omit form still accepted tone through a spread; verified with a focused tsc probe before changing anything (Omit accepted the spread with no diagnostic, tone?: never rejected it with TS2345), because excess-property checking only fires on object literals. Fixed with tone?: never plus a type-level contract test that stops compiling if the prop widens back. CodeRabbit's future-dated finding fixed in ff307cc5b. CodeRabbit's ledger-scope finding does not apply: that row records a different ref and head and was accurate as written, but a superseding row for the final #1719 head was appended anyway since its scope grew after the review pass", "checks": "tsc -p tsconfig.typecheck.json --noEmit exit 0 zero diagnostics; lint exit 0; check:design-system-contract exit 0 (676 production files, legacy shadow aliases 228 confirming the #262 re-measure, adoption 53 components 55 roots, design-sync 53 components and 7 guidelines); check-icon-scale.mjs --strict exit 0; vitest threads pool 3 files 164 tests passed; check:outstanding-issues pass; check:branch-review-ledger pass; prettier --check . pass whole-tree; main merged in with merge-tree proven clean first and an id-set proof over both merge parents showing 274 ids each side, none lost, none invented" }, @@ -9969,7 +10011,7 @@ "ref": "claude/mode-routing-search-pages-jabe17", "head": "3a0bdd62466080ad713873cdd690ae600635a979", "scope": "mode routing: one shared home page at /, mode pill retargets the composer, /documents + /medications mode homes", - "outcome": "handoff \u2014 PR #1744 opened; 2 pre-existing failures verified at base bc33d41", + "outcome": "handoff — PR #1744 opened; 2 pre-existing failures verified at base bc33d41", "checks": "test:e2e:pr 406 passed/2 failed (both fail at base); vitest 5608 passed/1 failed (pre-existing); lint clean; tsc clean; sitemap:check, docs:check-index, docs:check-inventory, check:design-system-contract, check:outstanding-issues pass; verify:pr-local and verify:ui blocked by pre-existing installed-lock-parity (playwright 1.62.0 vs locked 1.62.1)" }, { @@ -9993,7 +10035,7 @@ "ref": "claude/mode-routing-search-pages-jabe17 (PR #1744)", "head": "e7a6b44cf4488228129fb2f7285904f9e040dcaa", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Static maintainability 4205>4140 + DIRTY \u2192 merged main; extracted payloads+home-mode-seed to 4124 lines; CI re-running", + "outcome": "Static maintainability 4205>4140 + DIRTY → merged main; extracted payloads+home-mode-seed to 4124 lines; CI re-running", "checks": "check:maintainability-budgets pass; typecheck; vitest clinical-dashboard-merge+search-route-ownership 25; no provider-backed checks" }, { @@ -10025,7 +10067,7 @@ "ref": "claude/planning-build-intelligence-9ot0nm (PR #1730)", "head": "fa616b11e8072ac3a94dd25e02c9c096983770f5", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "DIRTY \u2192 CLEAN at current head (auto-merge/sync); local merge push blocked by armed auto-merge sentinel", + "outcome": "DIRTY → CLEAN at current head (auto-merge/sync); local merge push blocked by armed auto-merge sentinel", "checks": "no local gates; no provider-backed checks" }, { @@ -10041,7 +10083,7 @@ "ref": "codex/lighthouse-hardening (PR #1746)", "head": "038058ea63837e7c4a90e84b7f8f860aacc51e13", "scope": "heavy review-and-fix", - "outcome": "CONFLICT merge-tree on lighthouse-budget.json resolved: kept main baseline measurements + this PR Lighthouse hardening (scripts/workflows/ci-change-scope); visual-baseline policy matches main; 3 unresolved threads (comments 403 \u2014 skipped)", + "outcome": "CONFLICT merge-tree on lighthouse-budget.json resolved: kept main baseline measurements + this PR Lighthouse hardening (scripts/workflows/ci-change-scope); visual-baseline policy matches main; 3 unresolved threads (comments 403 — skipped)", "checks": "ci-change-scope --self-test PASS; vitest check-lighthouse-budget+ci-cache-safety 84/84 PASS; no provider-backed checks" }, { @@ -10049,7 +10091,7 @@ "ref": "codex/lighthouse-hardening (PR #1746)", "head": "d4af6a6356de3327906936a237405e4e7ccba0cb", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "DIRTY + 3 Codex P2 + Static contract fail \u2192 main sync; process-group kill; suite deadline; normalized samples; contract test updated; threads unreplied (API 403)", + "outcome": "DIRTY + 3 Codex P2 + Static contract fail → main sync; process-group kill; suite deadline; normalized samples; contract test updated; threads unreplied (API 403)", "checks": "vitest live-web-vitals-inputs+check-lighthouse-budget 61; ci-cache-safety 32; no provider-backed checks" }, { @@ -10057,7 +10099,7 @@ "ref": "cursor/compact-services-result-text-9b7d (PR #1731)", "head": "bdaad2cc471e5b599205b2f1f265b2d8e1fdb43c", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "2 Codex P2 \u2192 skip placeholders in compactBestUseTitle; gate subtitle compaction to services mode; threads unreplied (API 403)", + "outcome": "2 Codex P2 → skip placeholders in compactBestUseTitle; gate subtitle compaction to services mode; threads unreplied (API 403)", "checks": "vitest services-catalog+document-search-record-fault 20 passed; no provider-backed checks" }, { @@ -10113,7 +10155,7 @@ "ref": "cursor/confirm-checklist-polish-195c (PR #1734)", "head": "e1385d67ce42023f1293a652efa9799f3eb9eb2d", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "DIRTY reported \u2192 already contained main; no code change this sweep", + "outcome": "DIRTY reported → already contained main; no code change this sweep", "checks": "no gates; no provider-backed checks" }, { @@ -10153,7 +10195,7 @@ "ref": "cursor/factsheets-compact-mockups-ad4c (PR #1728)", "head": "541f68bd1bcd29daa05805d8fce22034b21d5076", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "BEHIND + 2 Codex P2 threads \u2192 synced main; full comfortable list + ComfortableCards density; threads unreplied (API 403)", + "outcome": "BEHIND + 2 Codex P2 threads → synced main; full comfortable list + ComfortableCards density; threads unreplied (API 403)", "checks": "vitest factsheets-compact-view-mockups.dom 3 passed; tsc; no provider-backed checks" }, { @@ -10265,7 +10307,7 @@ "ref": "cursor/forms-results-bar-documents-style-13dc", "head": "fd148ca931ab9c023619deed98bae5af787e4253", "scope": "sync", - "outcome": "PR #1751 unblock: CONFLICTING\u2192MERGEABLE; 11 behind main; merge-tree clean; merge commit fd148ca9 pushed; all static+unit+build+critical CI green; Production UI (1/2/3) pending", + "outcome": "PR #1751 unblock: CONFLICTING→MERGEABLE; 11 behind main; merge-tree clean; merge commit fd148ca9 pushed; all static+unit+build+critical CI green; Production UI (1/2/3) pending", "checks": "merge-tree:clean,static-pr:pass,unit-coverage:pass,build:pass,production-ui-critical:pass,safety:pass,pr-policy:pass,production-ui-1/2/3:pending" }, { @@ -10289,7 +10331,7 @@ "ref": "cursor/phone-mode-dense-production-05c0 (PR #1648)", "head": "276a5cd02cfb8fb93d969e9e4db167576e054a42", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "DIRTY/master-search-header conflict \u2192 merged origin/main; phone dense + desktop tall rows preserved; CI re-running", + "outcome": "DIRTY/master-search-header conflict → merged origin/main; phone dense + desktop tall rows preserved; CI re-running", "checks": "vitest header-scroll-hide+mode-nav 55 passed; lint master-search-header; no provider-backed checks" }, { @@ -10321,7 +10363,7 @@ "ref": "cursor/run-pr-sweep-ledger-d56c (PR #1698)", "head": "ccf7284cbbe2315e5dc6a1bf126403a8a2205fa7", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: DIRTY/CONFLICTING, PR mergeability fail, behind 33, 0 threads, fake single-parent merge tip \u2192 after: real merge origin/main (conflicts resolved: docs/outstanding-issues.md + lighthouse-budget.json took main), merge-tree clean, unique diff ledger-only, 0 threads", + "outcome": "before: DIRTY/CONFLICTING, PR mergeability fail, behind 33, 0 threads, fake single-parent merge tip → after: real merge origin/main (conflicts resolved: docs/outstanding-issues.md + lighthouse-budget.json took main), merge-tree clean, unique diff ledger-only, 0 threads", "checks": "check:outstanding-issues pass; check:branch-review-ledger pass; ledger:dedupe none; merge-tree clean; format; no provider-backed checks run" }, { @@ -10345,7 +10387,7 @@ "ref": "cursor/safety-plan-phone-safe-area-624a (PR #1711)", "head": "0aa81baf1260991f92dd8646bd9cd52b4077a39b", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "DIRTY/ledger-only \u2192 merged origin/main via ledger driver; CI re-running", + "outcome": "DIRTY/ledger-only → merged origin/main via ledger driver; CI re-running", "checks": "ledger merge driver; no provider-backed checks" }, { @@ -10393,7 +10435,7 @@ "ref": "cursor/services-content-cleanup-1c73 (PR #1733)", "head": "af90c9017fd6c1c65fab0f40f96e155bd4f64f41", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "DIRTY/ledger sync + 2 Copilot threads \u2192 placeholder ranking + multi-clause criteria; threads unreplied (API 403)", + "outcome": "DIRTY/ledger sync + 2 Copilot threads → placeholder ranking + multi-clause criteria; threads unreplied (API 403)", "checks": "vitest services-catalog 16 passed; no provider-backed checks" }, { @@ -10409,7 +10451,7 @@ "ref": "cursor/site-testing-speed-08c1 (PR #1686)", "head": "632958dd63e320b3c1ae911ca0b025aaab78a478", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "DIRTY (ledger+outstanding-issues+scripts-index) \u2192 merged origin/main with careful unions; CI re-running", + "outcome": "DIRTY (ledger+outstanding-issues+scripts-index) → merged origin/main with careful unions; CI re-running", "checks": "check:outstanding-issues pass; ledger:dedupe; vitest playwright-revision+ci-cache-safety 33 passed; no provider-backed checks" }, { @@ -10441,7 +10483,7 @@ "ref": "dependabot/npm_and_yarn/js-yaml-4.3.1 (PR #1668)", "head": "e95160210e7801c1f4e863648ed6b48c8fbee71f", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "BEHIND \u2192 merged origin/main; Safety audit failed on transitive nanoid\u2192bumped lock to 3.3.18; CI re-running", + "outcome": "BEHIND → merged origin/main; Safety audit failed on transitive nanoid→bumped lock to 3.3.18; CI re-running", "checks": "npm audit --omit=dev --audit-level=high clean; no provider-backed checks" }, { @@ -10521,7 +10563,7 @@ "ref": "claude/handover-review-nlhuln", "head": "de8b74e2fb94d1ec9b1982c15a2dea43421c3eee", "scope": "outstanding-issues ledger capture after the mode-nav rollout (PR #1685) (supersedes 2026-08-07)", - "outcome": "Confirmed #256's two remaining suspected section sets are dead (/forms/ and /differentials/presentations/ draw no section nav; form-decision-context-mobile is a testId not an id; ruled out sectionId indirection in both files). Added #271 (delete-or-keep the consumer-less action kind) and #272 (addon-slot single-owner rule held by two lists agreeing by coincidence) \u2014 renumbered from this PR's original #261/#262 because main claimed #261-#270 via PR #1678 design-system tracks in the interim. #207/#226/#231 reviewed and deliberately left untouched as existing P1 rows.", + "outcome": "Confirmed #256's two remaining suspected section sets are dead (/forms/ and /differentials/presentations/ draw no section nav; form-decision-context-mobile is a testId not an id; ruled out sectionId indirection in both files). Added #271 (delete-or-keep the consumer-less action kind) and #272 (addon-slot single-owner rule held by two lists agreeing by coincidence) — renumbered from this PR's original #261/#262 because main claimed #261-#270 via PR #1678 design-system tracks in the interim. #207/#226/#231 reviewed and deliberately left untouched as existing P1 rows.", "checks": "check:outstanding-issues passed (270 rows, 129 open, 141 archived, unique ids, next-id=273 above the highest, no ids deleted from base d32dd549a3dd); prettier --check clean on the changed file; rows written via scripts/outstanding-issues.mjs, never hand-edited; no code gates run - docs-only diff" }, { @@ -10529,7 +10571,7 @@ "ref": "claude/handover-review-nlhuln (PR #1685)", "head": "e200e589938c8dac2d3f76ef42ed1639b3fde18e", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: behind 1, checks green, 0 threads \u2192 after: merged origin/main (conflicts: none); PR required SUCCESS; 0 threads", + "outcome": "before: behind 1, checks green, 0 threads → after: merged origin/main (conflicts: none); PR required SUCCESS; 0 threads", "checks": "merge-tree clean; git merge origin/main + push; no provider-backed checks run" }, { @@ -10545,7 +10587,7 @@ "ref": "claude/issues-256-section-nav-clean (PR #1697)", "head": "2b99db1f00c42fd7c11c4bf8acbad904ef5003e1", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: DIRTY/PR mergeability fail, behind 3, merge-tree CLEAN, 0 threads \u2192 after: merged origin/main (conflicts: none), CI re-running; 0 threads", + "outcome": "before: DIRTY/PR mergeability fail, behind 3, merge-tree CLEAN, 0 threads → after: merged origin/main (conflicts: none), CI re-running; 0 threads", "checks": "merge-tree clean; git merge origin/main + push; no provider-backed checks run" }, { @@ -10585,7 +10627,7 @@ "ref": "claude/search-bar-mobile-layout-buu0io (PR #1689)", "head": "a152ffd89c962e3589509c0c3740dc429264063a", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: behind 1, required CI green (advisory lighthouse fail ignored), 1 CodeRabbit lighthouse baseline thread (human disagreement in progress) \u2192 after: waited for CI settle, disabled automerge, merged origin/main, pushed, re-enabled automerge; thread left open for human", + "outcome": "before: behind 1, required CI green (advisory lighthouse fail ignored), 1 CodeRabbit lighthouse baseline thread (human disagreement in progress) → after: waited for CI settle, disabled automerge, merged origin/main, pushed, re-enabled automerge; thread left open for human", "checks": "settled CI then merge+push; no provider-backed checks run; advisory lighthouse not chased" }, { @@ -10641,7 +10683,7 @@ "ref": "cursor/clinician-workflow-mockups-2b63 (PR #1662)", "head": "42ccad8ecc2889612e8f25ba79bb26a19e0a8baa", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: behind 17, checks green, 0 threads \u2192 after: merged origin/main (conflicts: none), CI re-running; 0 threads", + "outcome": "before: behind 17, checks green, 0 threads → after: merged origin/main (conflicts: none), CI re-running; 0 threads", "checks": "merge-tree clean; git merge origin/main + push; no provider-backed checks run" }, { @@ -10713,7 +10755,7 @@ "ref": "cursor/phone-mode-dense-production-05c0 (PR #1648)", "head": "4e0cca2ccbc19ed676765b029642da0afea6215a", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: behind 17, checks green, 0 threads \u2192 after: merged origin/main (conflicts: none), CI re-running; 0 threads", + "outcome": "before: behind 17, checks green, 0 threads → after: merged origin/main (conflicts: none), CI re-running; 0 threads", "checks": "merge-tree clean; git merge origin/main + push; no provider-backed checks run" }, { @@ -10729,7 +10771,7 @@ "ref": "cursor/pr-1676-unblock-ledger-ef51 (PR #1677)", "head": "89e25e97d442ebbbc7d33e87edec37ef42090486", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: DIRTY/PR mergeability fail, behind 1, merge-tree CLEAN, 0 threads \u2192 after: merged origin/main (conflicts: none), CI re-running; 0 threads", + "outcome": "before: DIRTY/PR mergeability fail, behind 1, merge-tree CLEAN, 0 threads → after: merged origin/main (conflicts: none), CI re-running; 0 threads", "checks": "merge-tree clean; git merge origin/main + push; no provider-backed checks run" }, { @@ -10753,7 +10795,7 @@ "ref": "cursor/privacy-live-signal-variants-bc81 (PR #1676)", "head": "7dd4ea9b1ce17777f2d0ac6bd95bb916cd69758f", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: DIRTY/PR mergeability fail, behind 2, merge-tree CLEAN, 0 threads \u2192 after: merged origin/main (conflicts: none), CI re-running; 0 threads", + "outcome": "before: DIRTY/PR mergeability fail, behind 2, merge-tree CLEAN, 0 threads → after: merged origin/main (conflicts: none), CI re-running; 0 threads", "checks": "merge-tree clean; git merge origin/main + push; no provider-backed checks run" }, { @@ -10777,7 +10819,7 @@ "ref": "cursor/remove-specifiers-back-arrow-f1c4", "head": "095791235d58a6309b21b139911a1aad9fe9086b", "scope": "specifiers-search-results-breadcrumb", - "outcome": "removed lone \u2190 Specifiers crumb from search results; deep pages unchanged", + "outcome": "removed lone ← Specifiers crumb from search results; deep pages unchanged", "checks": "format,typecheck,lint,ensure+phone-spot-check" }, { @@ -10801,7 +10843,7 @@ "ref": "cursor/settings-features-mockups-97ac (PR #1657)", "head": "d64288ce0f2f111b1838ded31a23d0020b38da8b", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: behind 17, checks green, 0 threads \u2192 after: merged origin/main (conflicts: none), CI re-running; 0 threads", + "outcome": "before: behind 17, checks green, 0 threads → after: merged origin/main (conflicts: none), CI re-running; 0 threads", "checks": "merge-tree clean; git merge origin/main + push; no provider-backed checks run" }, { @@ -10809,7 +10851,7 @@ "ref": "cursor/ship-first-redesign-mockups-2398 (PR #1654)", "head": "9d9eb0be47073a7f051a5885359b82f2ff978a85", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: behind 17, checks green, 0 threads \u2192 after: merged origin/main (conflicts: none), CI re-running; 0 threads", + "outcome": "before: behind 17, checks green, 0 threads → after: merged origin/main (conflicts: none), CI re-running; 0 threads", "checks": "merge-tree clean; git merge origin/main + push; no provider-backed checks run" }, { @@ -10833,8 +10875,8 @@ "ref": "cursor/site-testing-speed-08c1 (PR #1686)", "head": "71b57ea5ce0c46c16c42c07e66933836ae609b6a", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: DIRTY + Static PR fail (docs inventory stale) + PR required fail, merge-tree CLEAN \u2192 after: merged origin/main, docs:update inventory, pushed; CI re-running; 0 threads", - "checks": "docs:check-inventory fail\u2192docs:update; format via Prettier; no provider-backed checks run" + "outcome": "before: DIRTY + Static PR fail (docs inventory stale) + PR required fail, merge-tree CLEAN → after: merged origin/main, docs:update inventory, pushed; CI re-running; 0 threads", + "checks": "docs:check-inventory fail→docs:update; format via Prettier; no provider-backed checks run" }, { "date": "2026-08-07", @@ -10865,7 +10907,7 @@ "ref": "cursor/tools-search-mockups-72e1 (PR #1653)", "head": "a7fbc26a917b347d90c6bab1e6c1b2ede6422263", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: behind 17, checks green, 0 threads \u2192 after: merged origin/main (conflicts: none), CI re-running; 0 threads", + "outcome": "before: behind 17, checks green, 0 threads → after: merged origin/main (conflicts: none), CI re-running; 0 threads", "checks": "merge-tree clean; git merge origin/main + push; no provider-backed checks run" }, { @@ -10889,15 +10931,15 @@ "ref": "cursor/viewer-phase2a-frame-controls-1db8 (PR #1687)", "head": "5c10730be1641a386ee8c8476778933588a822fc", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: up to date with main, Static PR fail (format:changed pdf-canvas-viewer), 1 outdated CodeRabbit thread (ref sync) already fixed on head \u2192 after: prettier format fix pushed; thread left open (no review-write API as cursor[bot]); CI re-running", - "checks": "format:changed fail\u2192prettier --write pdf-canvas-viewer.tsx; format:changed PASS locally; no provider-backed checks run" + "outcome": "before: up to date with main, Static PR fail (format:changed pdf-canvas-viewer), 1 outdated CodeRabbit thread (ref sync) already fixed on head → after: prettier format fix pushed; thread left open (no review-write API as cursor[bot]); CI re-running", + "checks": "format:changed fail→prettier --write pdf-canvas-viewer.tsx; format:changed PASS locally; no provider-backed checks run" }, { "date": "2026-08-07", "ref": "cursor/viewer-phase2c-rail-filmstrip-1db8 (PR #1707)", "head": "af52b592bd22794f5cf96cbca0fb27f2d6bbb3e3", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Not behind main, no merge needed (mergeable_state 'blocked' was just the failing required check). Fixed the real Unit coverage CI failure: tests/document-image-filmstrip.dom.test.tsx still asserted the stale aria-current='true' after the component was already fixed to emit 'page' for an earlier a11y review finding -- exactly matched an unresolved CodeRabbit finding, applied its suggested fix. Also fixed an unresolved LOW-severity Sentry finding (image metadata line could start with a leading ' \u00b7 ' separator when image_type is falsy) by collecting parts into an array and filter+join instead of individually prefixing. All 4 review threads now resolved (2 new fixes + 2 already-fixed-on-branch copilot threads).", + "outcome": "Not behind main, no merge needed (mergeable_state 'blocked' was just the failing required check). Fixed the real Unit coverage CI failure: tests/document-image-filmstrip.dom.test.tsx still asserted the stale aria-current='true' after the component was already fixed to emit 'page' for an earlier a11y review finding -- exactly matched an unresolved CodeRabbit finding, applied its suggested fix. Also fixed an unresolved LOW-severity Sentry finding (image metadata line could start with a leading ' · ' separator when image_type is falsy) by collecting parts into an array and filter+join instead of individually prefixing. All 4 review threads now resolved (2 new fixes + 2 already-fixed-on-branch copilot threads).", "checks": "eslint on both fixed files (clean); local vitest blocked by environment-wide missing tailwind-merge dependency -- relying on CI" }, { @@ -10913,7 +10955,7 @@ "ref": "dependabot/npm_and_yarn/js-yaml-4.3.1 (PR #1668)", "head": "a7dde7e6101ed69fb43f004981be9500ba773105", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: behind 17, checks green, 0 threads \u2192 after: merged origin/main (conflicts: none), CI re-running; 0 threads", + "outcome": "before: behind 17, checks green, 0 threads → after: merged origin/main (conflicts: none), CI re-running; 0 threads", "checks": "merge-tree clean; git merge origin/main + push; no provider-backed checks run" }, { @@ -10937,7 +10979,7 @@ "ref": "claude/ds-truth-fixes", "head": "7a9c41a971aa9111f050cd39d4429ada1b3f4409", "scope": "PR #1655 heavy review-and-fix", - "outcome": "fixed DownloadLink tone DOM leak + stale ToggleSwitch/Links \u00a79 docs; merge-tree clean; verify:cheap+verify:pr-local green; CI re-queued after push", + "outcome": "fixed DownloadLink tone DOM leak + stale ToggleSwitch/Links §9 docs; merge-tree clean; verify:cheap+verify:pr-local green; CI re-queued after push", "checks": "bugbot+deep-review; vitest ui-primitives+ui-v2 60p; verify:cheap 5448p; verify:pr-local format+lint+typecheck+test+build+rag-fixtures; no provider gates" }, { @@ -10945,7 +10987,7 @@ "ref": "claude/implement-97vpz7", "head": "00ab7bfd34684bc854d15a3f28987674098a7130", "scope": "PR #1646 soft-tail answer-cache skip + soft-tail test hardening", - "outcome": "fixed \u2014 answer-path soft-tail skip via rag-query-guard helpers; soft-tail fixture pins; duplicate memo test removed; in-corpus assert narrowed; budget 4362", + "outcome": "fixed — answer-path soft-tail skip via rag-query-guard helpers; soft-tail fixture pins; duplicate memo test removed; in-corpus assert narrowed; budget 4362", "checks": "test:rag-query-guard+unsupported-cache+classifier-memo 22/22,check:maintainability-budgets 4362/4362" }, { @@ -10977,7 +11019,7 @@ "ref": "claude/pr-handoff-stop-hook (PR #1649)", "head": "3403126bc6cd86145d6921a3fe4d081181e8a113", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: 5 unresolved threads (Devin create-from-output + 4 CodeRabbit), mergeable/BLOCKED, Actions major outage leaving CI pending; after: hardened jq-less input/output separation + session fail-open + prefix unlock + tests (9 passed) in 3403126bc6cd86145d6921a3fe4d081181e8a113, threads replied+resolved, branch current with main, CI re-triggered (Actions outage \u2014 not babysat)", + "outcome": "before: 5 unresolved threads (Devin create-from-output + 4 CodeRabbit), mergeable/BLOCKED, Actions major outage leaving CI pending; after: hardened jq-less input/output separation + session fail-open + prefix unlock + tests (9 passed) in 3403126bc6cd86145d6921a3fe4d081181e8a113, threads replied+resolved, branch current with main, CI re-triggered (Actions outage — not babysat)", "checks": "npx vitest run tests/pr-handoff-stop.test.ts (9 passed); bash -n hook OK; no provider-backed checks run" }, { @@ -10985,7 +11027,7 @@ "ref": "claude/pr-handoff-stop-hook (PR #1649)", "head": "36c1bccd89f976bcae3dabf8f5787198db5df078", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: 5 unresolved threads (Devin create-from-output + 4 CodeRabbit), mergeable/BLOCKED, Actions major outage leaving CI pending; after: hardened jq-less input/output separation + session fail-open + prefix unlock + tests (9 passed) in 36c1bccd89f976bcae3dabf8f5787198db5df078, threads replied+resolved, branch current with main, CI re-triggered (Actions outage \u2014 not babysat)", + "outcome": "before: 5 unresolved threads (Devin create-from-output + 4 CodeRabbit), mergeable/BLOCKED, Actions major outage leaving CI pending; after: hardened jq-less input/output separation + session fail-open + prefix unlock + tests (9 passed) in 36c1bccd89f976bcae3dabf8f5787198db5df078, threads replied+resolved, branch current with main, CI re-triggered (Actions outage — not babysat)", "checks": "npx vitest run tests/pr-handoff-stop.test.ts (9 passed); bash -n hook OK; no provider-backed checks run" }, { @@ -10993,7 +11035,7 @@ "ref": "claude/pr-handoff-stop-hook (PR #1649)", "head": "f67e5c9103c3e1483ad8e034fe7a6757c2362d74", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: 5 unresolved threads (Devin create-from-output + 4 CodeRabbit), mergeable/BLOCKED, Actions major outage leaving CI pending; after: hardened jq-less input/output separation + session fail-open + prefix unlock + tests (9 passed) in f67e5c9103c3e1483ad8e034fe7a6757c2362d74, threads replied+resolved, branch current with main, CI re-triggered (Actions outage \u2014 not babysat)", + "outcome": "before: 5 unresolved threads (Devin create-from-output + 4 CodeRabbit), mergeable/BLOCKED, Actions major outage leaving CI pending; after: hardened jq-less input/output separation + session fail-open + prefix unlock + tests (9 passed) in f67e5c9103c3e1483ad8e034fe7a6757c2362d74, threads replied+resolved, branch current with main, CI re-triggered (Actions outage — not babysat)", "checks": "npx vitest run tests/pr-handoff-stop.test.ts (9 passed); bash -n hook OK; no provider-backed checks run" }, { @@ -11001,7 +11043,7 @@ "ref": "claude/pr-handoff-stop-hook (PR #1649)", "head": "fff524d73ebfafeef7bdc50752a6d14f253ebc2e", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: 5 unresolved threads (Devin create-from-output + 4 CodeRabbit), mergeable/BLOCKED, Actions major outage leaving CI pending; after: hardened jq-less input/output separation + session fail-open + prefix unlock + tests (9 passed) in fff524d73ebfafeef7bdc50752a6d14f253ebc2e, threads replied+resolved, branch current with main, CI re-triggered (Actions outage \u2014 not babysat)", + "outcome": "before: 5 unresolved threads (Devin create-from-output + 4 CodeRabbit), mergeable/BLOCKED, Actions major outage leaving CI pending; after: hardened jq-less input/output separation + session fail-open + prefix unlock + tests (9 passed) in fff524d73ebfafeef7bdc50752a6d14f253ebc2e, threads replied+resolved, branch current with main, CI re-triggered (Actions outage — not babysat)", "checks": "npx vitest run tests/pr-handoff-stop.test.ts (9 passed); bash -n hook OK; no provider-backed checks run" }, { @@ -11017,7 +11059,7 @@ "ref": "claude/settings-nav-freeze-desktop-tdzh7z (PR #1641)", "head": "d4ecd2b5fc48a8d8f37f081cac2d80beb749df01", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: mergeable/BLOCKED, 0 unresolved threads, 0 behind main; prior CI reds were infra (npm ECONNRESET on Unit coverage; e7f380f3 cancelled at Set up job). after: pushed d4ecd2b5 ResizeObserver pin-clamp distance reset; all review threads remain resolved; CI re-triggered but GitHub Actions major_outage \u2014 runs pending/queued, no product failure to fix; merge tree clean", + "outcome": "before: mergeable/BLOCKED, 0 unresolved threads, 0 behind main; prior CI reds were infra (npm ECONNRESET on Unit coverage; e7f380f3 cancelled at Set up job). after: pushed d4ecd2b5 ResizeObserver pin-clamp distance reset; all review threads remain resolved; CI re-triggered but GitHub Actions major_outage — runs pending/queued, no product failure to fix; merge tree clean", "checks": "local typecheck PASS; local lint (settings-dialog) PASS; format unchanged; no provider-backed checks run; hosted CI awaiting Actions recovery (run 31120931239)" }, { @@ -11249,7 +11291,7 @@ "ref": "cursor/ledger-fastest-wins-capture-1479", "head": "b03b51d7b22671f2734115b5fef469bd2e932ae3", "scope": "prlanded PR #1624", - "outcome": "MERGED squash b03b51d7; 118/118 open\u2194queue, A1 #226 at order 5, #249\u2013#251; orphaned #250 acuity clarify \u2192 fix-forward", + "outcome": "MERGED squash b03b51d7; 118/118 open↔queue, A1 #226 at order 5, #249–#251; orphaned #250 acuity clarify → fix-forward", "checks": "check:outstanding-issues PASS on merge head; Bugbot clean after clarify" }, { @@ -11304,7 +11346,7 @@ "date": "2026-08-04", "ref": "claude/ds-v2-empty-state-heading", "head": "5c1c1b32c8efb030a8603ac281c59108b842798d", - "scope": "PR #1612 \u2014 EmptyState headingLevel (#217), /dsm/search heading (#224), document-search empty-state adoption, ledger #230", + "scope": "PR #1612 — EmptyState headingLevel (#217), /dsm/search heading (#224), document-search empty-state adoption, ledger #230", "outcome": "self-review clean; no findings raised", "checks": "typecheck 0; lint 0; vitest 5085 passed/3 skipped; verify:ui 347 passed; prettier whole-tree clean; verify:pr-local exit 0" }, @@ -11336,7 +11378,7 @@ "date": "2026-08-04", "ref": "claude/top-search-design-mockups-w53znc", "head": "b432448e4893a42d07558aff0dc04be797971231", - "scope": "PR #1611 \u2014 results-band shelf Clear filter-only, memo deps, restored tests", + "scope": "PR #1611 — results-band shelf Clear filter-only, memo deps, restored tests", "outcome": "Fixed two Qodo findings from merged #1555; mutation-tested guard added", "checks": "tsc 0; eslint 0; vitest 4 files/59 tests; verify:pr-local blocked by lock parity (node 24.13 vs jsdom@30)" }, @@ -11362,14 +11404,14 @@ "head": "6cc0b6ffdae3b515a05a17f2a87e5f51e5347263", "scope": "PR review + fix (ingestion-autopilot service-role exposure) (supersedes 2026-08-02)", "outcome": "Supersedes the earlier row to record decisive gate results; historical review outcome otherwise unchanged.", - "checks": "PASS: npm run test:ci-workflows \u2014 206/206 passed; PASS: focused ci-cache-safety + ingestion-autopilot-workflow \u2014 21/21 passed; PASS: npm run check:github-actions \u2014 GitHub Actions pin check passed; PASS: prettier --check \u2014 all matched files use Prettier code style; PASS: git diff --check \u2014 clean. No provider calls." + "checks": "PASS: npm run test:ci-workflows — 206/206 passed; PASS: focused ci-cache-safety + ingestion-autopilot-workflow — 21/21 passed; PASS: npm run check:github-actions — GitHub Actions pin check passed; PASS: prettier --check — all matched files use Prettier code style; PASS: git diff --check — clean. No provider calls." }, { "date": "2026-08-04", "ref": "codex/fix-mode-switching-and-loading-issues", "head": "3e3b224a2ec13928d1e28173b1fc4c75d202d7d2", "scope": "PR #1607 unblock/fix", - "outcome": "clean \u2014 behind 0, merge-tree clean, 0 unresolved threads, required CI in progress (no code fix)", + "outcome": "clean — behind 0, merge-tree clean, 0 unresolved threads, required CI in progress (no code fix)", "checks": "merge-tree clean; behind_by 0; Unit/Build/Static/ProdUI in progress; no failing required" }, { @@ -11617,7 +11659,7 @@ "ref": "claude/ds-v2-architecture", "head": "157373700281f81f136275c56c9a82fb22776d99", "scope": "PR-Arch Wave4 motion/z/overlays/print", - "outcome": "local gates green; frontend-ui-reviewer API-limited \u2014 glance required before auto-merge", + "outcome": "local gates green; frontend-ui-reviewer API-limited — glance required before auto-merge", "checks": "unit 4972p; e2e:critical 15p; verify:ui 347p; verify:pr-local 0; eval:rag:offline pass" }, { @@ -11641,7 +11683,7 @@ "ref": "claude/ds-v2-architecture", "head": "93bb4b4756a7fad22f93008325f2c0f72471b0db", "scope": "PR-Arch Wave4 motion/z/overlays/print", - "outcome": "local gates green; frontend-ui-reviewer API-limited \u2014 glance required before auto-merge", + "outcome": "local gates green; frontend-ui-reviewer API-limited — glance required before auto-merge", "checks": "unit 4972p; e2e:critical 15p; verify:ui 347p; verify:pr-local 0; eval:rag:offline pass" }, { @@ -11649,7 +11691,7 @@ "ref": "claude/ds-v2-values", "head": "48012d359b84daae347201697c82f3e433c182c5", "scope": "PR #1571 review-and-fix (ds-v2-values tap/radius)", - "outcome": "fixed: Tools submit + account-setup close onto h-tap; phone composer input 44px pin; gate 2 demoted to implemented-partial; SPEC 407\u2192426; short-runway/short-answer smoke pins retuned; verify:cheap + verify:pr-local + 2 smoke tests green; CI Production UI in progress", + "outcome": "fixed: Tools submit + account-setup close onto h-tap; phone composer input 44px pin; gate 2 demoted to implemented-partial; SPEC 407→426; short-runway/short-answer smoke pins retuned; verify:cheap + verify:pr-local + 2 smoke tests green; CI Production UI in progress", "checks": "verify:cheap 471/4879; verify:pr-local build+fixtures; test:e2e 2 phone smoke passed; design-system-contract raw 2/0/0" }, { @@ -11793,7 +11835,7 @@ "ref": "claude/top-search-design-mockups-w53znc", "head": "4f4440fd6776742f5de203ee15295f372205321d", "scope": "search results bar: scope-system deletion, filter shelf, bar anatomy", - "outcome": "Handoff for PR #1555. Deleted the inert command-scope system (voided props, six modes' scope config, three matchers, four no-op call sites, the original shelf) \u2014 behaviour-preserving because every matcher early-returned true on a permanently-empty array. Rebuilt the applied-filter shelf prop-driven on live facet data, scoped to documents and therapy-compass. Landed the bar anatomy: tile spinner and funnel states, Filter to the right edge, Sort inboard. Study step 6 (remove the library button) deliberately declined \u2014 the nav route clears the query via onSearchModeChange. Ledger #182 closed.", + "outcome": "Handoff for PR #1555. Deleted the inert command-scope system (voided props, six modes' scope config, three matchers, four no-op call sites, the original shelf) — behaviour-preserving because every matcher early-returned true on a permanently-empty array. Rebuilt the applied-filter shelf prop-driven on live facet data, scoped to documents and therapy-compass. Landed the bar anatomy: tile spinner and funnel states, Filter to the right edge, Sort inboard. Study step 6 (remove the library button) deliberately declined — the nav route clears the query via onSearchModeChange. Ledger #182 closed.", "checks": "verify:pr-local exit 0 (460 files / 4796 tests, production build, client-bundle secret scan, RAG fixtures 36 cases / 23 suites); ui-tools 87 passed; ui-smoke + ui-accessibility 108 passed 1 failed (pre-existing PDF-canvas test, fails identically stashed, Chromium 1194 vs pinned 1228); mutation-tested the shelf's survives-loading guard" }, { @@ -11832,7 +11874,7 @@ "date": "2026-07-31", "ref": "1489", "head": "67d5cb91083f9b0e9d3017816cbf68abab102688", - "scope": "PR 1489 review \u2014 Therapy startup/sidebar perf, catalogue split, bundle-budget, phone-chrome", + "scope": "PR 1489 review — Therapy startup/sidebar perf, catalogue split, bundle-budget, phone-chrome", "outcome": "approved with follow-ups; merged 945148251. No P0/P1. Findings fixed on claude/pr-1489-review-786e01: inferred modality mislabelled ECT/rTMS as ACT and Psychoanalysis as CBT (pre-existing on main); hashed catalogue assets never pruned (2 stranded in-PR); classifyPullRequestFiles returned clinicalRisk:false for 205 clinical records; viewportHeightChanged guard outranked topRevealOffset; guard keyed innerHeight not visualViewport; sk-proj- keys unescaped; bundle-budget step timeout 3m too tight. Bundling note: operationalRisk+clinicalRisk in one squash, so no per-item revert.", "checks": "verify:cheap static gates pass; lint pass; typecheck exit 0; vitest 449 files/4700 pass; verify:phone-chrome contracts 116 pass + focused browser 13 pass; verify:ui 342 pass/2 fail, both pass isolated (composer hero-vs-dock hydration race, no position: assignment in use-hide-on-scroll)" }, @@ -11929,7 +11971,7 @@ "ref": "claude/issues-133-evidence", "head": "37f71f02f731175e4fed500f95529c3ef9eb568f", "scope": "PR #1506 reopen prep: sync main, renumber hazard to #155, supersede #112 residual", - "outcome": "READY \u2014 conflict cleared vs origin/main; main #154 preserved; hazard=#155 with archived #112 residual cross-link; med-accent=#156; false #155 evidence clause removed; Codex P2 addressed; Bugbot P1/P2 fixed; PR left CLOSED", + "outcome": "READY — conflict cleared vs origin/main; main #154 preserved; hazard=#155 with archived #112 residual cross-link; med-accent=#156; false #155 evidence clause removed; Codex P2 addressed; Bugbot P1/P2 fixed; PR left CLOSED", "checks": "check:outstanding-issues 154 rows/46 open next-id=157; check:branch-review-ledger 277 live; merge-tree clean da0c63d0; format no-op" }, { @@ -11945,7 +11987,7 @@ "ref": "claude/issues-writer-cli (PR #1524)", "head": "83dec1f5a36d577c87ee9a5382ef8431d197d93d", "scope": "PR #1524 review+bugbot+fix", - "outcome": "before: dirty/CONFLICTING vs main (outstanding-issues.md + scripts-index.md), missing pull_request CI, 0 review threads, NOT REVIEWED. after: merged origin/main (prefer main queues; renumbered this PR collision-free-ids note #159\u2192#168, next-id=169); fixed wrong skill/writer cite #154\u2192#156/#168; no other P0\u2013P2 writer defects; 0 threads. Residual: concurrent id RMW (#156/#168) still open.", + "outcome": "before: dirty/CONFLICTING vs main (outstanding-issues.md + scripts-index.md), missing pull_request CI, 0 review threads, NOT REVIEWED. after: merged origin/main (prefer main queues; renumbered this PR collision-free-ids note #159→#168, next-id=169); fixed wrong skill/writer cite #154→#156/#168; no other P0–P2 writer defects; 0 threads. Residual: concurrent id RMW (#156/#168) still open.", "checks": "check:outstanding-issues pass (166 rows, next-id=169); outstanding-issues.mjs --self-test pass; vitest tests/outstanding-issues-writer.test.ts 8/8; merge-tree clean vs origin/main; format clean; no provider-backed checks" }, { @@ -11993,7 +12035,7 @@ "ref": "claude/sentry-agent-monitoring-eri94v", "head": "38378ac78c0b288b6e93b638019653001f375042", "scope": "Sentry AI agent monitoring (OpenAI wrap, gen_ai scrubber allowlist, conversation id)", - "outcome": "pass \u2014 metadata-only instrumentation; privacy boundary preserved", + "outcome": "pass — metadata-only instrumentation; privacy boundary preserved", "checks": "verify:pr-local,verify:cheap,typecheck,vitest 458 files green" }, { @@ -12001,7 +12043,7 @@ "ref": "claude/sentry-agent-monitoring-eri94v", "head": "d521fe9dc4ce50e94273a77ee819332afc5bc7e1", "scope": "Ingestion-worker Sentry error reporting (worker/observability.ts, SAFE_TAGS worker keys, @sentry/node direct dep, docs + ledger #183)", - "outcome": "pass \u2014 additive capture only; privacy scrubbers reused, worker events pinned by tests", + "outcome": "pass — additive capture only; privacy scrubbers reused, worker events pinned by tests", "checks": "verify:pr-local exit 0 (460 files/4794 tests, build, eval:rag:offline),build:worker,npm ci --dry-run,check:outstanding-issues" }, { @@ -12081,7 +12123,7 @@ "ref": "codex/address-performance-issues-in-package", "head": "caced05a1bd9f0047e14ce5ab21d56f03f8ce0ec", "scope": "PR #1489 review+bugbot+fix+heavy", - "outcome": "fixed Build bundle-budget post-success hang (CI timeout\u2192cancelled); stream measure + exitProcess failsafe + 3m step timeout; supersedes a861c968/2257c221", + "outcome": "fixed Build bundle-budget post-success hang (CI timeout→cancelled); stream measure + exitProcess failsafe + 3m step timeout; supersedes a861c968/2257c221", "checks": "vitest bundle-budget 14/14; check:bundle-budget done; check:github-actions passed" }, { @@ -12321,7 +12363,7 @@ "ref": "codex/reduce-catalogue-json-bundle-weight", "head": "4d1f776ae77c26b2b323caad2eb43651f5b823bd", "scope": "PR #1468 review+bugbot+fix+heavy", - "outcome": "PASS heavy: synced main (DIRTY\u2192clean); no PR-introduced P0/P1/P2; Production UI #146 Services settle flake dispositioned as pre-existing (not cache-caused); required CI expected after sync push", + "outcome": "PASS heavy: synced main (DIRTY→clean); no PR-introduced P0/P1/P2; Production UI #146 Services settle flake dispositioned as pre-existing (not cache-caused); required CI expected after sync push", "checks": "merge-tree clean; verify:cheap 445 files/4659 passed; verify:pr-local + rag fixtures; check:github-actions prior; bugbot+diff review" }, { @@ -12929,7 +12971,7 @@ "ref": "claude/organize-local-worktree-d22bc3", "head": "2f26a53b5aeb3df451cf7b1d04f80b07edf0d6fe", "scope": "docs organisation: dated-record filing, docs index gaps, orientation maps", - "outcome": "PR #1436 opened \u2014 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", + "outcome": "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", "checks": "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" }, { @@ -12985,7 +13027,7 @@ "ref": "claude/test-coverage-analysis-2vcd8a", "head": "4f498b66a56b2a7eddde6c841a79621f23b59cc7", "scope": "PR #1398 babysit", - "outcome": "BLOCKER CLEARED: CONFLICTING due to docs/outstanding-issues.md vs main (#115 band-adoption follow-up). Kept main #115 + next-id=116; preserved PR #109 single-branch/refspec update. Prior tip had no GitHub CI suite (only PR Policy/CircleCI) \u2014 push retriggered full CI. 0 review threads; 0 Bugbot findings.", + "outcome": "BLOCKER CLEARED: CONFLICTING due to docs/outstanding-issues.md vs main (#115 band-adoption follow-up). Kept main #115 + next-id=116; preserved PR #109 single-branch/refspec update. Prior tip had no GitHub CI suite (only PR Policy/CircleCI) — push retriggered full CI. 0 review threads; 0 Bugbot findings.", "checks": "verify:cheap PASS (432 files, 4467 passed | 4 skipped); repo-hygiene 38/38; sweep:branch-ledger --no-fetch exit 0; format:changed PASS; Bugbot none; hosted CI re-triggered on tip" }, { @@ -12993,7 +13035,7 @@ "ref": "claude/test-coverage-analysis-2vcd8a", "head": "d5842e62238237ff5c47da0b32ef8d9f12819714", "scope": "PR #1398 babysit", - "outcome": "COMPLETE for tip: cleared main conflict; fixed Codex P2 (reject refs/*\u2192origin/* nesting); prior Codex P2 (destination check) already fixed in de594186 and resolved; 0 unresolved threads; merge-tree clean. Hosted CI re-running.", + "outcome": "COMPLETE for tip: cleared main conflict; fixed Codex P2 (reject refs/*→origin/* nesting); prior Codex P2 (destination check) already fixed in de594186 and resolved; 0 unresolved threads; merge-tree clean. Hosted CI re-running.", "checks": "repo-hygiene 40/40; verify:cheap earlier PASS on pre-tip; format:changed PASS; Bugbot none; Codex P2 resolved" }, { @@ -13033,7 +13075,7 @@ "ref": "claude/white-element-positioning-t607pk", "head": "db341491b0d94cf11641eb98aa8726629580a652", "scope": "phone-chrome safe-area paint fix", - "outcome": "APPROVED \u2014 no P0/P1. One P2 pre-existing residual (spacer/bar mismatch on notched tablet sm+ in PWA mode \u2014 worse before, slightly better after; no action needed). P3: contract test slice brittleness (indexOf '/>') and invariant-6 prose length. No defects introduced.", + "outcome": "APPROVED — no P0/P1. One P2 pre-existing residual (spacer/bar mismatch on notched tablet sm+ in PWA mode — worse before, slightly better after; no action needed). P3: contract test slice brittleness (indexOf '/>') and invariant-6 prose length. No defects introduced.", "checks": "vitest header-scroll-hide-contract 27/27 green; source read: master-search-header.tsx, globals.css forced-colors block, tests/header-scroll-hide-contract.test.ts, docs/search-chrome-behaviour.md" }, { @@ -13057,7 +13099,7 @@ "ref": "claude/x3-rag-coverage-gate-qx9j7d (PR #1454, squashed as 102bb1f)", "head": "102bb1f5edf09e666d1be5934ff5dfb2aa5abcf0", "scope": "X3/#086 evidence coverage gate extraction from rag.ts into rag-coverage-gate.ts", - "outcome": "clean and landed \u2014 byte-identical move verified against pre-merge main, rag.ts 5030->4780, budget ratcheted to 4780, no back-edge, public re-export preserved; squash captured 100% of branch content, nothing orphaned", + "outcome": "clean and landed — byte-identical move verified against pre-merge main, rag.ts 5030->4780, budget ratcheted to 4780, no back-edge, public re-export preserved; squash captured 100% of branch content, nothing orphaned", "checks": "workflow:rag-lab, focused vitest 81/81, check:maintainability-budgets 4780/4780, check:rag:fixtures 36 golden, eval:rag:offline 567/567, typecheck, lint, check:knip, format:check, verify:cheap 4569 passed, npm test 4569 passed, verify:pr-local build+bundle-scan, post-merge npm test on main 4574 passed" }, { @@ -13065,7 +13107,7 @@ "ref": "claude/x3-rag-coverage-gate-qx9j7d (PR #1463, squashed as dba7356f)", "head": "dba7356fc8dc926d951d6de6f019d5b8e000be21", "scope": "X3/#101 per-request hydration extraction from rag.ts into rag-hydration.ts", - "outcome": "clean and landed \u2014 byte-identical move verified against pre-merge main, rag.ts 4780->4543, budget ratcheted to 4543, no back-edge (cluster referenced zero rag.ts-local symbols), both public re-exports preserved; squash captured 100% of branch content", + "outcome": "clean and landed — byte-identical move verified against pre-merge main, rag.ts 4780->4543, budget ratcheted to 4543, no back-edge (cluster referenced zero rag.ts-local symbols), both public re-exports preserved; squash captured 100% of branch content", "checks": "typecheck, lint, check:knip, check:maintainability-budgets 4543/4543, focused vitest 83/83 incl rag-query-concurrency, eval:rag:offline 572/572 36 golden, format:check, verify:cheap, verify:pr-local build+bundle-scan, post-merge content verification on main" }, { @@ -13289,7 +13331,7 @@ "ref": "codex/computed-style-assertions", "head": "1f431caa8d80660b8f6d90f557e4b8ea5d82560c", "scope": "post-sync archive completed rendered-style contract task #094", - "outcome": "APPROVED \u2014 no findings after exact current-main sync; archive move and prior review record only.", + "outcome": "APPROVED — no findings after exact current-main sync; archive move and prior review record only.", "checks": "check:outstanding-issues PASS (151 rows; 44 open, 107 archived); branch-review-ledger PASS (254 live, 1206 archived); git diff --check PASS; merge-tree 9ab802e9ec73132e4a7231b9060bf95be090b9d2" }, { @@ -13297,7 +13339,7 @@ "ref": "codex/computed-style-assertions", "head": "229b0d396decd0ad7f7779b57631ae1f137752d7", "scope": "archive completed rendered-style contract task #094", - "outcome": "APPROVED \u2014 no findings; docs-only archive move matches landed computed-style, forced-colors, tap-size, and unlayered-class registry evidence.", + "outcome": "APPROVED — no findings; docs-only archive move matches landed computed-style, forced-colors, tap-size, and unlayered-class registry evidence.", "checks": "check:outstanding-issues PASS (148 rows; 42 open, 106 archived); git diff --check PASS; implementation commits verified ancestral to origin/main" }, { @@ -13305,7 +13347,7 @@ "ref": "codex/computed-style-assertions", "head": "a18085a15339f280fff76cad15fafcf1a80084fe", "scope": "post-#1490 sync archive rendered-style task #094", - "outcome": "APPROVED \u2014 no findings; current-main issue additions are preserved and #094 is the sole state change.", + "outcome": "APPROVED — no findings; current-main issue additions are preserved and #094 is the sole state change.", "checks": "outstanding-issues PASS (151 rows; 43 open, 108 archived); branch-review-ledger PASS (271 live, 1206 archived); diff check PASS; merge-tree ab18c4319fcca6c915d340bdea286481caa8ea43" }, { @@ -13313,7 +13355,7 @@ "ref": "codex/computed-style-assertions", "head": "a8ee3315f2c9959025b7d652c0b7ea45432ca6be", "scope": "post-#121 sync archive rendered-style task #094", - "outcome": "APPROVED \u2014 no findings; #121 main merge preserved and #094 remains the only issue-state change.", + "outcome": "APPROVED — no findings; #121 main merge preserved and #094 remains the only issue-state change.", "checks": "outstanding-issues PASS (151 rows; 43 open, 108 archived); branch-review-ledger PASS (261 live, 1206 archived); diff check PASS; merge-tree 2c567bcbb60f5d3f36eb18b6f7d7f6ee2a7a788b" }, { @@ -14569,7 +14611,7 @@ "ref": "cursor/ci-hygiene-gates-1bf5", "head": "ad9da6a6f8ba3884b389fa78e678bb88ee72d9d1", "scope": "ci-hygiene-gates", - "outcome": "implemented matrix unblock, scope narrow, cancelled\u2260failure, pinned gitleaks, critical-first UI, eval:rag:offline; skipped #093; verify:cheap 4471 pass", + "outcome": "implemented matrix unblock, scope narrow, cancelled≠failure, pinned gitleaks, critical-first UI, eval:rag:offline; skipped #093; verify:cheap 4471 pass", "checks": "verify:cheap,check:ci-scope,check:gitleaks-pinned,check:gate-manifest,eval:rag:offline" }, { @@ -14641,7 +14683,7 @@ "ref": "dba7356fc8dc926d951d6de6f019d5b8e000be21", "head": "dba7356fc8dc926d951d6de6f019d5b8e000be21", "scope": "X3 hydration unit: per-request hydration extraction from rag.ts into rag-hydration.ts (PR #1463)", - "outcome": "clean and landed \u2014 byte-identical move verified against pre-merge main, rag.ts 4780->4543, budget ratcheted to 4543, no back-edge, both public re-exports preserved. Supersedes the earlier row for this HEAD, which was keyed only to the slash-form branch token and so returned NOT REVIEWED on a landed-SHA lookup; it also mislabelled the unit as #101, which is the unrelated open canary-gated retrieval-parallelisation recommendation", + "outcome": "clean and landed — byte-identical move verified against pre-merge main, rag.ts 4780->4543, budget ratcheted to 4543, no back-edge, both public re-exports preserved. Supersedes the earlier row for this HEAD, which was keyed only to the slash-form branch token and so returned NOT REVIEWED on a landed-SHA lookup; it also mislabelled the unit as #101, which is the unrelated open canary-gated retrieval-parallelisation recommendation", "checks": "typecheck, lint, check:knip, check:maintainability-budgets 4543/4543, focused vitest 83/83, eval:rag:offline 572/572 36 golden, format:check, verify:cheap 442 files 4625 passed, verify:pr-local, post-merge content verification on main" }, { @@ -14689,7 +14731,7 @@ "ref": "origin/codex/document-reader-condensed-view", "head": "b5cdbf301d517239ffe9ed941b9ebe809aea0bfd", "scope": "branch-cleanup", - "outcome": "safe to delete \u2014 tip tree identical to merge-base tree (855aa291), so the branch nets zero content change vs main; --cherry-pick shows 13 commits, a squash-merge false positive", + "outcome": "safe to delete — tip tree identical to merge-base tree (855aa291), so the branch nets zero content change vs main; --cherry-pick shows 13 commits, a squash-merge false positive", "checks": "git diff --name-only merge-base..tip = 0 files; tree(tip)==tree(merge-base); git ls-remote confirms live HEAD" }, { @@ -14697,7 +14739,7 @@ "ref": "origin/codex/document-reader-condensed-view", "head": "b5cdbf301d517239ffe9ed941b9ebe809aea0bfd", "scope": "branch-cleanup (supersedes 2026-07-30)", - "outcome": "safe to delete \u2014 merge-base 855aa291 is an ANCESTOR of main and tree(tip)==tree(855aa291), so every byte at the tip exists in main's history; the 13 --cherry-pick commits are merges of main plus work already squash-merged, not uncancelled work", + "outcome": "safe to delete — merge-base 855aa291 is an ANCESTOR of main and tree(tip)==tree(855aa291), so every byte at the tip exists in main's history; the 13 --cherry-pick commits are merges of main plus work already squash-merged, not uncancelled work", "checks": "git merge-base --is-ancestor 855aa291 origin/main = YES; tree(tip)==tree(855aa291); feature blobs present and byte-identical on origin/main; supersedes the earlier row, which omitted the ancestor step (Codex P2, PR #1398/#1403)" }, { @@ -14713,7 +14755,7 @@ "ref": "origin/cursor/page-anchored-search-composer-30ee", "head": "7ff134ca7f614db527b8d142676640305533669d", "scope": "branch-cleanup", - "outcome": "safe to delete \u2014 tip tree identical to merge-base tree (79d1c879), so the branch nets zero content change vs main; --cherry-pick shows 6 commits, a squash-merge false positive", + "outcome": "safe to delete — tip tree identical to merge-base tree (79d1c879), so the branch nets zero content change vs main; --cherry-pick shows 6 commits, a squash-merge false positive", "checks": "git diff --name-only merge-base..tip = 0 files; tree(tip)==tree(merge-base); git ls-remote confirms live HEAD" }, { @@ -14721,7 +14763,7 @@ "ref": "origin/cursor/page-anchored-search-composer-30ee", "head": "7ff134ca7f614db527b8d142676640305533669d", "scope": "branch-cleanup (supersedes 2026-07-30)", - "outcome": "safe to delete \u2014 merge-base 79d1c879 is an ANCESTOR of main and tree(tip)==tree(79d1c879), so every byte at the tip exists in main's history; the 6 --cherry-pick commits are merges of main plus work already squash-merged, not uncancelled work", + "outcome": "safe to delete — merge-base 79d1c879 is an ANCESTOR of main and tree(tip)==tree(79d1c879), so every byte at the tip exists in main's history; the 6 --cherry-pick commits are merges of main plus work already squash-merged, not uncancelled work", "checks": "git merge-base --is-ancestor 79d1c879 origin/main = YES; tree(tip)==tree(79d1c879); feature blobs present and byte-identical on origin/main; supersedes the earlier row, which omitted the ancestor step (Codex P2, PR #1398/#1403)" }, { @@ -14729,7 +14771,7 @@ "ref": "origin/cursor/pr-1379-babysit-ledger-9365", "head": "be2de03f855cb7fdfccea4bb74d05eb4c9bf6c61", "scope": "branch-cleanup", - "outcome": "safe to delete \u2014 tip tree identical to merge-base tree (b2740480), so the branch nets zero content change vs main; --cherry-pick shows 4 commits, a squash-merge false positive", + "outcome": "safe to delete — tip tree identical to merge-base tree (b2740480), so the branch nets zero content change vs main; --cherry-pick shows 4 commits, a squash-merge false positive", "checks": "git diff --name-only merge-base..tip = 0 files; tree(tip)==tree(merge-base); git ls-remote confirms live HEAD" }, { @@ -14737,7 +14779,7 @@ "ref": "origin/cursor/pr-1379-babysit-ledger-9365", "head": "be2de03f855cb7fdfccea4bb74d05eb4c9bf6c61", "scope": "branch-cleanup (supersedes 2026-07-30)", - "outcome": "safe to delete \u2014 merge-base b2740480 is an ANCESTOR of main and tree(tip)==tree(b2740480), so every byte at the tip exists in main's history; the 4 --cherry-pick commits are merges of main plus work already squash-merged, not uncancelled work", + "outcome": "safe to delete — merge-base b2740480 is an ANCESTOR of main and tree(tip)==tree(b2740480), so every byte at the tip exists in main's history; the 4 --cherry-pick commits are merges of main plus work already squash-merged, not uncancelled work", "checks": "git merge-base --is-ancestor b2740480 origin/main = YES; tree(tip)==tree(b2740480); feature blobs present and byte-identical on origin/main; supersedes the earlier row, which omitted the ancestor step (Codex P2, PR #1398/#1403)" }, { @@ -14745,7 +14787,7 @@ "ref": "origin/execute-audit-code-remediation", "head": "3470279fba23ad442d59d34552eb576e87f24141", "scope": "branch-cleanup", - "outcome": "REJECTED and deleted remote. PR #1162 already merged; sole unique commit was a ledger CI-green row already present on main (edcd17a1\u2026). No open PR; no unique product content.", + "outcome": "REJECTED and deleted remote. PR #1162 already merged; sole unique commit was a ledger CI-green row already present on main (edcd17a1…). No open PR; no unique product content.", "checks": "fetch --prune; cherry-pick log; tip-to-tip/three-dot; grep ledger for edcd17a1; gh pr 1162 MERGED; open=0; GitHub reads explicitly authorized; no non-GitHub provider checks." }, { @@ -14800,7 +14842,7 @@ "date": "2026-07-30", "ref": "PR #1394 / `claude/top-search-design-mockups-w53znc`", "head": "0d47141fc030684299dcb265e3d853c93b9e2a91", - "scope": "CI/review closeout \u2014 merged", + "scope": "CI/review closeout — merged", "outcome": "MERGED as squash `0d47141f`. Prior tip `4a001efa` had required CI green after prettier fix `61314887` (Static PR/CircleCI red on `#096` padding) and main sync. Layout/`/tools` false-positive fixed; `#115` deferred; review threads resolved. Post-merge ledger-only follow-up.", "checks": "hosted Static/Unit/PR-required/CircleCI pass on pre-merge tip; vitest adoption 6/6; typecheck; Bugbot no open P0/P1; merge-tree clean" }, @@ -14905,7 +14947,7 @@ "ref": "PR #1400", "head": "e869cb9d7ab20939361b277d1c6fcc07bbb6ca45", "scope": "pr-1400-guard-push-band-adoption", - "outcome": "MERGED \u2014 17 review findings across guard-push.mjs and the band-adoption gate, all fixed and thread-resolved; each fix confirmed by reverting it and watching the guard fail. Guard now checks the pushed SHA in a git worktree (config, dynamic config, policy escalation incl. removal, lockfile Prettier parity); adoption gate replaced presence-matching with per-module reachability, closing six false greens of one root cause plus type-position edges found in self-review. Merge verified: all 8 commits ancestors of main, 4 changed files byte-identical.", + "outcome": "MERGED — 17 review findings across guard-push.mjs and the band-adoption gate, all fixed and thread-resolved; each fix confirmed by reverting it and watching the guard fail. Guard now checks the pushed SHA in a git worktree (config, dynamic config, policy escalation incl. removal, lockfile Prettier parity); adoption gate replaced presence-matching with per-module reachability, closing six false greens of one root cause plus type-position edges found in self-review. Merge verified: all 8 commits ancestors of main, 4 changed files byte-identical.", "checks": "verify:cheap 432 files / 4470 passed 4 skipped; format:check clean; PR required success; services+tools page gutting reports orphans; 6 push-guard scratch-repo cases with real exit codes; every fixture mutation-verified" }, { @@ -15393,7 +15435,7 @@ "ref": "PR-1507", "head": "12e5c8c977a873a7b900596fdc310a1a78d863f0", "scope": "PR #1507 current-main merge and ledger normalization", - "outcome": "APPROVED \u2014 no findings after current-main sync; feature diff unchanged and ledger reduced to three unique append-only review rows.", + "outcome": "APPROVED — no findings after current-main sync; feature diff unchanged and ledger reduced to three unique append-only review rows.", "checks": "focused Vitest 2 files/40 tests PASS; outstanding-issues PASS; branch-review-ledger PASS; diff check PASS; merge-tree f8f88bd79706c2fb36637014a25e93af6e08eb99" }, { @@ -15409,7 +15451,7 @@ "ref": "PR-1507", "head": "5e22b89f7bdb73335d12a0cf4091915615b20dd7", "scope": "PR #1507 remote ancestry reconciliation", - "outcome": "APPROVED \u2014 identical-tree remote merge ancestry reconciled without content change; no remaining findings.", + "outcome": "APPROVED — identical-tree remote merge ancestry reconciled without content change; no remaining findings.", "checks": "focused Vitest 2 files/40 tests PASS on identical tree; issue and ledger guards PASS; diff check PASS; merge-tree d6594063a4aa2c5f8b7a9ec72c1c41c94e6937fa" }, { @@ -15529,7 +15571,7 @@ "ref": "1374", "head": "c14edb9c6f0bdbbfb147752503e016f2543fd803", "scope": "PR #1374 review + merge", - "outcome": "merged as 3704007c \u2014 DocumentViewer identity-bound state clear (P1) implemented and verified red without it; all 12 review threads resolved", + "outcome": "merged as 3704007c — DocumentViewer identity-bound state clear (P1) implemented and verified red without it; all 12 review threads resolved", "checks": "verify:cheap exit 0 (429 files / 4403 tests); PR required success; Production UI success" }, { @@ -15537,7 +15579,7 @@ "ref": "1391", "head": "baecef05cac86c4d52af895d483a33ba3c40cd61", "scope": "PR #1391 review", - "outcome": "reviewed clean \u2014 text-4xs retirement confirmed against globals.css (--text-3xs 0.625rem present, --text-4xs absent); orphan guard proven to fail on a reintroduced class; six Playwright retries all retry action-plus-effect so a genuine regression still fails. Resolved the outstanding-issues #108/#109 double-allocation (renumbered to #110/#111, marker to 112) and recorded #111 done", + "outcome": "reviewed clean — text-4xs retirement confirmed against globals.css (--text-3xs 0.625rem present, --text-4xs absent); orphan guard proven to fail on a reintroduced class; six Playwright retries all retry action-plus-effect so a genuine regression still fails. Resolved the outstanding-issues #108/#109 double-allocation (renumbered to #110/#111, marker to 112) and recorded #111 done", "checks": "verify:cheap exit 0 (429 files / 4404 tests); design-token-contract 28 passed; check:branch-review-ledger passed" }, { @@ -15601,7 +15643,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb", "head": "df29f311b60cadf8e43bf51283a9d6f496b295e3", "scope": "branch-cleanup-deletion-pending", - "outcome": "DELETION PENDING \u2014 content proven fully on main. Branch tip IS the merge-base with main (df29f311), so the tip is a direct ancestor of main; tree comparison of merge-base vs tip shows 0 changed files. Backs no open PR. Deletion blocked by HTTP 403; HEAD recorded here so the later branch-cleanup row can be keyed to it after the ref is gone. Supersedes the aggregate main-keyed row at 855aa291, which recorded no candidate HEADs.", + "outcome": "DELETION PENDING — content proven fully on main. Branch tip IS the merge-base with main (df29f311), so the tip is a direct ancestor of main; tree comparison of merge-base vs tip shows 0 changed files. Backs no open PR. Deletion blocked by HTTP 403; HEAD recorded here so the later branch-cleanup row can be keyed to it after the ref is gone. Supersedes the aggregate main-keyed row at 855aa291, which recorded no candidate HEADs.", "checks": "local git only for the content proof: git merge-base, git diff --name-only (0 files), git diff --name-only origin/main... (0 files), full history after git fetch --unshallow. PROVIDER-BACKED evidence obtained (GitHub reads, authorised repo-scope): open-PR head cross-check via GitHub API against PRs #1374/#1377/#1384/#1385/#1386/#1387, and GitHub MCP capability inspection. PROVIDER-BACKED MUTATION ATTEMPTED AND REJECTED: git push origin --delete returned HTTP 403; no branch was deleted. No OpenAI/Supabase/hosted-CI calls." }, { @@ -15609,7 +15651,7 @@ "ref": "claude/dazzling-blackwell-f348d0", "head": "c9bec8f9dce38cb647de9aa64ebf08bf7823a524", "scope": "branch-cleanup-deletion-pending", - "outcome": "DELETION PENDING \u2014 content proven fully on main. Branch tip IS the merge-base with main (c9bec8f9), so the tip is a direct ancestor of main; tree comparison of merge-base vs tip shows 0 changed files. Backs no open PR. Deletion blocked by HTTP 403; HEAD recorded here so the later branch-cleanup row can be keyed to it after the ref is gone. Supersedes the aggregate main-keyed row at 855aa291, which recorded no candidate HEADs.", + "outcome": "DELETION PENDING — content proven fully on main. Branch tip IS the merge-base with main (c9bec8f9), so the tip is a direct ancestor of main; tree comparison of merge-base vs tip shows 0 changed files. Backs no open PR. Deletion blocked by HTTP 403; HEAD recorded here so the later branch-cleanup row can be keyed to it after the ref is gone. Supersedes the aggregate main-keyed row at 855aa291, which recorded no candidate HEADs.", "checks": "local git only for the content proof: git merge-base, git diff --name-only (0 files), git diff --name-only origin/main... (0 files), full history after git fetch --unshallow. PROVIDER-BACKED evidence obtained (GitHub reads, authorised repo-scope): open-PR head cross-check via GitHub API against PRs #1374/#1377/#1384/#1385/#1386/#1387, and GitHub MCP capability inspection. PROVIDER-BACKED MUTATION ATTEMPTED AND REJECTED: git push origin --delete returned HTTP 403; no branch was deleted. No OpenAI/Supabase/hosted-CI calls." }, { @@ -15624,7 +15666,7 @@ "date": "2026-07-29", "ref": "claude/latency-findings-impl-s8g01v", "head": "0e937f80f1c4fdfa66a4e5abc2918e763ed51bc1", - "scope": "PR #1377 latency findings \u2014 operator rollback sequencing", + "scope": "PR #1377 latency findings — operator rollback sequencing", "outcome": "Codex P2 confirmed and fixed: the index rollback merged the revert migration into the expectation deploy, so the deployed migration would take ACCESS EXCLUSIVE on documents before the concurrent drop; split into three deployed phases (retract required_indexes -> concurrent live drop -> schema.sql removal + idempotent forward drop migration). Apply-side commit-vs-deploy ordering made explicit. Docs only.", "checks": "prettier --check clean; docs:check-links 1355; docs:check-scripts 390; check:branch-review-ledger 1232 records" }, @@ -15632,7 +15674,7 @@ "date": "2026-07-29", "ref": "claude/latency-findings-impl-s8g01v", "head": "310d0fbc4f08ca88cb097f3e480896e75d0007bf", - "scope": "PR #1377 latency findings \u2014 search_schema_health registration is a migration", + "scope": "PR #1377 latency findings — search_schema_health registration is a migration", "outcome": "Codex P2 confirmed and fixed: apply step 5 and rollback phase A described the required_indexes change as a schema.sql edit, but schema.sql is a mirror and search_schema_health() is redefined by create or replace function in 11 migrations (precedent 20260705180000_reconcile_search_health_indexes.sql:62). As written the hosted function never moved, leaving the new indexes unmonitored on apply and, on rollback, letting phase B drop indexes the hosted function still required. Both now specify a create-or-replace-function migration plus matching mirror; apply deploys last. Docs only.", "checks": "prettier --check clean; docs:check-links 1356; docs:check-scripts 390" }, @@ -15640,7 +15682,7 @@ "date": "2026-07-29", "ref": "claude/latency-findings-impl-s8g01v", "head": "39ac6fde537946d0dd94712a206725969689f056", - "scope": "PR #1377 latency findings \u2014 RAG canary gate is not lifted by ordering", + "scope": "PR #1377 latency findings — RAG canary gate is not lifted by ordering", "outcome": "Codex P2 confirmed and fixed: the #102 queue row, the #102 detail row and the runbook bullet described the RAG-path index as canary-gated until/unless/or the unordered .limit(12) is ordered, implying ordering lifts the gate. An unordered LIMIT has no stable selection to preserve, so imposing an order can select a different twelve and is itself an ordering behaviour change on a retrieval surface requiring its own canary pair per AGENTS.md. All four sites now state two canary-gated changes rather than one unlockable gate. Docs only; no src/lib/rag change.", "checks": "prettier --check clean; docs:check-links 1356; docs:check-scripts 390" }, @@ -15649,7 +15691,7 @@ "ref": "claude/latency-findings-impl-s8g01v", "head": "71db10c41de872fca6e400626704a549f145c66c", "scope": "latency audit implementation (PR #1377)", - "outcome": "SUPERSEDES the 78e2beb record: its 'scope-vs-ratelimit overlap with abort' description is stale and describes behaviour that was REVERTED. Codex review raised it P1 and it was correct \u2014 an AbortSignal cannot un-execute a statement Postgres already began, and resolveSearchScope only skips the database when there are no filters and no explicit ids (search-scope.ts:242,253), so a throttled caller kept spending DB capacity while collecting 429s. Shipped behaviour is rate-limit admission BEFORE scope evaluation, with request.signal threaded so a client disconnect still cancels scope's paginated queries, pinned by tests/answer-route-preamble.test.ts. Also retracted on this head: the L2-3 'recall is byte-identical' claim, since fetchDocumentTitleAliasRows applies .limit(12) with no ORDER BY.", + "outcome": "SUPERSEDES the 78e2beb record: its 'scope-vs-ratelimit overlap with abort' description is stale and describes behaviour that was REVERTED. Codex review raised it P1 and it was correct — an AbortSignal cannot un-execute a statement Postgres already began, and resolveSearchScope only skips the database when there are no filters and no explicit ids (search-scope.ts:242,253), so a throttled caller kept spending DB capacity while collecting 429s. Shipped behaviour is rate-limit admission BEFORE scope evaluation, with request.signal threaded so a client disconnect still cancels scope's paginated queries, pinned by tests/answer-route-preamble.test.ts. Also retracted on this head: the L2-3 'recall is byte-identical' claim, since fetchDocumentTitleAliasRows applies .limit(12) with no ORDER BY.", "checks": "verify:cheap exit 0 (423 files, 4278 passed/4 skipped); check:branch-review-ledger pass; focused preamble + server-timing suites pass" }, { @@ -15664,7 +15706,7 @@ "date": "2026-07-29", "ref": "claude/latency-findings-impl-s8g01v", "head": "881b7cfe9f4c9b313e70496968d5a7591f2b594d", - "scope": "PR #1377 latency findings \u2014 #103 drift allowlist is not a reconciliation route", + "scope": "PR #1377 latency findings — #103 drift allowlist is not a reconciliation route", "outcome": "Codex P2 confirmed and fixed: the #103 queue and detail rows offered drift-allowlist.json as an alternative to mirroring document_table_facts_text_trgm_idx into schema.sql. The allowlist header scopes it to live-vs-schema.sql divergence, so it cannot reconcile migrations with the mirror; a fresh db reset still runs 20260714190000 while schema.sql omits the index, leaving the row outcome unmet. Both rows now give exactly two routes (mirror, or forward-migration drop after live scan evidence) and record that no offline gate catches this. Docs only.", "checks": "prettier --check clean; docs:check-links 1356; docs:check-scripts 390" }, @@ -15672,7 +15714,7 @@ "date": "2026-07-29", "ref": "claude/latency-findings-impl-s8g01v", "head": "9e2ee65ca0bcce45a3cb6a0539e265ec8d961582", - "scope": "PR #1377 latency findings \u2014 #098 stale offline-harness references", + "scope": "PR #1377 latency findings — #098 stale offline-harness references", "outcome": "Codex P2 confirmed and fixed: the #098 row in docs/outstanding-issues.md still named test-cache-path.mjs and check-rag-fixtures.mjs as the offline fixtures for the round-trip counting harness. Neither exercises a RAG request (cache paths; fixture-manifest validation), so a harness built on them would count nothing. The audit doc carried the retraction at :358 but this row did not - the same local-retraction pattern flagged in two prior rounds. Now names eval-rag-offline.mjs, test-rag-offline.mjs, rag-offline-contract.mjs and the contract fixture, all verified present, with the correction recorded inline. Docs only.", "checks": "prettier --check clean; docs:check-links 1363; docs:check-scripts 390; grep confirms no stale refs remain" }, @@ -15737,7 +15779,7 @@ "ref": "claude/test-coverage-analysis-2vcd8a", "head": "f4a3f50048fa113d5e4e704defdafad2d37ba8d2", "scope": "prlanded", - "outcome": "MERGED AND VERIFIED. PR #1383 squash-merged as f4a3f50. Content diff between the squash commit and branch tip bebc6c02 is EMPTY \u2014 nothing orphaned by the auto-merge race despite four concurrent pushes during the merge window. Landed on main: tests/calculator-scoring.test.ts (60 tests, 8 validated instruments), 9 batch signed-URL cases in tests/private-access-routes.test.ts, coverage floors raised 48/38/43/50 -> 62/53/55/64. Follow-ups renumbered #098/#099 -> #106/#107 during the main merge (main had claimed #098-#105); both rows verified present with content intact and next-id marker at 108. The three red 'PR required' results at 0922d7f/6f476b5/b72bc20 were concurrency cancellations (issue #095), not defects \u2014 all upstream jobs reported 'cancelled'; the clean run 30447852418 at tip bebc6c0 superseded them.", + "outcome": "MERGED AND VERIFIED. PR #1383 squash-merged as f4a3f50. Content diff between the squash commit and branch tip bebc6c02 is EMPTY — nothing orphaned by the auto-merge race despite four concurrent pushes during the merge window. Landed on main: tests/calculator-scoring.test.ts (60 tests, 8 validated instruments), 9 batch signed-URL cases in tests/private-access-routes.test.ts, coverage floors raised 48/38/43/50 -> 62/53/55/64. Follow-ups renumbered #098/#099 -> #106/#107 during the main merge (main had claimed #098-#105); both rows verified present with content intact and next-id marker at 108. The three red 'PR required' results at 0922d7f/6f476b5/b72bc20 were concurrency cancellations (issue #095), not defects — all upstream jobs reported 'cancelled'; the clean run 30447852418 at tip bebc6c0 superseded them.", "checks": "post-merge verification only: content diff squash-vs-tip EMPTY; origin/main content spot-checks PASS (test file present, floors 62/53/55/64, #106/#107 rows, 13 signed-urls refs); pre-merge local gates on the merged tree: test:coverage PASS exit 0 (424 files, 4371 passed | 4 skipped, no threshold errors); no provider-backed checks" }, { @@ -15769,7 +15811,7 @@ "ref": "codex/document-reader-condensed-view", "head": "b5cdbf301d517239ffe9ed941b9ebe809aea0bfd", "scope": "branch-cleanup-deletion-pending", - "outcome": "DELETION PENDING \u2014 content proven fully on main. Merge-base with main is 855aa291 and tree(merge-base) equals tree(tip): git diff --name-only 855aa291 b5cdbf30 reports 0 files, so the tip introduces nothing beyond a state already in main. Its work landed as main's tip via squash. Backs no open PR. Deletion blocked by HTTP 403; HEAD recorded here so the later branch-cleanup row can be keyed to it after the ref is gone. Supersedes the aggregate main-keyed row at 855aa291, which recorded no candidate HEADs.", + "outcome": "DELETION PENDING — content proven fully on main. Merge-base with main is 855aa291 and tree(merge-base) equals tree(tip): git diff --name-only 855aa291 b5cdbf30 reports 0 files, so the tip introduces nothing beyond a state already in main. Its work landed as main's tip via squash. Backs no open PR. Deletion blocked by HTTP 403; HEAD recorded here so the later branch-cleanup row can be keyed to it after the ref is gone. Supersedes the aggregate main-keyed row at 855aa291, which recorded no candidate HEADs.", "checks": "local git only for the content proof: git merge-base, git diff --name-only (0 files), git diff --name-only origin/main... (0 files), full history after git fetch --unshallow. PROVIDER-BACKED evidence obtained (GitHub reads, authorised repo-scope): open-PR head cross-check via GitHub API against PRs #1374/#1377/#1384/#1385/#1386/#1387, and GitHub MCP capability inspection. PROVIDER-BACKED MUTATION ATTEMPTED AND REJECTED: git push origin --delete returned HTTP 403; no branch was deleted. No OpenAI/Supabase/hosted-CI calls." }, { @@ -15833,7 +15875,7 @@ "ref": "cursor/page-anchored-search-composer-30ee", "head": "7ff134ca7f614db527b8d142676640305533669d", "scope": "branch-cleanup-deletion-pending", - "outcome": "DELETION PENDING \u2014 content proven fully on main. Merge-base with main is 79d1c879 and tree(merge-base) equals tree(tip): git diff --name-only 79d1c879 7ff134ca reports 0 files, so the tip introduces nothing beyond a state already in main. Backs no open PR. Deletion blocked by HTTP 403; HEAD recorded here so the later branch-cleanup row can be keyed to it after the ref is gone. Supersedes the aggregate main-keyed row at 855aa291, which recorded no candidate HEADs.", + "outcome": "DELETION PENDING — content proven fully on main. Merge-base with main is 79d1c879 and tree(merge-base) equals tree(tip): git diff --name-only 79d1c879 7ff134ca reports 0 files, so the tip introduces nothing beyond a state already in main. Backs no open PR. Deletion blocked by HTTP 403; HEAD recorded here so the later branch-cleanup row can be keyed to it after the ref is gone. Supersedes the aggregate main-keyed row at 855aa291, which recorded no candidate HEADs.", "checks": "local git only for the content proof: git merge-base, git diff --name-only (0 files), git diff --name-only origin/main... (0 files), full history after git fetch --unshallow. PROVIDER-BACKED evidence obtained (GitHub reads, authorised repo-scope): open-PR head cross-check via GitHub API against PRs #1374/#1377/#1384/#1385/#1386/#1387, and GitHub MCP capability inspection. PROVIDER-BACKED MUTATION ATTEMPTED AND REJECTED: git push origin --delete returned HTTP 403; no branch was deleted. No OpenAI/Supabase/hosted-CI calls." }, { @@ -15841,7 +15883,7 @@ "ref": "cursor/pr-1379-babysit-ledger-9365", "head": "be2de03f855cb7fdfccea4bb74d05eb4c9bf6c61", "scope": "branch-cleanup-deletion-pending", - "outcome": "DELETION PENDING \u2014 content proven fully on main. Merge-base with main is b2740480 and tree(merge-base) equals tree(tip): git diff --name-only b2740480 be2de03f reports 0 files, so the tip introduces nothing beyond a state already in main. Backs no open PR. Deletion blocked by HTTP 403; HEAD recorded here so the later branch-cleanup row can be keyed to it after the ref is gone. Supersedes the aggregate main-keyed row at 855aa291, which recorded no candidate HEADs.", + "outcome": "DELETION PENDING — content proven fully on main. Merge-base with main is b2740480 and tree(merge-base) equals tree(tip): git diff --name-only b2740480 be2de03f reports 0 files, so the tip introduces nothing beyond a state already in main. Backs no open PR. Deletion blocked by HTTP 403; HEAD recorded here so the later branch-cleanup row can be keyed to it after the ref is gone. Supersedes the aggregate main-keyed row at 855aa291, which recorded no candidate HEADs.", "checks": "local git only for the content proof: git merge-base, git diff --name-only (0 files), git diff --name-only origin/main... (0 files), full history after git fetch --unshallow. PROVIDER-BACKED evidence obtained (GitHub reads, authorised repo-scope): open-PR head cross-check via GitHub API against PRs #1374/#1377/#1384/#1385/#1386/#1387, and GitHub MCP capability inspection. PROVIDER-BACKED MUTATION ATTEMPTED AND REJECTED: git push origin --delete returned HTTP 403; no branch was deleted. No OpenAI/Supabase/hosted-CI calls." }, { @@ -15897,7 +15939,7 @@ "ref": "main", "head": "855aa2914fd9cf29f9ce34f67e197d7a2d0c1a86", "scope": "branch-cleanup-deletion-pending", - "outcome": "Full-history branch-cleanup review of all 92 remote branches. IMPORTANT PRECONDITION: the session clone was SHALLOW (74 commits of origin/main); every merge-base and cherry-pick result computed before 'git fetch --unshallow' was invalid, and an initial pass wrongly showed 90/91 branches as carrying unmerged work. After unshallowing (2829 commits) the analysis is sound. Cherry-pick matching alone finds only 2 candidates because squash merges collapse N commits into 1 so per-commit patch-ids never match; a content test (files touched vs merge-base, compared between branch tip and main) finds 5. VERIFIED SAFE TO DELETE \u2014 each introduces an empty diff against main and backs no open PR: claude/clinical-kb-pwa-review-asi3wb, claude/dazzling-blackwell-f348d0, codex/document-reader-condensed-view, cursor/page-anchored-search-composer-30ee, cursor/pr-1379-babysit-ledger-9365. DELETION BLOCKED: the session git proxy rejects ref deletion with HTTP 403 and the GitHub MCP toolset exposes no delete-branch capability, so the five remain and must be removed from the GitHub UI or an interactive session. The other 87 were NOT cleared: their touched files still differ from main, which is the conservative direction (a branch whose files main later modified reads as not-landed). Local cleanup done: stale local main fast-forwarded to origin/main (0 ahead, 0 patch-unique after unshallow \u2014 its earlier 'ahead 52 / unrelated histories' was purely the shallow-clone artifact); redundant local claude/prlanded-ledger-1383 deleted after confirming its row is in the pushed branch.", + "outcome": "Full-history branch-cleanup review of all 92 remote branches. IMPORTANT PRECONDITION: the session clone was SHALLOW (74 commits of origin/main); every merge-base and cherry-pick result computed before 'git fetch --unshallow' was invalid, and an initial pass wrongly showed 90/91 branches as carrying unmerged work. After unshallowing (2829 commits) the analysis is sound. Cherry-pick matching alone finds only 2 candidates because squash merges collapse N commits into 1 so per-commit patch-ids never match; a content test (files touched vs merge-base, compared between branch tip and main) finds 5. VERIFIED SAFE TO DELETE — each introduces an empty diff against main and backs no open PR: claude/clinical-kb-pwa-review-asi3wb, claude/dazzling-blackwell-f348d0, codex/document-reader-condensed-view, cursor/page-anchored-search-composer-30ee, cursor/pr-1379-babysit-ledger-9365. DELETION BLOCKED: the session git proxy rejects ref deletion with HTTP 403 and the GitHub MCP toolset exposes no delete-branch capability, so the five remain and must be removed from the GitHub UI or an interactive session. The other 87 were NOT cleared: their touched files still differ from main, which is the conservative direction (a branch whose files main later modified reads as not-landed). Local cleanup done: stale local main fast-forwarded to origin/main (0 ahead, 0 patch-unique after unshallow — its earlier 'ahead 52 / unrelated histories' was purely the shallow-clone artifact); redundant local claude/prlanded-ledger-1383 deleted after confirming its row is in the pushed branch.", "checks": "npm run sweep:branch-ledger (report-only, 2 candidates); full-history recompute after git fetch --unshallow; per-branch git diff origin/main... empty for all 5; open-PR head cross-check against PRs #1374/#1377/#1384/#1385/#1386/#1387; no branch deleted (HTTP 403); no provider-backed checks" }, { @@ -15985,7 +16027,7 @@ "ref": "`codex/fix-p2-audit-20260719`", "head": "d99a71b82abf605f26fcc81ba61cdc805a99a36f", "scope": "Bugbot-style unique product delta vs origin/main (playwright SW block, ClinicalDashboard focus drop, sheet Tab trap, clinical-search neuroleptic/clozapine/med-dose, rag-retrieval-variants, supporting tests)", - "outcome": "CHANGES REQUESTED. No P0. P1: `medicationDoseQueryContext` named-medication gate requires canonical generic token in evidence (`evidenceTokens.has(\"clozapine\")`) and ignores brand aliases, so Clozaril-only evidence fails for Clozaril/clozapine monitoring queries and can rank below unrelated high-hybrid monitoring docs (\u22120.24 / missed +0.26). P2: neuroleptic side-effects early `document_lookup` return preempts dose classification (`What dose applies for neuroleptic side effect management?` \u2192 `document_lookup`). Cleared: SW block + PWA allow, documents `focus:true` removal on in-place pushState ask path, clozapine blood-token retention, Clozaril\u2192clozapine variant intent via analysis.medications. Highest residual: sheet Tab trap rewrite has no Tab-cycle DOM proof.", + "outcome": "CHANGES REQUESTED. No P0. P1: `medicationDoseQueryContext` named-medication gate requires canonical generic token in evidence (`evidenceTokens.has(\"clozapine\")`) and ignores brand aliases, so Clozaril-only evidence fails for Clozaril/clozapine monitoring queries and can rank below unrelated high-hybrid monitoring docs (−0.24 / missed +0.26). P2: neuroleptic side-effects early `document_lookup` return preempts dose classification (`What dose applies for neuroleptic side effect management?` → `document_lookup`). Cleared: SW block + PWA allow, documents `focus:true` removal on in-place pushState ask path, clozapine blood-token retention, Clozaril→clozapine variant intent via analysis.medications. Highest residual: sheet Tab trap rewrite has no Tab-cycle DOM proof.", "checks": "Offline red proofs via temporary Vitest probes (brand gate + neuroleptic class); focused clinical-search regressions 6/6; no OpenAI/Supabase/hosted CI." }, { @@ -16177,7 +16219,7 @@ "ref": "cursor/pr-policy-caveman-docs-dc4e", "head": "c0fe85980b998a7790e99e4a0ab4a04c01934536", "scope": "pr-1335", - "outcome": "docs-ready: caveman\u00d7pr-policy + consolidation ledger", + "outcome": "docs-ready: caveman×pr-policy + consolidation ledger", "checks": "content-proofread,check:branch-review-ledger" }, { @@ -16185,7 +16227,7 @@ "ref": "cursor/pr-policy-caveman-docs-dc4e", "head": "e449eccc7e050736519588a89d2c35b2348e4380", "scope": "pr-1335", - "outcome": "docs-ready: caveman\u00d7pr-policy guidance", + "outcome": "docs-ready: caveman×pr-policy guidance", "checks": "content-proofread" }, { @@ -16209,7 +16251,7 @@ "ref": "open-prs@2026-07-28", "head": "ac786b3553252df48bd13ef414afbcc62e1b41e9", "scope": "open-pr-usefulness", - "outcome": "TRIAGE of 19 open PRs vs origin/main ac786b35: CLOSE #1364 (author throwaway), #1322 (superseded by #1335), #1352 (stale continuation of merged #1305; 595 behind; real merge-tree conflicts; deletes private-access tests / diverges answer+upload). KEEP product: #1366 Claude settings diagnostic, #1365 issues #096/#097, #1335 caveman\u00d7pr-policy docs, #1360 npm-ci CI, #1361 sheet max-h, #1362 calculator/therapy mockups, #1311 doc-nav mockups+viewer, #1351 error/a11y audit, #1298 sheet-focus/P2 tests, #1295 tablet mode-home, #1268/#1269/#1267 dependabot. FOLD ledger-only #1353+#1341+#1363 into one hygiene PR then close the extras. Order: land #1335 before depending on caveman guidance; sync #1361 vs #1298 (same sheet.tsx, different deltas); refresh #1267 after #1366; do not land #096's seven unrun follow-ups piecemeal.", + "outcome": "TRIAGE of 19 open PRs vs origin/main ac786b35: CLOSE #1364 (author throwaway), #1322 (superseded by #1335), #1352 (stale continuation of merged #1305; 595 behind; real merge-tree conflicts; deletes private-access tests / diverges answer+upload). KEEP product: #1366 Claude settings diagnostic, #1365 issues #096/#097, #1335 caveman×pr-policy docs, #1360 npm-ci CI, #1361 sheet max-h, #1362 calculator/therapy mockups, #1311 doc-nav mockups+viewer, #1351 error/a11y audit, #1298 sheet-focus/P2 tests, #1295 tablet mode-home, #1268/#1269/#1267 dependabot. FOLD ledger-only #1353+#1341+#1363 into one hygiene PR then close the extras. Order: land #1335 before depending on caveman guidance; sync #1361 vs #1298 (same sheet.tsx, different deltas); refresh #1267 after #1366; do not land #096's seven unrun follow-ups piecemeal.", "checks": "gh-pr-list; git-fetch-prune; ahead/behind+cherry-pick+merge-tree per tip; three-dot file inventory; overlap matrix; #1305 MERGED proof; content compare SettingsStateProvider/Overlay/z-ladder already on main; #1335 body supersedes #1322; no provider checks; no closes performed" }, { @@ -16297,7 +16339,7 @@ "ref": "PR #1285 / `cursor/pdf-extractor-sigkill-137-0687`", "head": "f1e422e8ee64f7e161e78d9a56707a1a83cc3374", "scope": "CI babysit: PR policy + main sync", - "outcome": "Before: PR marked ready \u2192 PR policy FAIL (missing Clinical Governance Preflight); GitHub CONFLICTING/DIRTY but merge-tree clean (17 behind). 0 unresolved review threads; Bugbot no P0/P1. After: merged origin/main; PR body updated with complete Clinical Governance Preflight (7/7 checked).", + "outcome": "Before: PR marked ready → PR policy FAIL (missing Clinical Governance Preflight); GitHub CONFLICTING/DIRTY but merge-tree clean (17 behind). 0 unresolved review threads; Bugbot no P0/P1. After: merged origin/main; PR body updated with complete Clinical Governance Preflight (7/7 checked).", "checks": "Local pr-policy evaluate ok; Vitest process-failure 2/2; no provider checks." }, { @@ -16337,7 +16379,7 @@ "ref": "PR #1287 / `claude/site-audit-quick-wins-21v9gb`", "head": "b90d659be12efedd339297daa2d289c2bd7ebb03", "scope": "Sync main + Format check on outstanding-issues", - "outcome": "FIXED. Cause of GitHub CONFLICTING/DIRTY: branch 1 behind main (`11a4ed74` numeric claim truncation); `git merge-tree` CLEAN \u2014 ledger union auto-merge. Cause of Static PR red: Prettier on `docs/outstanding-issues.md` after queue closeout rewrite. Merged main; reformatted file; `#012` remains Resolved and out of the recommended queue.", + "outcome": "FIXED. Cause of GitHub CONFLICTING/DIRTY: branch 1 behind main (`11a4ed74` numeric claim truncation); `git merge-tree` CLEAN — ledger union auto-merge. Cause of Static PR red: Prettier on `docs/outstanding-issues.md` after queue closeout rewrite. Merged main; reformatted file; `#012` remains Resolved and out of the recommended queue.", "checks": "merge-tree CLEAN; `prettier --check` PASS; `check:branch-review-ledger` PASS; no provider-backed checks." }, { @@ -16361,7 +16403,7 @@ "ref": "PR #1289 / `codex/rag-reliability-final`", "head": "d49af8acb42ccedbfe6c8b3f03d30769ba906ec7", "scope": "Bugbot review (exact head)", - "outcome": "APPROVE. No high-confidence P0\u2013P2. Application `src/`/`supabase/`/`tests/`/`scripts/` trees are unchanged vs prior APPROVE tip `a1ca6a01`; tip delta is docs evidence + clean merge from `main`. No unresolved `cursor[bot]` Bugbot threads. Residual risk: unapplied BMJ attestation migration (`#022`) correctly fails closed with `503 source_review_v2_unavailable` until qualified hosted apply.", + "outcome": "APPROVE. No high-confidence P0–P2. Application `src/`/`supabase/`/`tests/`/`scripts/` trees are unchanged vs prior APPROVE tip `a1ca6a01`; tip delta is docs evidence + clean merge from `main`. No unresolved `cursor[bot]` Bugbot threads. Residual risk: unapplied BMJ attestation migration (`#022`) correctly fails closed with `503 source_review_v2_unavailable` until qualified hosted apply.", "checks": "Focused high-risk Vitest 358 + 1502 passed; merge-tree CLEAN vs `origin/main`; no provider-backed checks; no PR comment mutations." }, { @@ -16441,7 +16483,7 @@ "ref": "PR #1294 / `execute-typography-fixes-clean-2`", "head": "41da30ed82eb1cb6685883b6afbaa1e3198ee37d", "scope": "CI green closeout", - "outcome": "APPROVE. Hosted required aggregate green after diagnosis-detail S: clone locator scope + Prettier + main sync (#1275). Bugbot: 0 unresolved cursor[bot] threads; no P0/P1 on unique product delta (mockup h3\u2192h2 + test locator). Mergeable; 0 behind main.", + "outcome": "APPROVE. Hosted required aggregate green after diagnosis-detail S: clone locator scope + Prettier + main sync (#1275). Bugbot: 0 unresolved cursor[bot] threads; no P0/P1 on unique product delta (mockup h3→h2 + test locator). Mergeable; 0 behind main.", "checks": "Hosted Static PR / Unit / Build / Safety / Advisory UI / Production UI / PR required PASS; focused Chromium diagnosis-detail PASS 1/1 earlier; no provider-backed checks." }, { @@ -16481,7 +16523,7 @@ "ref": "PR #1294 / `execute-typography-fixes-clean-2`", "head": "9ac401fd3f9997c1a18c83dc2e5190ff02fcad63", "scope": "CI babysit re-request", - "outcome": "FIXED drift. Hosted required checks already green on prior tip `10157dec`; GitHub DIRTY was staleness (merge-tree CLEAN, 31 behind). Merged origin/main cleanly; unique delta unchanged (mockup h3\u2192h2 + diagnosis-detail S: clone locator). Bugbot: 0 unresolved cursor[bot] threads; no P0/P1.", + "outcome": "FIXED drift. Hosted required checks already green on prior tip `10157dec`; GitHub DIRTY was staleness (merge-tree CLEAN, 31 behind). Merged origin/main cleanly; unique delta unchanged (mockup h3→h2 + diagnosis-detail S: clone locator). Bugbot: 0 unresolved cursor[bot] threads; no P0/P1.", "checks": "Prior hosted Production UI/PR required PASS on `10157dec`; merge-tree CLEAN; prettier check PASS; no provider-backed checks." }, { @@ -16497,7 +16539,7 @@ "ref": "PR #1294 / `execute-typography-fixes-clean-2`", "head": "da6cc04bc3a3823db4d2f14581ceec15f7757b80", "scope": "Codex P2 heading hierarchy", - "outcome": "FIXED. Reverted mockup popup/sheet titles h2\u2192h3 under Section h2 (hierarchy regression; same finding as PR #1200). Added answer-evidence-popups-heading-contract. Retained CI fixes: diagnosis-detail S: locator + Build RAM-guard CI warn.", + "outcome": "FIXED. Reverted mockup popup/sheet titles h2→h3 under Section h2 (hierarchy regression; same finding as PR #1200). Added answer-evidence-popups-heading-contract. Retained CI fixes: diagnosis-detail S: locator + Build RAM-guard CI warn.", "checks": "Vitest heading+guard contracts 3/3; no provider-backed checks." }, { @@ -16593,7 +16635,7 @@ "ref": "PR #1296 / `css-layout-audit-complete`", "head": "84d846d8d0d168ca2babcc6d699e0a88bb0379c0", "scope": "Inspect closeout: sync main + forced-colors scope", - "outcome": "FIXED. GitHub CONFLICTING was unpushed main sync (local merge-tree CLEAN, 3 behind on remote tip). Pushed merge. Bugbot P2: removed broad forced-colors `!important` wipe on `.edge-glass-header`/`[aria-selected=true]`/`.surface-raised` (token remap retained; header Canvas fill already earlier). Mockup board `z-[2147483647]` \u2192 ladder `z-[100]`. Prior CodeRabbit/Codex threads remain resolved.", + "outcome": "FIXED. GitHub CONFLICTING was unpushed main sync (local merge-tree CLEAN, 3 behind on remote tip). Pushed merge. Bugbot P2: removed broad forced-colors `!important` wipe on `.edge-glass-header`/`[aria-selected=true]`/`.surface-raised` (token remap retained; header Canvas fill already earlier). Mockup board `z-[2147483647]` → ladder `z-[100]`. Prior CodeRabbit/Codex threads remain resolved.", "checks": "lint/typecheck/format:check PASS; vitest 4197; local build PASS; no provider checks." }, { @@ -16601,7 +16643,7 @@ "ref": "PR #1296 / `css-layout-audit-complete`", "head": "957a79e4", "scope": "Re-inspect: main sync + Bugbot", - "outcome": "FIXED CONFLICTING/DIRTY: 1 commit behind main (#1294 typography) \u2014 ledger/tests auto-merged clean. Prior CodeRabbit/Codex threads remain resolved. Local Bugbot: no P0/P1. Residual only intentional z-token demotions for mockup/popover.", + "outcome": "FIXED CONFLICTING/DIRTY: 1 commit behind main (#1294 typography) — ledger/tests auto-merged clean. Prior CodeRabbit/Codex threads remain resolved. Local Bugbot: no P0/P1. Residual only intentional z-token demotions for mockup/popover.", "checks": "lint+typecheck PASS; focused vitest 19/19; awaiting exact-head hosted CI; no provider checks." }, { @@ -16857,7 +16899,7 @@ "ref": "PR #1305 / `execute-audit-remediation-fixes`", "head": "6c089f2fa5ce5a0e6057dc99ff0199fce136d105", "scope": "CI/conflict babysit + Bugbot + PR policy body", - "outcome": "FIXED. Merged origin/main (was CONFLICTING); restored fail-closed clinical-notes `answer:\"\"` wipe; fixed upload merge hazard (undefined canonicalAuthority \u2192 500); restored phone chrome viewport breakpoints; kept ClinicalDashboard under 4140-line budget via settingsState handle + memoized provider; updated account-access source contract; completed Clinical Governance Preflight in PR body. Zero unresolved review threads; zero cursor[bot] Bugbot findings.", + "outcome": "FIXED. Merged origin/main (was CONFLICTING); restored fail-closed clinical-notes `answer:\"\"` wipe; fixed upload merge hazard (undefined canonicalAuthority → 500); restored phone chrome viewport breakpoints; kept ClinicalDashboard under 4140-line budget via settingsState handle + memoized provider; updated account-access source contract; completed Clinical Governance Preflight in PR body. Zero unresolved review threads; zero cursor[bot] Bugbot findings.", "checks": "`npm run verify:cheap` PASS (4115 tests); local pr-policy evaluate ok; no provider-backed checks." }, { @@ -16873,7 +16915,7 @@ "ref": "PR #1305 / `execute-audit-remediation-fixes`", "head": "b488485d075912bc54d514ea65a1cf73c3d9b413", "scope": "PR policy body sync closeout", - "outcome": "SUPERSEDES prior #1305 babysit tip. Synced complete Summary/Verification/Risk/governance via temporary `PR_POLICY_BODY.md` (gh/API cannot edit PR body \u2014 403), then deleted template. PR policy PASS; mergeable CLEAN.", + "outcome": "SUPERSEDES prior #1305 babysit tip. Synced complete Summary/Verification/Risk/governance via temporary `PR_POLICY_BODY.md` (gh/API cannot edit PR body — 403), then deleted template. PR policy PASS; mergeable CLEAN.", "checks": "Sync PR policy body SUCCESS; PR policy PASS; `verify:cheap` prior tip green." }, { @@ -16913,7 +16955,7 @@ "ref": "PR #1307 / `claude/rag-019-fallback-guard`", "head": "0827d65d12f5c25faffdf4ebca036f00fc2512cd", "scope": "CI babysit + Bugbot", - "outcome": "FIXED. Build failed because `guard-next-build.mjs` hard-failed when GitHub runners reported 7.8 GiB RAM (<10 GiB); prior tip Build succeeded on a larger runner (flake). Softened to warn-and-continue under CI/GITHUB_ACTIONS; local/Docker still hard-fail. PR policy FAIL: missing `## Clinical Governance Preflight` \u2014 body updated. Bugbot: zero cursor[bot] findings; reviewThreads=0 (nothing to resolve). merge-tree clean vs origin/main.", + "outcome": "FIXED. Build failed because `guard-next-build.mjs` hard-failed when GitHub runners reported 7.8 GiB RAM (<10 GiB); prior tip Build succeeded on a larger runner (flake). Softened to warn-and-continue under CI/GITHUB_ACTIONS; local/Docker still hard-fail. PR policy FAIL: missing `## Clinical Governance Preflight` — body updated. Bugbot: zero cursor[bot] findings; reviewThreads=0 (nothing to resolve). merge-tree clean vs origin/main.", "checks": "Unit: guard-next-build + #019 fallback + extractive-answer-formatting 137/137; prettier/eslint clean on touched files; pr-policy evaluate ok; no provider checks." }, { @@ -16929,7 +16971,7 @@ "ref": "PR #1309 / `claude/gates-skill`", "head": "7dfe103bfa408052c9e899211b8373c7ccb708d3", "scope": "Conflict sync + Codex/CodeRabbit + Bugbot", - "outcome": "FIXED. GitHub CONFLICTING/DIRTY was main-staleness only (`merge-tree` clean); merged `origin/main`. Codex P2: skill wrongly claimed `verify:ui` exits 0 under heavy-lock contention \u2014 corrected to 15m queue then exit 1 via `run-playwright.mjs`; mirrored in AGENTS.md. CodeRabbit: marked `${PIPESTATUS[0]}` as Bash-specific. Bugbot: zero `cursor[bot]` findings; confirmed same P2. No CI failures on prior tip.", + "outcome": "FIXED. GitHub CONFLICTING/DIRTY was main-staleness only (`merge-tree` clean); merged `origin/main`. Codex P2: skill wrongly claimed `verify:ui` exits 0 under heavy-lock contention — corrected to 15m queue then exit 1 via `run-playwright.mjs`; mirrored in AGENTS.md. CodeRabbit: marked `${PIPESTATUS[0]}` as Bash-specific. Bugbot: zero `cursor[bot]` findings; confirmed same P2. No CI failures on prior tip.", "checks": "`prettier --check` PASS; `docs:check-links` 1287 PASS; no provider-backed checks." }, { @@ -16945,7 +16987,7 @@ "ref": "PR #1310 / claude/branch-review-ledger-fixes-42575f", "head": "7c870c139211a419fe8b4dfacae3195a7a7caa2b", "scope": "PR babysit: CI + Codex P2s + Bugbot-equivalent", - "outcome": "Hosted PR required SUCCESS on 7c870c13. Fixed 3 Codex P2s (exact scope match, supersede mints distinct scope, verify full SHAs via git rev-parse) plus n/a-embedded hex and parenthetical ref-token false matches. 3 review threads replied+resolved. Mergeable; 0 behind main. Hosted Cursor Bugbot check not produced \u2014 bot-authored bugbot run/cursor review comments ignored; local Bugbot-style review done and defects fixed.", + "outcome": "Hosted PR required SUCCESS on 7c870c13. Fixed 3 Codex P2s (exact scope match, supersede mints distinct scope, verify full SHAs via git rev-parse) plus n/a-embedded hex and parenthetical ref-token false matches. 3 review threads replied+resolved. Mergeable; 0 behind main. Hosted Cursor Bugbot check not produced — bot-authored bugbot run/cursor review comments ignored; local Bugbot-style review done and defects fixed.", "checks": "check:branch-review-ledger PASS; vitest repo-hygiene 25/25; lint; typecheck; full vitest 4133 pass; hosted Static/Unit/Build/Safety/PR-required SUCCESS. No provider-backed gates." }, { @@ -16985,7 +17027,7 @@ "ref": "PR #1335 / cursor/pr-policy-caveman-docs-dc4e (merged)", "head": "fd5651c821426605df0cb9df44236d6c67e65f41", "scope": "open-pr-merge-sweep", - "outcome": "MERGED ledger fold. Product AGENTS/handoff already on main via #1322 (two-dot empty). Fixed Codex P2: pr-* ledger refs \u2192 resolvable branch names; resolved blocking thread (reply 403).", + "outcome": "MERGED ledger fold. Product AGENTS/handoff already on main via #1322 (two-dot empty). Fixed Codex P2: pr-* ledger refs → resolvable branch names; resolved blocking thread (reply 403).", "checks": "hosted-pr-required,static,circleci,resolveReviewThread" }, { @@ -17041,7 +17083,7 @@ "ref": "PR #1352 / execute-audit-remediation-fixes", "head": "dcdcb5b2b0546eddbb5bfd6efdb68122be2eabaa", "scope": "open-pr-merge-sweep", - "outcome": "SKIP-CLOSE confirmed: stale continuation of merged #1305; REAL merge-tree conflicts across answer route, ClinicalDashboard, OverlayProvider, z-index ladder, private-access tests, etc. Close attempted \u2192 403.", + "outcome": "SKIP-CLOSE confirmed: stale continuation of merged #1305; REAL merge-tree conflicts across answer route, ClinicalDashboard, OverlayProvider, z-index ladder, private-access tests, etc. Close attempted → 403.", "checks": "merge-tree-conflicts,gh-pr-1305-MERGED" }, { @@ -17065,7 +17107,7 @@ "ref": "PR #1371 / cursor/document-viewer-ci-guards-eac3 (merged)", "head": "64be97b96b46617e63f7d004fef4f9bcb14bf710", "scope": "open-pr-merge-sweep", - "outcome": "MERGED. Useful Production UI drift guards (document-overview id ownership + phone section sheet selectors). Draft\u2192ready; sync main; squash+delete-branch.", + "outcome": "MERGED. Useful Production UI drift guards (document-overview id ownership + phone section sheet selectors). Draft→ready; sync main; squash+delete-branch.", "checks": "hosted-pr-required,static,unit,circleci,merge-tree-clean" }, { @@ -17113,7 +17155,7 @@ "ref": "`claude/clinical-kb-pwa-review-asi3wb` (PR #1050: eval cost readout fix + issues-ledger capture)", "head": "eb1046be132d8e94d9d6b4905d7e240a99f33187", "scope": "Retrospective disposition row for PR #1050 (omitted at merge time; ride-along from the 2026-07-26 scheduled-runs reader)", - "outcome": "MERGED 2026-07-22 as squash `9fb9bc7`. External reviews dispositioned pre-merge: one Codex P2 and one CodeRabbit Major converged on the same defect (zero-usage cases with a provider attempt must stay `n/a`, not `$0`) plus two CodeRabbit ledger Minors and a real merge conflict against #1049's concurrent ID allocation \u2014 all resolved in `eb1046b` (provider-attempt cost branch; issue rows renumbered #018-#023, next-id 024), threads resolved and confirmed by the reviewer. Cost readout subsequently validated live twice: merged-main canary `30018289898` (2026-07-23) and scheduled run `30216191889` (2026-07-26, Estimated cost USD 0.235936; 9 priced + 35 provably-zero-cost cases, no `n/a`), archiving issue #020.", + "outcome": "MERGED 2026-07-22 as squash `9fb9bc7`. External reviews dispositioned pre-merge: one Codex P2 and one CodeRabbit Major converged on the same defect (zero-usage cases with a provider attempt must stay `n/a`, not `$0`) plus two CodeRabbit ledger Minors and a real merge conflict against #1049's concurrent ID allocation — all resolved in `eb1046b` (provider-attempt cost branch; issue rows renumbered #018-#023, next-id 024), threads resolved and confirmed by the reviewer. Cost readout subsequently validated live twice: merged-main canary `30018289898` (2026-07-23) and scheduled run `30216191889` (2026-07-26, Estimated cost USD 0.235936; 9 priced + 35 provably-zero-cost cases, no `n/a`), archiving issue #020.", "checks": "PR CI green at merge (squash auto-merge armed by the user); post-merge validation read-only from hosted run logs; tests 28/28 on `tests/eval-quality.test.ts` plus typecheck and prettier at `eb1046b`; no provider dispatch or live RAG spend for this row." }, { @@ -17257,7 +17299,7 @@ "ref": "open-PR recommendation implementation (Cursor)", "head": "multi-head", "scope": "Implement review recommendations safely", - "outcome": "CLOSED #1261/#1262/#1263 without merge (unsafe audit lineage). Pushed fixes: #1273 type-scale + phone-frame scroll + PriorityDock selection; #1275 prefetch source-contract tighten; #1280 rail MutationObserver + main sync; #1281 StepBuilderCard completeness + clipboard draft test (automerge temporarily disabled to land polish). Opened #PDF-137 salvage branch for exit-code 137. Dependabot #1267-1269 left HOLD \u2014 workflow approve/update-branch 403 for this integration token; no merge to main.", + "outcome": "CLOSED #1261/#1262/#1263 without merge (unsafe audit lineage). Pushed fixes: #1273 type-scale + phone-frame scroll + PriorityDock selection; #1275 prefetch source-contract tighten; #1280 rail MutationObserver + main sync; #1281 StepBuilderCard completeness + clipboard draft test (automerge temporarily disabled to land polish). Opened #PDF-137 salvage branch for exit-code 137. Dependabot #1267-1269 left HOLD — workflow approve/update-branch 403 for this integration token; no merge to main.", "checks": "type-scale strict PASS; focused Vitest safety-plan 3/3 and prefetch contract 1/1 and band 9/9; PDF extractor pymupdf tests skipped in this VM; no provider-backed checks; no main merges." }, { @@ -17265,7 +17307,7 @@ "ref": "open-PR review + Bugbot sweep (Cursor)", "head": "multi-head", "scope": "Fresh review of all open PRs + pr-bugbot on each head", - "outcome": "Reviewed 10 open PRs after #1277 merged. No hosted `cursor[bot]` Bugbot comments existed on any PR; ran repo `pr-bugbot` triage per head instead. Cluster: close #1261/#1263 (unsafe audit lineage); salvage/rebuild only thin #1262 bits; hold Dependabot #1267\u2192#1268\u2192#1269 pending workflow approval; fix #1273 type-scale + mockup UX before design trust; sync #1275 and restore ledger from main; #1280 blocked by unrelated Loading-answer strict-mode flake; #1281 sound clinical follow-up with two P2 polish items.", + "outcome": "Reviewed 10 open PRs after #1277 merged. No hosted `cursor[bot]` Bugbot comments existed on any PR; ran repo `pr-bugbot` triage per head instead. Cluster: close #1261/#1263 (unsafe audit lineage); salvage/rebuild only thin #1262 bits; hold Dependabot #1267→#1268→#1269 pending workflow approval; fix #1273 type-scale + mockup UX before design trust; sync #1275 and restore ledger from main; #1280 blocked by unrelated Loading-answer strict-mode flake; #1281 sound clinical follow-up with two P2 polish items.", "checks": "merge-tree classification; gh PR/CI/thread inventory; pr-bugbot review-only agents; no provider-backed checks; no PR mutations." }, { @@ -17305,7 +17347,7 @@ "ref": "PR #1267 / `dependabot/github_actions/...`", "head": "fdc6bdf5e235", "scope": "Bugbot review", - "outcome": "HOLD then MERGE after workflow approval. Pin `anthropics/claude-code-action` b76a077\u2192be7b93b (v1.0.183) SHA matches annotated tag. merge-tree CLEAN; required CI awaiting Dependabot approval.", + "outcome": "HOLD then MERGE after workflow approval. Pin `anthropics/claude-code-action` b76a077→be7b93b (v1.0.183) SHA matches annotated tag. merge-tree CLEAN; required CI awaiting Dependabot approval.", "checks": "pin/tag verify; merge-tree; no provider checks." }, { @@ -17321,7 +17363,7 @@ "ref": "PR #1269 / `dependabot/npm-development/...`", "head": "c9114439e6e6", "scope": "Bugbot review", - "outcome": "HOLD; rebase after #1268. Playwright 1.61.1\u21921.62.0 is residual flake risk; prettier/eslint-config-next/@next/bundle-analyzer patches otherwise low risk.", + "outcome": "HOLD; rebase after #1268. Playwright 1.61.1→1.62.0 is residual flake risk; prettier/eslint-config-next/@next/bundle-analyzer patches otherwise low risk.", "checks": "package.json/lock diff; merge-tree CLEAN; no provider checks." }, { @@ -17473,7 +17515,7 @@ "ref": "PR #1280 / `claude/top-search-design-mockups-w53znc`", "head": "93a9f90ff287", "scope": "Bugbot + CI debug", - "outcome": "NOT READY until Production UI green. Product band rebuild looks sound; Advisory UI green. Hosted failure is Answer Suspense `Loading answer` strict-mode (2 nodes / one hidden) in ui-smoke \u2014 not caused by band diff. Optional P2: `useRailOverflow` can miss child-list changes.", + "outcome": "NOT READY until Production UI green. Product band rebuild looks sound; Advisory UI green. Hosted failure is Answer Suspense `Loading answer` strict-mode (2 nodes / one hidden) in ui-smoke — not caused by band diff. Optional P2: `useRailOverflow` can miss child-list changes.", "checks": "Production UI log job 90037898852; unique diff vs main; focused band unit 9/9 on tip; no provider checks." }, { @@ -17497,7 +17539,7 @@ "ref": "PR #1280 / `claude/top-search-design-mockups-w53znc`", "head": "c844560da909b7f88a1ef351fc833ad45cfb0a81 vs origin/main 7740535a", "scope": "Thorough merge-readiness review vs main", - "outcome": "APPROVE AFTER MAIN SYNC. No P0/P1. Presentation-only shared results band rebuild; clean merge-tree; hosted PR required + Production UI green on tip; 0 unresolved threads. Branch is 1 commit behind unrelated safety-plan #1281 \u2014 final-merge audit fails closed until tip contains origin/main. Residual P2 (non-blocking): phone overflowing-rail `mask-image` lacks forced-colors clear (pattern exists for edge-glass); ResizeObserver does not unobserve removed children.", + "outcome": "APPROVE AFTER MAIN SYNC. No P0/P1. Presentation-only shared results band rebuild; clean merge-tree; hosted PR required + Production UI green on tip; 0 unresolved threads. Branch is 1 commit behind unrelated safety-plan #1281 — final-merge audit fails closed until tip contains origin/main. Residual P2 (non-blocking): phone overflowing-rail `mask-image` lacks forced-colors clear (pattern exists for edge-glass); ResizeObserver does not unobserve removed children.", "checks": "Diff review of 6 unique files; `git merge-tree` clean; `audit:final-merge --dry-run` fails only on missing main ancestor; band DOM 9/9; hosted checks green on tip; no provider-backed app checks." }, { @@ -17537,7 +17579,7 @@ "ref": "PR #1285 / `cursor/pdf-extractor-sigkill-137-0687`", "head": "pending-push", "scope": "CI babysit + Bugbot + main sync", - "outcome": "Before: required CI SUCCESS on tip `630792c9`; mergeable but BEHIND main; 0 unresolved review threads; no `cursor[bot]` Bugbot comments. After: merged `origin/main` cleanly; pr-bugbot found no P0/P1 \u2014 fixed P2 by moving SIGKILL/exit-137 regressions out of `describe.runIf(hasPyMuPDF)` and asserting `PdfExtractorProcessError` by name so the OOM path cannot silently skip or pass via JS fallback.", + "outcome": "Before: required CI SUCCESS on tip `630792c9`; mergeable but BEHIND main; 0 unresolved review threads; no `cursor[bot]` Bugbot comments. After: merged `origin/main` cleanly; pr-bugbot found no P0/P1 — fixed P2 by moving SIGKILL/exit-137 regressions out of `describe.runIf(hasPyMuPDF)` and asserting `PdfExtractorProcessError` by name so the OOM path cannot silently skip or pass via JS fallback.", "checks": "Focused Vitest `tests/pdf-extractor.test.ts` 2 passed / 4 skipped (PyMuPDF absent locally); merge-tree clean; no provider-backed checks." }, { @@ -17584,8 +17626,8 @@ "date": "2026-07-27", "ref": "PR #1287 / `claude/site-audit-quick-wins-21v9gb`", "head": "18fcfae24b41cdd5caebd2780afa963a2a1335a5", - "scope": "Follow-up \u2014 Bugbot/CodeRabbit residuals addressed (supersedes the 97ab067 Bugbot row)", - "outcome": "Residual P2 closed: import-graph lock added \u2014 an allowlist test asserts `cross-mode-differentials.ts` may import ONLY the precomputed index + the (type-only) catalog type, catching direct, transitive-via-new-import, and dynamic `import()`/`require` reintroductions of `@/lib/differentials`. P3s closed: stale `cross-mode-links.tsx` comment fixed; `build-cross-mode-differentials-index.mjs` listed in `scripts-index.md`. CodeRabbit's two Minor nits (guard depth + this ledger refresh) addressed.", + "scope": "Follow-up — Bugbot/CodeRabbit residuals addressed (supersedes the 97ab067 Bugbot row)", + "outcome": "Residual P2 closed: import-graph lock added — an allowlist test asserts `cross-mode-differentials.ts` may import ONLY the precomputed index + the (type-only) catalog type, catching direct, transitive-via-new-import, and dynamic `import()`/`require` reintroductions of `@/lib/differentials`. P3s closed: stale `cross-mode-links.tsx` comment fixed; `build-cross-mode-differentials-index.mjs` listed in `scripts-index.md`. CodeRabbit's two Minor nits (guard depth + this ledger refresh) addressed.", "checks": "vitest `cross-mode-differentials-index` 3/3; typecheck + lint PASS; `docs:check-scripts` + `docs:check-links` PASS; `check:cross-mode-index` PASS; no provider-backed checks." }, { @@ -17593,7 +17635,7 @@ "ref": "PR #1287 / `claude/site-audit-quick-wins-21v9gb`", "head": "5c2816d1dc2e7a99c37d27310b487bcac5232db3", "scope": "Production UI CI fix: differentials-home hydration strict-mode", - "outcome": "FIXED. Hosted Production UI failed solely on `dashboard differentials mode param redirects\u2026`: `getByTestId(differentials-home)` hit 2 nodes (server+client overlap). Applied `expectSingleSettledOwner` before the visibility assert. No product change.", + "outcome": "FIXED. Hosted Production UI failed solely on `dashboard differentials mode param redirects…`: `getByTestId(differentials-home)` hit 2 nodes (server+client overlap). Applied `expectSingleSettledOwner` before the visibility assert. No product change.", "checks": "Focused production Playwright journey PASS 1/1 via `npm run test:e2e` (system Chrome); no provider-backed checks." }, { @@ -17617,7 +17659,7 @@ "ref": "PR #1287 / `claude/site-audit-quick-wins-21v9gb`", "head": "88d8638974075fa91334c2bb4a0e6b54fda00176", "scope": "Review closeout: main sync + resolved-graph guard + ledger attribution", - "outcome": "FIXED. Cause of GitHub CONFLICTING/DIRTY: both tips appended `docs/branch-review-ledger.md` (union); `git merge-tree` was clean \u2014 merged `origin/main` (#1284 ledger rows). CodeRabbit recursive import-graph ask: walk resolved runtime imports from `cross-mode-differentials.ts` (services/forms boundary pattern) + keep entry allowlist. Supersedes residual wording on rows 1148/1149: import-graph lock + scripts-index + comment already landed; `client-performance-boundaries` guards the consumer dynamic import, `cross-mode-differentials-index` guards the catalog module/graph. Hosted Production UI already green after hydration settle.", + "outcome": "FIXED. Cause of GitHub CONFLICTING/DIRTY: both tips appended `docs/branch-review-ledger.md` (union); `git merge-tree` was clean — merged `origin/main` (#1284 ledger rows). CodeRabbit recursive import-graph ask: walk resolved runtime imports from `cross-mode-differentials.ts` (services/forms boundary pattern) + keep entry allowlist. Supersedes residual wording on rows 1148/1149: import-graph lock + scripts-index + comment already landed; `client-performance-boundaries` guards the consumer dynamic import, `cross-mode-differentials-index` guards the catalog module/graph. Hosted Production UI already green after hydration settle.", "checks": "Focused vitest index+boundaries 10/10; `check:cross-mode-index` PASS; merge-tree CLEAN vs origin/main; prior Production UI PASS on `f738f083`; no provider-backed checks." }, { @@ -17625,7 +17667,7 @@ "ref": "PR #1287 / `claude/site-audit-quick-wins-21v9gb`", "head": "97ab067bfdca644e0750bfbc717da7d58ecd27ee", "scope": "Bugbot defect hunt (cursoragent request; no hosted cursor[bot] threads)", - "outcome": "APPROVE pending exact-head required CI. No P0/P1. Projection \u2261 live helpers (201 diagnoses / 31 presentations / 20 alias keys); `--check` compares parsed values (Prettier-safe); CI `static-pr` + `verify:cheap` wire `check:cross-mode-index`. Residual P2: re-importing `@/lib/differentials` into `cross-mode-differentials.ts` would restore the ~1.2 MB lazy-chunk weight while data gates stay green \u2014 no import-graph lock yet. P3: stale comment in `cross-mode-links.tsx`; scripts-index omits new generator.", + "outcome": "APPROVE pending exact-head required CI. No P0/P1. Projection ≡ live helpers (201 diagnoses / 31 presentations / 20 alias keys); `--check` compares parsed values (Prettier-safe); CI `static-pr` + `verify:cheap` wire `check:cross-mode-index`. Residual P2: re-importing `@/lib/differentials` into `cross-mode-differentials.ts` would restore the ~1.2 MB lazy-chunk weight while data gates stay green — no import-graph lock yet. P3: stale comment in `cross-mode-links.tsx`; scripts-index omits new generator.", "checks": "`check:cross-mode-index` PASS; vitest `cross-mode-differentials-index` 2/2; gate-manifest PASS; drift/invalid-JSON proofs FAIL closed; import-graph grep clean today; no provider-backed checks." }, { @@ -17737,7 +17779,7 @@ "ref": "PR #1192 / `cursor/fix-mobile-composer-edge-scroll-5b1d`", "head": "head 2597dd305fd61e4e16166cccd109ff6f8eae0a33 / squash c4d5f47a39", "scope": "prlanded after squash merge", - "outcome": "LANDED. Phone Answer edge-dock hide/reveal, layout-clamp versus upward-intent detection, and composer focus binding, reconciled against the #1222 cross-breakpoint header. `git diff c4d5f47a 2597dd30` empty, so the content landed intact; remote branch deleted at merge; required contexts Gitleaks, PR required and PR policy all SUCCESS on the merged head. Two things worth keeping: merging `main` made the ledger's `union` driver re-append records both sides already carried, failing `check:branch-review-ledger` twice in one hour (see #082), and the final head was a `coderabbitai[bot]` auto-fix swapping an inline two-step upward scroll for the shared `scrollPrimarySurface` helper in `tests/ui-smoke.spec.ts` \u2014 an identical earlier auto-fix had been reverted on this branch, so it was re-proven rather than trusted.", + "outcome": "LANDED. Phone Answer edge-dock hide/reveal, layout-clamp versus upward-intent detection, and composer focus binding, reconciled against the #1222 cross-breakpoint header. `git diff c4d5f47a 2597dd30` empty, so the content landed intact; remote branch deleted at merge; required contexts Gitleaks, PR required and PR policy all SUCCESS on the merged head. Two things worth keeping: merging `main` made the ledger's `union` driver re-append records both sides already carried, failing `check:branch-review-ledger` twice in one hour (see #082), and the final head was a `coderabbitai[bot]` auto-fix swapping an inline two-step upward scroll for the shared `scrollPrimarySurface` helper in `tests/ui-smoke.spec.ts` — an identical earlier auto-fix had been reverted on this branch, so it was re-proven rather than trusted.", "checks": "`npm run verify:ui` 285/285 Chromium on the production build; `npm run verify:cheap` pass except the pre-existing `tests/pdf-extractor.test.ts` Python-OCR case, whose subject is absent from the diff (3437/3439 otherwise); `ui-chrome-scroll` + `ui-phone-scroll` 30/30 across phone, tablet and desktop; `use-hide-on-scroll` + `header-scroll-hide-contract` + `mobile-composer-reserve` 39/39; the CodeRabbit-modified in-flow collapse test re-run 3/3. No provider-backed checks." }, { @@ -17809,7 +17851,7 @@ "ref": "PR #1241 / `cursor/imp04-prune-dead-exports-01f2`", "head": "2c6d9c96 merge of origin/main 5475fcfb", "scope": "Main sync after GitHub CONFLICTING", - "outcome": "SIMPLE. `git merge-tree --write-tree` clean before merge; GitHub DIRTY was staleness behind #1227/#1245/#1200. Ledger union auto-merge. Calculator path rename `calculator-mockups`\u2192`calculators` detected; IMP-04 dead-export prune content carried onto new paths (`calculatorById`/`useCalculatorState` still absent). No conflicting intents; no conflict markers.", + "outcome": "SIMPLE. `git merge-tree --write-tree` clean before merge; GitHub DIRTY was staleness behind #1227/#1245/#1200. Ledger union auto-merge. Calculator path rename `calculator-mockups`→`calculators` detected; IMP-04 dead-export prune content carried onto new paths (`calculatorById`/`useCalculatorState` still absent). No conflicting intents; no conflict markers.", "checks": "merge-tree clean; merge ort; `check:branch-review-ledger`; `tsc --noEmit` clean; no stale calculator-mockups imports. No provider calls." }, { @@ -17833,7 +17875,7 @@ "ref": "PR #1241 / `cursor/imp04-prune-dead-exports-01f2`", "head": "ac056083bad351659cc970171c8cd62bbb3526a5", "scope": "Codex P2: sync recipe catalogs after prune", - "outcome": "FIXED. Updated `.design-sync/conventions.md` + `docs/redesign/09-ui-primitives-recipes.md` (plus badge/design-system mentions) so catalogs no longer advertise deleted or module-private recipes (`insetCard`, `iconTile`, `compactMetadataRow`, `commandInput`, `toneWarningQuiet`, \u2026).", + "outcome": "FIXED. Updated `.design-sync/conventions.md` + `docs/redesign/09-ui-primitives-recipes.md` (plus badge/design-system mentions) so catalogs no longer advertise deleted or module-private recipes (`insetCard`, `iconTile`, `compactMetadataRow`, `commandInput`, `toneWarningQuiet`, …).", "checks": "Doc grep of catalogs vs `ui-primitives` export surface; `check:branch-review-ledger`. No provider calls." }, { @@ -17929,7 +17971,7 @@ "ref": "PR #1253 / `remediate-system-audit-findings`", "head": "cc1fa9d48434c809e2cf73dfeb3124d2b36f0968", "scope": "Authorized babysit peek", - "outcome": "CLOSED before sweep actions. CONFLICTING vs main with clinical/answer/privacy paths; non-trivial \u2014 no merge attempted. Policy failure was missing Clinical Governance Preflight (body not agent-managed).", + "outcome": "CLOSED before sweep actions. CONFLICTING vs main with clinical/answer/privacy paths; non-trivial — no merge attempted. Policy failure was missing Clinical Governance Preflight (body not agent-managed).", "checks": "merge-tree conflict inventory only; no provider-backed checks." }, { @@ -18001,7 +18043,7 @@ "ref": "PR #1255 / `execute-audit-remediation-plan`", "head": "cc645928cefb18e4c08870ddc1c483bc051a92b9", "scope": "Authorized babysit peek", - "outcome": "CLOSED before sweep actions. CONFLICTING vs main including `api/answer`, ClinicalDashboard, privacy routes; non-trivial \u2014 no merge attempted. Policy failure was missing Clinical Governance Preflight.", + "outcome": "CLOSED before sweep actions. CONFLICTING vs main including `api/answer`, ClinicalDashboard, privacy routes; non-trivial — no merge attempted. Policy failure was missing Clinical Governance Preflight.", "checks": "merge-tree conflict inventory only; no provider-backed checks." }, { @@ -18121,15 +18163,15 @@ "ref": "`cursor/fix-mobile-composer-edge-scroll-5b1d` (PR #1192)", "head": "333e67b8", "scope": "pr-ci-fix: Static PR checks / Maintainability hotspot budgets", - "outcome": "Main merge (e688c6e2) expanded a JSX comment from 2\u21923 lines while restructuring heroComposerBreakpoint/heroOwnsPhoneComposer declarations, netting +2 lines vs budget-fix commit (ae77f8c3). ClinicalDashboard.tsx hit 4141 vs 4140 budget. Fix: compressed 3-line comment back to 2 lines. Zero behaviour change.", - "checks": "`npm run check:maintainability-budgets` \u2192 PASS (4140/4140). No provider-backed checks." + "outcome": "Main merge (e688c6e2) expanded a JSX comment from 2→3 lines while restructuring heroComposerBreakpoint/heroOwnsPhoneComposer declarations, netting +2 lines vs budget-fix commit (ae77f8c3). ClinicalDashboard.tsx hit 4141 vs 4140 budget. Fix: compressed 3-line comment back to 2 lines. Zero behaviour change.", + "checks": "`npm run check:maintainability-budgets` → PASS (4140/4140). No provider-backed checks." }, { "date": "2026-07-25", "ref": "`cursor/fix-mode-switch-lag-22f6`", "head": "0ef62ff521fb9f0457f685e9d2f50a24d640e663", "scope": "Frontend-architecture review: loading/navigation performance for modes/pages", - "outcome": "No P0. P1: (1) GlobalSearchShell statically imports ClinicalDashboard into shared (search-app) layout client graph \u2014 every namespaced mode pays dashboard module weight; (2) ClientHydrationBoundary blanks standalone mode children until hydrate \u2014 defeats RSC paint for DSM/factsheets/etc. P2: ClinicalDashboard\u2194standalone remount + grid-template-columns transition; dashboard URL sync still useEffect+rAF (shell already render-time); ToolsHub ssr:false on /?mode=tools; MutationObserver portal rebind cost on mode-home slot changes; SearchCommandProvider value tied to query in shell. P3/#007: /tools vs /?mode=tools dual entry (PT-11 vs nav). Quick wins: dynamic() ClinicalDashboard; remove/narrow ClientHydrationBoundary; point tools href to /tools. Larger: unify shells / extract shared chrome.", + "outcome": "No P0. P1: (1) GlobalSearchShell statically imports ClinicalDashboard into shared (search-app) layout client graph — every namespaced mode pays dashboard module weight; (2) ClientHydrationBoundary blanks standalone mode children until hydrate — defeats RSC paint for DSM/factsheets/etc. P2: ClinicalDashboard↔standalone remount + grid-template-columns transition; dashboard URL sync still useEffect+rAF (shell already render-time); ToolsHub ssr:false on /?mode=tools; MutationObserver portal rebind cost on mode-home slot changes; SearchCommandProvider value tied to query in shell. P3/#007: /tools vs /?mode=tools dual entry (PT-11 vs nav). Quick wins: dynamic() ClinicalDashboard; remove/narrow ClientHydrationBoundary; point tools href to /tools. Larger: unify shells / extract shared chrome.", "checks": "Static architecture review of SharedSearchAppShell/GlobalSearchShell/ClinicalDashboard/MasterSearchHeader/app-modes/search-route-ownership/mode homes/tools routes; prior mode-switch ledger rows at b9484396/775d15ad noted. No browser, verify:ui, bundle measure, or provider-backed checks." }, { @@ -18137,7 +18179,7 @@ "ref": "`cursor/fix-mode-switch-lag-22f6`", "head": "b9484396347defaaa934571604b9d165ae6d8b98", "scope": "Same-class mode-switch thrash review + fixes", - "outcome": "FIXED prior open P2s from 54d45f68 hunt: crossModeSearch now mirrors selectSearchMode (navigate-only when leaving dashboard); shared shell resets phone scrollTop + scroll-hide on pathname; hero portal keeps default composer until host attaches; ModeHomeRouteLoading uses --shell-header-h; services/forms contentAlign stays startOnPhone while loading. No P0/P1. Residual P2: ClinicalDashboard\u2194standalone shell remount + sidebar grid-template-columns transition; dashboard-internal Answer\u2194Documents still eager setSearchMode (overlay/hero flip by design, scroll now reset). Residual P3/#007: /tools vs /?mode=tools dual entry.", + "outcome": "FIXED prior open P2s from 54d45f68 hunt: crossModeSearch now mirrors selectSearchMode (navigate-only when leaving dashboard); shared shell resets phone scrollTop + scroll-hide on pathname; hero portal keeps default composer until host attaches; ModeHomeRouteLoading uses --shell-header-h; services/forms contentAlign stays startOnPhone while loading. No P0/P1. Residual P2: ClinicalDashboard↔standalone shell remount + sidebar grid-template-columns transition; dashboard-internal Answer↔Documents still eager setSearchMode (overlay/hero flip by design, scroll now reset). Residual P3/#007: /tools vs /?mode=tools dual entry.", "checks": "Focused Vitest ownership/align/hide-on-scroll/merge-artifacts/overlay 46/46; typecheck; static contracts for portal/scroll reset/crossModeSearch. No verify:ui / provider-backed checks." }, { @@ -18145,7 +18187,7 @@ "ref": "`cursor/fix-mode-switch-lag-22f6` / PR #1187", "head": "775d15adef8155aba68e43f0e9354adf60f1ea8d", "scope": "Same-class thrash fixes lint closeout", - "outcome": "Supersedes b9484396 row for lint follow-up: pathname bottomComposerHidden reset moved to render-time; removed unused desktopHomeComposerFallback. verify:cheap green. Residual unchanged (dashboard\u2194standalone remount; #007 Tools dual entry).", + "outcome": "Supersedes b9484396 row for lint follow-up: pathname bottomComposerHidden reset moved to render-time; removed unused desktopHomeComposerFallback. verify:cheap green. Residual unchanged (dashboard↔standalone remount; #007 Tools dual entry).", "checks": "verify:cheap 3345 passed / 3 skipped; focused ownership tests; eslint clean on touched shell/header. No provider checks." }, { @@ -18153,8 +18195,8 @@ "ref": "`cursor/fix-mode-switch-lag-22f6` / PR #1187", "head": "876d7ecfa1ae8ec79fc0f0bdf1198c6640ad89b8", "scope": "Parallel loading UX + frontend-architecture review + quick-win fixes", - "outcome": "No P0. Confirmed live: H1 dashboard\u2194standalone remount dominant (~0.6\u20131.2s settle); H4 hero portal rebind; H3 registry post-paint. FIXED quick wins: remove ClientHydrationBoundary blanking; ModeHomeRouteLoading startOnPhone; mode-home loading.tsx alignment/additions; forms server defaultFormSlug + client-boundary test; dynamic ClinicalDashboard; sidebar grid transition mount-gate; forms drop key=query; DocumentViewer key=id; therapy Suspense ModeHomeRouteLoading; redirect /?mode=services|forms. Residual P2: unify shells (H1), stable hero slot, registry abort+LRU/summary fields, Tools dual entry #007, prescribing full-catalogue cliff.", - "checks": "Parallel explore\u00d73 + debug measurement; focused Vitest loading/forms/ownership/align contracts; typecheck; eslint touched shell. No verify:ui / provider-backed checks." + "outcome": "No P0. Confirmed live: H1 dashboard↔standalone remount dominant (~0.6–1.2s settle); H4 hero portal rebind; H3 registry post-paint. FIXED quick wins: remove ClientHydrationBoundary blanking; ModeHomeRouteLoading startOnPhone; mode-home loading.tsx alignment/additions; forms server defaultFormSlug + client-boundary test; dynamic ClinicalDashboard; sidebar grid transition mount-gate; forms drop key=query; DocumentViewer key=id; therapy Suspense ModeHomeRouteLoading; redirect /?mode=services|forms. Residual P2: unify shells (H1), stable hero slot, registry abort+LRU/summary fields, Tools dual entry #007, prescribing full-catalogue cliff.", + "checks": "Parallel explore×3 + debug measurement; focused Vitest loading/forms/ownership/align contracts; typecheck; eslint touched shell. No verify:ui / provider-backed checks." }, { "date": "2026-07-25", @@ -18216,7 +18258,7 @@ "date": "2026-07-25", "ref": "automated-audit-remediations (PR #1158)", "head": "aa745922f00", - "scope": "Babysit sweep: automated audit remediations \u2014 squash-merged", + "scope": "Babysit sweep: automated audit remediations — squash-merged", "outcome": "pr-required", "checks": "merged" }, @@ -18232,7 +18274,7 @@ "date": "2026-07-25", "ref": "canary-comparison-preflight (PR #1180)", "head": "43f261cf229", - "scope": "Babysit sweep: canary comparison preflight docs \u2014 squash-merged", + "scope": "Babysit sweep: canary comparison preflight docs — squash-merged", "outcome": "pr-required", "checks": "merged" }, @@ -18256,7 +18298,7 @@ "date": "2026-07-25", "ref": "codex/complete-all-pending-tasks (PR #1191)", "head": "e2488dbb108", - "scope": "Babysit sweep: scoped-label pagination + order assertion for CodeRabbit thread \u2014 squash-merged", + "scope": "Babysit sweep: scoped-label pagination + order assertion for CodeRabbit thread — squash-merged", "outcome": "unit + pr-required", "checks": "merged" }, @@ -18328,7 +18370,7 @@ "date": "2026-07-25", "ref": "cursor-indexing-ignore (PR #1171)", "head": "3a4036580df", - "scope": "Babysit sweep: Cursor indexing ignore rules \u2014 squash-merged", + "scope": "Babysit sweep: Cursor indexing ignore rules — squash-merged", "outcome": "pr-required", "checks": "merged" }, @@ -18344,7 +18386,7 @@ "date": "2026-07-25", "ref": "cursor/alias-slot-disjointness-guard-6273 (PR #1215)", "head": "406cf21eb730809fb06df00b1a9299e3462c728a", - "scope": "prlanded \u2014 generalized #030 contracts + ledger #081", + "scope": "prlanded — generalized #030 contracts + ledger #081", "outcome": "LANDED. Squash `b2d794c532ea8b7e259751005165f69906fcd784`. Adds two table-independent guards to `tests/eval-document-matching.test.ts`: pairwise alias disjointness across every multi-slot eval case, and the structural rule that one document can never satisfy every slot of a multi-slot case. Also opened ledger item #081 for the then-open PR #1196 alias conflict. Content verified by tree comparison against the squash commit (identical); remote branch deleted at merge, local pruned.", "checks": "`npm run verify:cheap` green; hosted `PR required` green; tree-identity check `git diff b2d794c5 406cf21e` empty. No provider-backed checks." }, @@ -18385,14 +18427,14 @@ "ref": "cursor/eval-matching-distinct-identity-6273", "head": "f5620e3a4a2d60fd8a67fd43d8046726f1761e5f", "scope": "Self-review of the merged #030/#075 fixes against current main", - "outcome": "Before: merged coverage matched expectations to distinct source _positions_, so one document repeated across `answer.citations` still filled both comparison slots, and first-come assignment made `allHit` depend on `expectedFiles` order; `PR_POLICY_BODY.md` was back on main (via #1153) ready to overwrite the next PR body; the #030/#075 queue row survived their archival. After: coverage dedupes by document text and assigns by maximum bipartite matching, label accumulation is linear, the stale template is removed, and #080 records the removed admission widening for approved eval re-test. Both new contracts were verified failing against main's matcher before the fix. RAG impact: no retrieval behaviour change \u2014 eval matching and label bookkeeping only.", + "outcome": "Before: merged coverage matched expectations to distinct source _positions_, so one document repeated across `answer.citations` still filled both comparison slots, and first-come assignment made `allHit` depend on `expectedFiles` order; `PR_POLICY_BODY.md` was back on main (via #1153) ready to overwrite the next PR body; the #030/#075 queue row survived their archival. After: coverage dedupes by document text and assigns by maximum bipartite matching, label accumulation is linear, the stale template is removed, and #080 records the removed admission widening for approved eval re-test. Both new contracts were verified failing against main's matcher before the fix. RAG impact: no retrieval behaviour change — eval matching and label bookkeeping only.", "checks": "Focused Vitest 39/39 (eval-document-matching, eval-utils, eval-search, search-scope, rag-imputation-contract); fail-closed proof 2 failed on the `origin/main` matcher; `npm run verify:cheap` pass (3379 passed, 5 skipped); `check:branch-review-ledger` and `check:pr-policy` pass; no OpenAI/Supabase/provider-backed checks run." }, { "date": "2026-07-25", "ref": "cursor/eval-matching-distinct-identity-6273 (PR #1204)", "head": "c0db5f5810a37dbe7df9efa3d5479db134c98e10", - "scope": "prlanded \u2014 #030 coverage hardening", + "scope": "prlanded — #030 coverage hardening", "outcome": "LANDED. Squash `eb443dfda0fcfca8181e6839d156d9986dfc52db`. `expectedFileCoverage` now dedupes the citation window by document identity and assigns sources by maximum bipartite matching, closing two re-entry routes into #030 (repeat chunk citations of one document; order-dependent greedy assignment). Content verified by tree comparison against the squash commit (identical). Remote branch deleted at merge; local branch pruned 2026-07-25 after that verification.", "checks": "`npm run verify:cheap` green pre-merge; hosted `PR required` green; tree-identity check `git diff eb443dfd c0db5f58` empty. No provider-backed checks." }, @@ -18425,14 +18467,14 @@ "ref": "cursor/fix-mode-switch-lag-22f6", "head": "54d45f687e3723f51fa3d7e9940692c9a6e3b52c", "scope": "Same-class bug hunt: mode-switch/layout thrash after reserve-flip fix", - "outcome": "No P0. Branch fix mitigates pathname\u2227searchMode gate, shell changeMode optimistic setSearchMode, selectSearchMode leaving dashboard, and always-on padding-bottom transitions. Still open P2s: (1) ClinicalDashboard.crossModeSearch still setSearchMode before router.push without isDashboardModeHref guard; (2) dashboard-internal Answer\u2194/?mode=* still eager setSearchMode \u2192 overlay/collapse + heroBreakpoint + portal rebind; (3) standalone shell persists #main-content scrollTop + phoneScrollHide across mode homes; (4) ClinicalDashboard\u2194GlobalStandaloneSearchShellClient remount + grid-template-columns transition; (5) hero portal null gap while slot/MutationObserver rebinds; (6) ModeHomeRouteLoading phone min-h 13.5rem vs idle-reserve mode homes; (7) /tools vs /?mode=tools dual shell (#007). P3: services/forms contentAlign center\u2192startOnPhone after registry load.", + "outcome": "No P0. Branch fix mitigates pathname∧searchMode gate, shell changeMode optimistic setSearchMode, selectSearchMode leaving dashboard, and always-on padding-bottom transitions. Still open P2s: (1) ClinicalDashboard.crossModeSearch still setSearchMode before router.push without isDashboardModeHref guard; (2) dashboard-internal Answer↔/?mode=* still eager setSearchMode → overlay/collapse + heroBreakpoint + portal rebind; (3) standalone shell persists #main-content scrollTop + phoneScrollHide across mode homes; (4) ClinicalDashboard↔GlobalStandaloneSearchShellClient remount + grid-template-columns transition; (5) hero portal null gap while slot/MutationObserver rebinds; (6) ModeHomeRouteLoading phone min-h 13.5rem vs idle-reserve mode homes; (7) /tools vs /?mode=tools dual shell (#007). P3: services/forms contentAlign center→startOnPhone after registry load.", "checks": "Static source audit of shell/dashboard/header/reserve/CSS/app-modes/skeletons; no browser/provider checks." }, { "date": "2026-07-25", "ref": "cursor/ledger-009-010-032-041-063-519b (PR #1175)", "head": "87b6b432c19", - "scope": "Babysit sweep: close ledger #009/#010/#032/#041/#063 \u2014 resolved outstanding-issues merge + prettier, squash-merged", + "scope": "Babysit sweep: close ledger #009/#010/#032/#041/#063 — resolved outstanding-issues merge + prettier, squash-merged", "outcome": "static-pr + pr-required", "checks": "merged" }, @@ -18448,7 +18490,7 @@ "date": "2026-07-25", "ref": "cursor/ledger-081-closeout-6273 (PR #1220)", "head": "84e91194ecca7f74c0d70b9e30e1dbd05ab7853f", - "scope": "prlanded \u2014 archive outstanding item #081", + "scope": "prlanded — archive outstanding item #081", "outcome": "LANDED. Squash `e7e60c6d02a37c1f5958cb97936bd3533c7a2f46`. #081 moved from Open items to Resolved/archive after PR #1196 was closed 2026-07-25 as superseded by #913 / current main; successor #1198 does not touch `src/lib/eval-document-matching.ts`, and the #1215 contracts fail closed on any re-added dual-listed alias. Merge friction worth recording: a `github-actions[bot]` branch-sync merge landed every 10-20 minutes and every bot-authored head produced `action_required` workflow runs, so the three required checks never reported and both normal and `--admin` merges were refused; runs on agent-pushed heads execute normally, so the resolution was to push an own-authored head and merge on green. Content verified by tree comparison against the squash commit (identical); remote branch deleted at merge, local pruned.", "checks": "`npm run verify:cheap` on merged main: 387 files / 3431 tests pass; hosted CI, SAST, Secret Scan and PR Policy green on `84e91194`; `npm run docs:check-links` pass. No provider-backed checks." }, @@ -18529,7 +18571,7 @@ "ref": "cursor/pr1197-fix-regressions-d06a (PR #1197 fix)", "head": "c1e9696de6000440ad5b44e4d2fb2738a858deae", "scope": "Fix-forward after Bugbot do-not-merge review", - "outcome": "FIXED for tip. Synced to origin/main; restored clinical-notes trust gate + boundary tests + summaryMode 400 contract by taking main; removed ISSUE-07 RAG pre-classifier (rag.ts matches main \u2014 RAG impact: no retrieval behaviour change). Kept only additive SQL remediation: migration 20260725000000 (real worker URL + ISSUE-05 revokes), schema.sql URL/[REDACTED] fix + ISSUE-05, regenerated drift-manifest. Dropped broken upload authority refs (undefined canonicalAuthority).", + "outcome": "FIXED for tip. Synced to origin/main; restored clinical-notes trust gate + boundary tests + summaryMode 400 contract by taking main; removed ISSUE-07 RAG pre-classifier (rag.ts matches main — RAG impact: no retrieval behaviour change). Kept only additive SQL remediation: migration 20260725000000 (real worker URL + ISSUE-05 revokes), schema.sql URL/[REDACTED] fix + ISSUE-05, regenerated drift-manifest. Dropped broken upload authority refs (undefined canonicalAuthority).", "checks": "Vitest: summaryMode reject + ClinicalNotes boundary 4/4; rag-classifier-memo + rag-tail-latency 17/17; upload smart-title/cleanup 3/3; check:migration-role pass; drift:manifest regenerated via Docker. No provider-backed checks." }, { @@ -18553,7 +18595,7 @@ "ref": "cursor/search-performance-review-4ee9 (PR #1134)", "head": "692834a86e612cc8b311dc6895e007f182f5c5b8", "scope": "Open-PR maintenance: superseded docs-link thread and clean main sync", - "outcome": "Before: branch was behind current main with one outdated docs-link thread; its product tree already matched main. After: merged current main cleanly and verified the route-group-aware docs-link fix now covers legacy route references. RAG impact: no retrieval behaviour change \u2014 history sync and docs tooling verification only.", + "outcome": "Before: branch was behind current main with one outdated docs-link thread; its product tree already matched main. After: merged current main cleanly and verified the route-group-aware docs-link fix now covers legacy route references. RAG impact: no retrieval behaviour change — history sync and docs tooling verification only.", "checks": "`node scripts/check-docs-links.mjs` pass (1154 references); clean merge-tree; no live RAG canary or provider-backed check run." }, { @@ -18609,7 +18651,7 @@ "ref": "execute-audit-code-remediation (PR #1162)", "head": "d5455837231f5cb6a927e8c4752ef5aa9c72767c", "scope": "Merge conflict + CI + Bugbot review", - "outcome": "Merged origin/main (164 behind). Fixed conflicts in ClinicalDashboard/global-search-shell/mode-home/search-scope/tests/pdf extractor. Renamed duplicate migration 20260724120000\u219220260724130200. CI: skills openai.yaml, owner-scope setup-status exemption, sitemap, drift hash, answer-render duplicate key, setup-status mock `.eq`. Bugbot: fixed Codex P1 view-only indexing + P2 differential back; also fixed P2 viewer visibility for retained images and duplicate-upload cleanup ledger fail-closed.", + "outcome": "Merged origin/main (164 behind). Fixed conflicts in ClinicalDashboard/global-search-shell/mode-home/search-scope/tests/pdf extractor. Renamed duplicate migration 20260724120000→20260724130200. CI: skills openai.yaml, owner-scope setup-status exemption, sitemap, drift hash, answer-render duplicate key, setup-status mock `.eq`. Bugbot: fixed Codex P1 view-only indexing + P2 differential back; also fixed P2 viewer visibility for retained images and duplicate-upload cleanup ledger fail-closed.", "checks": "Focused Vitest (back-href/worker/skills/setup-status/owner-scope/drift/sitemap/search-scope/favourites/forms/therapy/document-detail/upload-ledger) + typecheck + check:skills/migration-role/sitemap; no provider-backed checks." }, { @@ -18680,7 +18722,7 @@ "date": "2026-07-25", "ref": "fix-physics-animation-audit (PR #1142)", "head": "e966b5aa972", - "scope": "Babysit sweep: spring physics / reduced-motion \u2014 auto-merged after main sync", + "scope": "Babysit sweep: spring physics / reduced-motion — auto-merged after main sync", "outcome": "pr-required", "checks": "merged" }, @@ -18696,7 +18738,7 @@ "date": "2026-07-25", "ref": "implement-audit-recommendations-fix (PR #1140)", "head": "f4ae0a7217e", - "scope": "Babysit sweep: viewport/keyboard audit \u2014 squash-merged after CI green + thread triage", + "scope": "Babysit sweep: viewport/keyboard audit — squash-merged after CI green + thread triage", "outcome": "production-ui + pr-required", "checks": "merged" }, @@ -18760,7 +18802,7 @@ "date": "2026-07-25", "ref": "information-page-shell (PR #1148)", "head": "5b9574af480", - "scope": "Babysit sweep: unify information-page structure \u2014 squash-merged", + "scope": "Babysit sweep: unify information-page structure — squash-merged", "outcome": "pr-required", "checks": "merged" }, @@ -18776,7 +18818,7 @@ "date": "2026-07-25", "ref": "mobile-ergonomics-fixes (PR #1156)", "head": "de1a82b4936", - "scope": "Babysit sweep: mobile touch ergonomics \u2014 squash-merged", + "scope": "Babysit sweep: mobile touch ergonomics — squash-merged", "outcome": "pr-required", "checks": "merged" }, @@ -18816,7 +18858,7 @@ "date": "2026-07-25", "ref": "PR #1090 / `cursor/fix-phone-dock-edge-1b1d`", "head": "c993975f6b18393a9ff09f9145fd42dbb35df942 (merged as 09028ef217209fceb53f1122ac7738b509bce323)", - "scope": "prlanded \u2014 phone dock edge-to-edge / white-strip fix", + "scope": "prlanded — phone dock edge-to-edge / white-strip fix", "outcome": "MERGED. Content verified on `origin/main` (empty three-dot diff; spot-check dock CSS, ClinicalDashboard inset-0 shell, edge-to-edge Playwright test). No orphaned late commits. Remote branch already deleted; local branch removed. Codex review found no major issues; required CI green at merge.", "checks": "Hosted required + Production UI green at merge; local maintainability budget + Prettier follow-ups landed in tip `c993975f`." }, @@ -18825,7 +18867,7 @@ "ref": "PR #1162 / `execute-audit-code-remediation`", "head": "692eb248c095d64443a5f9ed0ab7b02394f0ed4b", "scope": "Explicit thorough Antigravity PR review", - "outcome": "CONDITIONAL after rebase. Substantive upload RPC + batch signed-URL work looks sound (service_role-only SECURITY DEFINER; batch auth equivalent to single-image). Still CONFLICTING vs main (ClinicalDashboard, global-search-shell, mode-home-template, search-scope, tests, pdf extractor). P2: batch rate-limit amplification \u00d7100; mobile back `push` vs `back` semantics; duplicate-hash match via plpgsql message text. CI red on Static/Safety/Unit/UI/Migration.", + "outcome": "CONDITIONAL after rebase. Substantive upload RPC + batch signed-URL work looks sound (service_role-only SECURITY DEFINER; batch auth equivalent to single-image). Still CONFLICTING vs main (ClinicalDashboard, global-search-shell, mode-home-template, search-scope, tests, pdf extractor). P2: batch rate-limit amplification ×100; mobile back `push` vs `back` semantics; duplicate-hash match via plpgsql message text. CI red on Static/Safety/Unit/UI/Migration.", "checks": "merge-tree conflict list; static auth/RPC review. No provider/migration replay." }, { @@ -18865,7 +18907,7 @@ "ref": "PR #1186 / `remediate-repository-audit-findings`", "head": "8637fec36dea6534c02e5b3f12e5a913c10bc455", "scope": "Explicit thorough Antigravity PR review", - "outcome": "DO NOT MERGE. P0: duplicate `const results` in `scripts/eval-retrieval.ts` (RAG eval surface; needs RAG impact line). P0: skills catalog 32\u219235 breaks `tests/database-skills.test.ts`. P1: stale-lock heartbeat never fires under `spawnSync`; `skill-create` YAML wrong shape; `sweep-merged-branches` destructive without dry-run + shell interpolation. Inherits conflict markers.", + "outcome": "DO NOT MERGE. P0: duplicate `const results` in `scripts/eval-retrieval.ts` (RAG eval surface; needs RAG impact line). P0: skills catalog 32→35 breaks `tests/database-skills.test.ts`. P1: stale-lock heartbeat never fires under `spawnSync`; `skill-create` YAML wrong shape; `sweep-merged-branches` destructive without dry-run + shell interpolation. Inherits conflict markers.", "checks": "`git show` eval-retrieval duplicate const; marker scan. No provider/eval runs." }, { @@ -18873,7 +18915,7 @@ "ref": "PR #1187 / `cursor/fix-mode-switch-lag-22f6`", "head": "113de416970cceea8952df55b3fe41cd7a2ca82a", "scope": "Explicit thorough open-PR review", - "outcome": "DO NOT MERGE. CONFLICTING on `globals.css` (semantic vs main motion tokens). P1: `isDashboardModeHref` early-return breaks Answer\u2192Documents cross-mode search (`/documents/search` keeps ClinicalDashboard mounted; stale mode + `run=1` can fire unintended answer generation). P2: dock reveal snap; phone dock flash on mode-home nav; forced scrollTop=0 on every pathname; skeleton min-height overshoot. PR body mismatched.", + "outcome": "DO NOT MERGE. CONFLICTING on `globals.css` (semantic vs main motion tokens). P1: `isDashboardModeHref` early-return breaks Answer→Documents cross-mode search (`/documents/search` keeps ClinicalDashboard mounted; stale mode + `run=1` can fire unintended answer generation). P2: dock reveal snap; phone dock flash on mode-home nav; forced scrollTop=0 on every pathname; skeleton min-height overshoot. PR body mismatched.", "checks": "Static path trace through app-modes/search-route-ownership; merge-tree confirmed globals.css conflict. Hosted CI previously red (Static PR + Production UI). No provider calls." }, { @@ -18921,7 +18963,7 @@ "ref": "PR #1190 / `remediate-dark-mode-audit`", "head": "00eca49b9b0d7e5fbfa5703a15e9e930963984a6", "scope": "Cursor review+Bugbot+prlanded+debug (fresh pass, same HEAD)", - "outcome": "DO NOT MERGE; NOT LANDED (OPEN, mergeable=CONFLICTING/DIRTY, 468 behind / 2 ahead). Reconfirmed P0: conflict resolution deleted `trustGatedAnswerForClinicalNotes` (0 hits on head; main L584/632/659/1075) \u2014 Clinical Notes consumes ungated answer. P1: `src/app/api/answer/route.ts:6` imports nonexistent `@/lib/rag` (tsc TS2307; stream correctly uses `@/lib/rag/rag`). P1: merge-tree conflicts on answer/upload/evidence-panels + 10 paths; literal `<<<<<<<` in docs audit plan; migration timestamp collision risk vs main. Intentional dark-mode delta is only commit `363672602` (~10 files). Salvage: `cursor/pr1190-dark-mode-salvage-f453` cherry-picks that commit onto current main, restores unused-manifest-import cleanup, keeps clinical gate. Close #1190 after salvage lands.", + "outcome": "DO NOT MERGE; NOT LANDED (OPEN, mergeable=CONFLICTING/DIRTY, 468 behind / 2 ahead). Reconfirmed P0: conflict resolution deleted `trustGatedAnswerForClinicalNotes` (0 hits on head; main L584/632/659/1075) — Clinical Notes consumes ungated answer. P1: `src/app/api/answer/route.ts:6` imports nonexistent `@/lib/rag` (tsc TS2307; stream correctly uses `@/lib/rag/rag`). P1: merge-tree conflicts on answer/upload/evidence-panels + 10 paths; literal `<<<<<<<` in docs audit plan; migration timestamp collision risk vs main. Intentional dark-mode delta is only commit `363672602` (~10 files). Salvage: `cursor/pr1190-dark-mode-salvage-f453` cherry-picks that commit onto current main, restores unused-manifest-import cleanup, keeps clinical gate. Close #1190 after salvage lands.", "checks": "Bugbot; `git grep` gate/import/markers; merge-tree; `tsc` TS2307 proof; gh pr view/checks (PR policy fail). Salvage: tsc clean; visual-evidence+overlay tests 13/13; eslint on changed files. No provider/UI matrix." }, { @@ -18937,7 +18979,7 @@ "ref": "PR #1192 / `cursor/fix-mobile-composer-edge-scroll-5b1d`", "head": "0c2b60a646fd6e7a53cf24f778aa59e3d54ba8aa", "scope": "Explicit thorough open-PR review (Antigravity/Cursor queue)", - "outcome": "REQUEST CHANGES. P1: `composerChromeFocused` latches forever when focused dock unmounts (no blur), pinning header scroll-hide permanently. P2: reserve-only hide gate ignores offset \u2192 near-bottom clamp (stress: 120/224 frames on answer geometry; 584 clamp-risk across sweep). P2s: submit blur to body; autofocus re-fire; non-answer `focus=1` unfixed; untested collapseKind DOM mapping; PR body copy-paste mismatch.", + "outcome": "REQUEST CHANGES. P1: `composerChromeFocused` latches forever when focused dock unmounts (no blur), pinning header scroll-hide permanently. P2: reserve-only hide gate ignores offset → near-bottom clamp (stress: 120/224 frames on answer geometry; 584 clamp-risk across sweep). P2s: submit blur to body; autofocus re-fire; non-answer `focus=1` unfixed; untested collapseKind DOM mapping; PR body copy-paste mismatch.", "checks": "Focused Vitest mobile-composer-reserve + use-hide-on-scroll PASS in detached worktree; Node stress of reserve-only gate; static diff review. No provider/UI browser matrix." }, { @@ -18961,7 +19003,7 @@ "ref": "PR #1192 / `cursor/fix-mobile-composer-edge-scroll-5b1d`", "head": "70abb74f7ceee5a50748c4c1e6baa730d7225cf4", "scope": "User-requested /review + Bugbot + /debug + /prlanded on current tip", - "outcome": "APPROVE with notes. Prior P1 focus latch and P2 near-bottom reserve-only clamp confirmed fixed on `5b5ecf405` and retained through main merge. No new P0/P1. Residual P2s: PR body was wrong audit-remediation paste (fixing); non-answer `focus=1` autofocus still broad; earlier document-detail double-header findings unchanged/out of Answer-dock scope. /prlanded: still OPEN, not merged. GitHub CONFLICTING was staleness (merge-tree clean) \u2014 merged origin/main.", + "outcome": "APPROVE with notes. Prior P1 focus latch and P2 near-bottom reserve-only clamp confirmed fixed on `5b5ecf405` and retained through main merge. No new P0/P1. Residual P2s: PR body was wrong audit-remediation paste (fixing); non-answer `focus=1` autofocus still broad; earlier document-detail double-header findings unchanged/out of Answer-dock scope. /prlanded: still OPEN, not merged. GitHub CONFLICTING was staleness (merge-tree clean) — merged origin/main.", "checks": "Bugbot; focused Vitest use-hide-on-scroll + mobile-composer-reserve 28/28 before and after main merge; merge-tree clean; no provider/UI browser matrix this pass." }, { @@ -18969,7 +19011,7 @@ "ref": "PR #1192 / `cursor/fix-mobile-composer-edge-scroll-5b1d`", "head": "73e87da63f5a9eca4162534074755891f952a4ee", "scope": "CORRECTION/supersede: final head after Bugbot fixes + main sync + review ledger push", - "outcome": "APPROVE with notes retained from prior row. Product fixes from `5b5ecf405` still present; branch now 0 behind / mergeable (BLOCKED on CI). Wrong audit-remediation PR body corrected. /prlanded: still OPEN \u2014 do not delete branch.", + "outcome": "APPROVE with notes retained from prior row. Product fixes from `5b5ecf405` still present; branch now 0 behind / mergeable (BLOCKED on CI). Wrong audit-remediation PR body corrected. /prlanded: still OPEN — do not delete branch.", "checks": "Focused Vitest 28/28 on pre-sync tip; merge-tree clean; CI re-queued on tip; no provider-backed checks." }, { @@ -18984,8 +19026,8 @@ "date": "2026-07-25", "ref": "PR #1192 / cursor/fix-mobile-composer-edge-scroll-5b1d @ 2955bc5c", "head": "df72c725", - "scope": "CI / Production UI failure \u2014 non-answer phone header keeps the in-flow collapse hide", - "outcome": "FIXED. Single failing Playwright test: `tests/ui-smoke.spec.ts:3780 \u2014 non-answer phone header keeps the in-flow collapse hide`. Root cause: RAF debouncing in useHideOnScroll.onScroll coalesces a layout-clamp scroll event with the test's deliberate -24px upward scroll into one RAF evaluation. The hook sees lastMaxOffsetRef stale (pre-collapse visibleMaxOffset V) while the net offset is already V-96 (= newMaxOffset-24). The clamp detection fires (`lastOffset V > newMaxOffset V-72`), incorrectly suppressing the genuine reveal. Fix: added `offset >= maxOffset - revealIntentDistance` guard to the clamp detection in `computeScrollHideUpdate`. Only treat movement as geometry feedback when the net offset is within revealIntentDistance (12 px) of the new bottom edge. Unit test added. PR-required failure is downstream of Production UI only (no independent breakage).", + "scope": "CI / Production UI failure — non-answer phone header keeps the in-flow collapse hide", + "outcome": "FIXED. Single failing Playwright test: `tests/ui-smoke.spec.ts:3780 — non-answer phone header keeps the in-flow collapse hide`. Root cause: RAF debouncing in useHideOnScroll.onScroll coalesces a layout-clamp scroll event with the test's deliberate -24px upward scroll into one RAF evaluation. The hook sees lastMaxOffsetRef stale (pre-collapse visibleMaxOffset V) while the net offset is already V-96 (= newMaxOffset-24). The clamp detection fires (`lastOffset V > newMaxOffset V-72`), incorrectly suppressing the genuine reveal. Fix: added `offset >= maxOffset - revealIntentDistance` guard to the clamp detection in `computeScrollHideUpdate`. Only treat movement as geometry feedback when the net offset is within revealIntentDistance (12 px) of the new bottom edge. Unit test added. PR-required failure is downstream of Production UI only (no independent breakage).", "checks": "verify:cheap pass (exit 0); npm run test 20/20 on use-hide-on-scroll.test.ts; Playwright chromium 9/9 scroll-hide smoke tests; Playwright chromium 1/1 target test. No provider-backed checks." }, { @@ -19009,7 +19051,7 @@ "ref": "PR #1195 / `subagent-Asset-Optimization-Implementer-self-b295a5bb`", "head": "8888bf87cbdc5a061bb6d3a2cf46b638af773b1b", "scope": "Cursor review+Bugbot+/debug (supersedes f3d90ecc Bugbot row)", - "outcome": "CONDITIONAL READY after favicon fix. Prior tip DO NOT MERGE (conflict-marker pollution) cleared by Bugbot main-merge; SignedImage transform silent no-op removed; check:assets now compare-only. Remaining P1 found+fixed: SVGO-stripped `icon.svg` failed `brand:check` and removed dark-mode favicon styles \u2014 restored `brandIconSvg()` and excluded that file from SVGO gate. Residual P2: orphan AVIF/WebP binaries unused by demo/mockup PNG refs; year-long immutable Cache-Control on unversioned `/icons/*`; `minimumCacheTTL: 86400` still a long lower bound for any optimized next/image. NOT LANDED (OPEN).", + "outcome": "CONDITIONAL READY after favicon fix. Prior tip DO NOT MERGE (conflict-marker pollution) cleared by Bugbot main-merge; SignedImage transform silent no-op removed; check:assets now compare-only. Remaining P1 found+fixed: SVGO-stripped `icon.svg` failed `brand:check` and removed dark-mode favicon styles — restored `brandIconSvg()` and excluded that file from SVGO gate. Residual P2: orphan AVIF/WebP binaries unused by demo/mockup PNG refs; year-long immutable Cache-Control on unversioned `/icons/*`; `minimumCacheTTL: 86400` still a long lower bound for any optimized next/image. NOT LANDED (OPEN).", "checks": "Bugbot; marker scan clean; brand:check + check:assets PASS; signed-image vitest 7/7; hosted Static/Safety were red on pre-fix tip (brand:check). No provider-backed app checks." }, { @@ -19081,7 +19123,7 @@ "ref": "PR #1196 / codex/fix-p2-audit-20260719", "head": "6d59b038514a92566e986d302b0c75707f13ea30", "scope": "fresh bug/regression review + Bugbot (clinical/RAG/search/auth/privacy)", - "outcome": "Changes requested. Not merge-ready. No P0. P1: search/embedding last-waiter abort leaves dying inflight map entry so healthy same-key retry can coalesce onto aborted work (HTTP 500 / AbortError); also present on main \u2014 fixed forward in cursor/pr1196-coalesce-main-4711 / PR #1212. P2: fractional PDF render dimensions rejected by Number.isSafeInteger(pixels), aborting JS fallback \u2014 also fixed in #1212. Cleared after inspection: public storage_path omission, document chunk UUID fail-closed schema, factsheet save persistence, therapy capability flags, extractive section-dedup exemption, auth definitive-vs-retryable handling. Blockers: GitHub mergeable CONFLICTING; ~680 commits behind main; ~23 content conflicts including openai.ts, rag.ts, semantic-rerank, supabase client, package.json, therapies-index. PR body RAG impact understates clinical-search / answer-ranking / retrieval-variant edits. prlanded: state OPEN, not merged.", + "outcome": "Changes requested. Not merge-ready. No P0. P1: search/embedding last-waiter abort leaves dying inflight map entry so healthy same-key retry can coalesce onto aborted work (HTTP 500 / AbortError); also present on main — fixed forward in cursor/pr1196-coalesce-main-4711 / PR #1212. P2: fractional PDF render dimensions rejected by Number.isSafeInteger(pixels), aborting JS fallback — also fixed in #1212. Cleared after inspection: public storage_path omission, document chunk UUID fail-closed schema, factsheet save persistence, therapy capability flags, extractive section-dedup exemption, auth definitive-vs-retryable handling. Blockers: GitHub mergeable CONFLICTING; ~680 commits behind main; ~23 content conflicts including openai.ts, rag.ts, semantic-rerank, supabase client, package.json, therapies-index. PR body RAG impact understates clinical-search / answer-ranking / retrieval-variant edits. prlanded: state OPEN, not merged.", "checks": "Bugbot + offline static/diff review + pure-JS race/fractional-pixel proofs; focused Vitest on #1212 fix (163 passed). Full PR #1196 Vitest/UI not re-run on stale tip. No OpenAI/Supabase/provider writes. Hosted CI for #1196 only showed PR policy pass + GitGuardian fail; required suite not green on this head." }, { @@ -19216,7 +19258,7 @@ "date": "2026-07-25", "ref": "sitewide-design-review-ledger (PR #1181)", "head": "8284fcd4420", - "scope": "Babysit sweep: design-review ledger \u2014 auto-merged after sync", + "scope": "Babysit sweep: design-review ledger — auto-merged after sync", "outcome": "pr-required", "checks": "merged" }, @@ -19257,7 +19299,7 @@ "ref": "`codex/review-search-bar-behavior-and-establish-rules` (PR #1137)", "head": "b10514374ac7640e5d3395f707c6f958764ae131 + ledger bookkeeping", "scope": "PR babysit: CI fix + Codex threads + drift", - "outcome": "COMPLETED for current head. Restored Tools arm in `showDesktopHomeComposer` and moved `0rem` reserve comment to `mobileComposerReserve` (3d82ead2); replaced unresolvable ledger SHA `bcf4571\u2026` with `6ee0484\u2026`; formatted `docs/search-chrome-behaviour.md`; merged `origin/main` (`0cc0ee2d`). 3/3 Codex review threads resolved via GraphQL (inline replies 403 with this token). Prior CI failures (syntax from misplaced comment) cleared on 3d82ead2; Production UI job cancelled mid-aggregate before this merge \u2014 CI re-running after push.", + "outcome": "COMPLETED for current head. Restored Tools arm in `showDesktopHomeComposer` and moved `0rem` reserve comment to `mobileComposerReserve` (3d82ead2); replaced unresolvable ledger SHA `bcf4571…` with `6ee0484…`; formatted `docs/search-chrome-behaviour.md`; merged `origin/main` (`0cc0ee2d`). 3/3 Codex review threads resolved via GraphQL (inline replies 403 with this token). Prior CI failures (syntax from misplaced comment) cleared on 3d82ead2; Production UI job cancelled mid-aggregate before this merge — CI re-running after push.", "checks": "Local: format:check on touched files; Vitest `ui-overlay-css-contract` + `mobile-composer-reserve` 15/15. Hosted: static/unit/build/advisory green on 3d82ead2. No provider-backed checks run." }, { @@ -19297,7 +19339,7 @@ "ref": "`cursor/docs-reliability-review-c38b`", "head": "af5d44abf031581d256006b51a1be98563d441d5", "scope": "Documentation reliability review vs repo state (setup, env, ops runbooks, testing safety)", - "outcome": "Fixed P1/P2 doc drift: worker region Sydney\u2192Railway Singapore; DR golden gate 23/23\u219236/36; Railway health `/api/health/ready`; auth checklist aligned to magic-link+OAuth UI; staging identity vars in `.env.example`; provider-approval boundary on testing/readiness docs; mode count 11\u219213. No P0. Residual: historical `23/23` mentions in point-in-time/archive docs left alone.", + "outcome": "Fixed P1/P2 doc drift: worker region Sydney→Railway Singapore; DR golden gate 23/23→36/36; Railway health `/api/health/ready`; auth checklist aligned to magic-link+OAuth UI; staging identity vars in `.env.example`; provider-approval boundary on testing/readiness docs; mode count 11→13. No P0. Residual: historical `23/23` mentions in point-in-time/archive docs left alone.", "checks": "`npm run docs:check-links`; `npm run docs:check-index`; `git diff --check`. No provider/OpenAI/Supabase/Railway mutation." }, { @@ -19305,7 +19347,7 @@ "ref": "`cursor/search-performance-review-4ee9` / PR #1134", "head": "76d47871c44c607f942a683351378230173dcbe3", "scope": "Search performance findings remediation (prescribing, differentials, typeahead docs timeout, shared shell, answer rate-limit fallback)", - "outcome": "FIXED. P1 prescribing catalogue now debounces (250\u202fms), aborts in-flight fetches, and uses `fields=index`. Differentials catalogue + evidence search abort/debounce. Universal documents typeahead timeout 6\u202fs\u2192750\u202fms (RAG impact: no retrieval behaviour change \u2014 typeahead timeout only). Shared `(search-app)` layout keeps GlobalSearchShell mounted across mode homes. Answer rate-limit fails closed only in production; development uses in-memory fallback when durable RPC is unavailable.", + "outcome": "FIXED. P1 prescribing catalogue now debounces (250 ms), aborts in-flight fetches, and uses `fields=index`. Differentials catalogue + evidence search abort/debounce. Universal documents typeahead timeout 6 s→750 ms (RAG impact: no retrieval behaviour change — typeahead timeout only). Shared `(search-app)` layout keeps GlobalSearchShell mounted across mode homes. Answer rate-limit fails closed only in production; development uses in-memory fallback when durable RPC is unavailable.", "checks": "Focused Vitest 362 via test:focused; api-rate-limit/search-shell/universal/route/site-map suites green; `npm run ensure` smoke 200 on mode homes; `/api/answer/stream` 200 after fallback. No OpenAI spend beyond local answer stream smoke; no live eval/soak." }, { @@ -19313,7 +19355,7 @@ "ref": "`cursor/sidebar-six-item-land-cfa0` / PR #1174 content-proof `d97c11e6`", "head": "d97c11e6", "scope": "#066 land/proof of six-item sidebar from `cd54e68f` onto main", - "outcome": "PROVE \u2014 feature content landed; focused 20/20; verify:pr-local PASS; ensure spot-check PASS; verify:ui 267/267. Not merged to main.", + "outcome": "PROVE — feature content landed; focused 20/20; verify:pr-local PASS; ensure spot-check PASS; verify:ui 267/267. Not merged to main.", "checks": "vitest favourites+therapy; verify:pr-local; ensure+computerUse spot-check; verify:ui" }, { @@ -19329,8 +19371,8 @@ "ref": "`main`", "head": "6ceaaff50712e10e857bf9a5a7ec88b530bf7b35", "scope": "Search performance across modes (load + typeahead + submit; local ensure)", - "outcome": "CHANGES REQUESTED / findings. No P0. P1: Prescribing `useMedicationCatalog(query)` refetches the full ~2.5\u20132.9\u202fMB medication catalogue on every keystroke without debounce, abort, or `fields=index` (~25\u00d7 larger than index). P2: differentials catalogue + evidence `/api/search` lack abort/debounce; universal typeahead `tookMs` dominated by empty live documents domain (~130\u2013340\u202fms); cross-namespace mode switches remount the search shell; Answer submit returns 503 `rate_limit_unavailable` when durable limiter is down (fail-closed). Mode HTML load medians ~40\u201375\u202fms; typeahead wall ~160\u2013180\u202fms (`ssri`) / ~350\u2013400\u202fms (`agitation im lorazepam`) + 250\u202fms client debounce; catalogue submits (differentials) ~45\u202fms; document `/api/search` demo-degraded ~230\u2013430\u202fms. Highest residual live risk: cold hybrid RPC tails (docs #25), not re-measured with soak/eval.", - "checks": "`npm run ensure` \u2192 http://localhost:4461; `/api/local-project-id` Clinical KB; paced universal typeahead across 13 modes \u00d7 2 queries (Server-Timing); `/api/search` + `/api/medications` (+`fields=index`) + differentials APIs + registry payload sizes; NDJSON vs JSON first-byte; browser walkthrough of 13 mode homes; static review of ClinicalDashboard / universal-search / medication+differential hooks. No OpenAI generation, no `eval:retrieval:latency`, no soak, no hosted CI. Environment had Supabase secrets so universal ran live (`publicAccess`); `/api/search` degraded to demo (`supabase_api_key_configuration_unavailable`)." + "outcome": "CHANGES REQUESTED / findings. No P0. P1: Prescribing `useMedicationCatalog(query)` refetches the full ~2.5–2.9 MB medication catalogue on every keystroke without debounce, abort, or `fields=index` (~25× larger than index). P2: differentials catalogue + evidence `/api/search` lack abort/debounce; universal typeahead `tookMs` dominated by empty live documents domain (~130–340 ms); cross-namespace mode switches remount the search shell; Answer submit returns 503 `rate_limit_unavailable` when durable limiter is down (fail-closed). Mode HTML load medians ~40–75 ms; typeahead wall ~160–180 ms (`ssri`) / ~350–400 ms (`agitation im lorazepam`) + 250 ms client debounce; catalogue submits (differentials) ~45 ms; document `/api/search` demo-degraded ~230–430 ms. Highest residual live risk: cold hybrid RPC tails (docs #25), not re-measured with soak/eval.", + "checks": "`npm run ensure` → http://localhost:4461; `/api/local-project-id` Clinical KB; paced universal typeahead across 13 modes × 2 queries (Server-Timing); `/api/search` + `/api/medications` (+`fields=index`) + differentials APIs + registry payload sizes; NDJSON vs JSON first-byte; browser walkthrough of 13 mode homes; static review of ClinicalDashboard / universal-search / medication+differential hooks. No OpenAI generation, no `eval:retrieval:latency`, no soak, no hosted CI. Environment had Supabase secrets so universal ran live (`publicAccess`); `/api/search` degraded to demo (`supabase_api_key_configuration_unavailable`)." }, { "date": "2026-07-24", @@ -19345,15 +19387,15 @@ "ref": "`main` / `01c209576207a3c279972697718d06c819fff000`", "head": "01c209576207a3c279972697718d06c819fff000", "scope": "Sitewide design/UX/interactive review (production pages, breakpoints, a11y)", - "outcome": "CHANGES REQUESTED / findings. No P0. Two confirmed P2 UX defects: (1) mobile presentation Compare tab is a self-link that drops `ids`/`q` and resets selection (1\u2192default 4) + clears Query chip; (2) document \u201cBrowse by tag\u201d / `searchByTag` navigates to `/?mode=documents&q=\u2026` without `run=1`, so results do not run. P3: comparison disabled dropdown/filter controls lack `aria-describedby` placeholder contract; bare `/documents` 404 (no inbound links; `/documents/search` is canonical); phone mode-switcher truncates \u201cDifferenti\u2026\u201d. Deduped: `/tools` vs `/?mode=tools` remains #007; coming-soon density/favourites/forms remain #010. Phone docks flush `bottom:0` on sampled result routes; no document horizontal overflow at 390/768/1280 across 30 routes.", - "checks": "`npm run workflow:design-sweep -- --write-evidence`; `npm run ensure` \u2192 http://localhost:4461 identity Clinical KB; Playwright HTTP+overflow matrix 30/30 no overflow; live Compare/tag proofs + phone route matrix; `npm run test:e2e:accessibility` 12/12; screenshots under `/opt/cursor/artifacts/screenshots/design-review-2026-07-24/`. No OpenAI/Supabase/GitHub/hosted CI/provider mutations. Added project subagent `.cursor/agents/design-review.md`." + "outcome": "CHANGES REQUESTED / findings. No P0. Two confirmed P2 UX defects: (1) mobile presentation Compare tab is a self-link that drops `ids`/`q` and resets selection (1→default 4) + clears Query chip; (2) document “Browse by tag” / `searchByTag` navigates to `/?mode=documents&q=…` without `run=1`, so results do not run. P3: comparison disabled dropdown/filter controls lack `aria-describedby` placeholder contract; bare `/documents` 404 (no inbound links; `/documents/search` is canonical); phone mode-switcher truncates “Differenti…”. Deduped: `/tools` vs `/?mode=tools` remains #007; coming-soon density/favourites/forms remain #010. Phone docks flush `bottom:0` on sampled result routes; no document horizontal overflow at 390/768/1280 across 30 routes.", + "checks": "`npm run workflow:design-sweep -- --write-evidence`; `npm run ensure` → http://localhost:4461 identity Clinical KB; Playwright HTTP+overflow matrix 30/30 no overflow; live Compare/tag proofs + phone route matrix; `npm run test:e2e:accessibility` 12/12; screenshots under `/opt/cursor/artifacts/screenshots/design-review-2026-07-24/`. No OpenAI/Supabase/GitHub/hosted CI/provider mutations. Added project subagent `.cursor/agents/design-review.md`." }, { "date": "2026-07-24", "ref": "`main` / `037b4808100946f96aee28b8ff51939ae2986851`", "head": "037b4808100946f96aee28b8ff51939ae2986851", "scope": "frontend-ui review: clinical-dashboard sidebar streamlining, global-search-shell, mobile-composer-reserve, globals.css forced-colors/reduced-motion, evidence-panels aria, answer-result-surface, visual-evidence-tabs DOM tests", - "outcome": "APPROVE with notes (P2 closed on `cursor/frontend-ui-review-docs-e8d9`). No P0/P1. One P2 was docs-only: `docs/codebase-index.md` mode-home list omitted `/therapy-compass`, `/dsm`, `/specifiers`, and `/factsheets` while `isStandaloneModeHome` already handles them \u2014 fixed in the follow-up docs PR. What holds: sidebar streamlining (`primarySidebarToolIds` Set) is correct; global reduced-motion CSS covers `animate-spin`; forced-colors token remap is comprehensive; mobile-composer-reserve and overlay CSS contracts intact; tab/tabpanel ARIA associations pass in jsdom; icon-only collapsed rail links carry `aria-label`+`title`; lucide-react defaults SVG `aria-hidden=\"true\"`.", + "outcome": "APPROVE with notes (P2 closed on `cursor/frontend-ui-review-docs-e8d9`). No P0/P1. One P2 was docs-only: `docs/codebase-index.md` mode-home list omitted `/therapy-compass`, `/dsm`, `/specifiers`, and `/factsheets` while `isStandaloneModeHome` already handles them — fixed in the follow-up docs PR. What holds: sidebar streamlining (`primarySidebarToolIds` Set) is correct; global reduced-motion CSS covers `animate-spin`; forced-colors token remap is comprehensive; mobile-composer-reserve and overlay CSS contracts intact; tab/tabpanel ARIA associations pass in jsdom; icon-only collapsed rail links carry `aria-label`+`title`; lucide-react defaults SVG `aria-hidden=\"true\"`.", "checks": "Full unit suite 3261/3264 passed (3 pre-existing skips); typecheck clean; lint clean; static read of globals.css forced-colors/reduced-motion, overlay contracts, aria patterns, and mobile-composer-reserve. Docs mode-home list aligned to `isStandaloneModeHome`. No live Supabase/OpenAI/Railway mutation." }, { @@ -19361,7 +19403,7 @@ "ref": "`main` / PR #1122 tip `037b4808100946f96aee28b8ff51939ae2986851`", "head": "037b4808100946f96aee28b8ff51939ae2986851", "scope": "Code-quality review of tip commit (streamlined sidebar tool list)", - "outcome": "No P0-P1. Two P2 maintainability findings: (1) dual catalogue \u2014 `sidebarToolItems` still defines specialist tools that `primarySidebarToolIds` always filters out, leaving unused Lucide imports and a footgun where new catalogue rows do not appear unless also added to the Set; (2) favourites-auth-gate asserts primary IDs by regex-parsing the Set initializer source, which couples the suite to TypeScript formatting. Highest residual risk is quiet nav drift if specialists are re-added only to `sidebarToolItems`. #066 in outstanding-issues still describes this sidebar land as open despite the tip merge.", + "outcome": "No P0-P1. Two P2 maintainability findings: (1) dual catalogue — `sidebarToolItems` still defines specialist tools that `primarySidebarToolIds` always filters out, leaving unused Lucide imports and a footgun where new catalogue rows do not appear unless also added to the Set; (2) favourites-auth-gate asserts primary IDs by regex-parsing the Set initializer source, which couples the suite to TypeScript formatting. Highest residual risk is quiet nav drift if specialists are re-added only to `sidebarToolItems`. #066 in outstanding-issues still describes this sidebar land as open despite the tip merge.", "checks": "Static diff inspection of `ClinicalSidebar.tsx`, `tests/favourites-auth-gate.test.ts`, `tests/ui-smoke.spec.ts`; no lint/test/provider runs (pure review)." }, { @@ -19377,8 +19419,8 @@ "ref": "`origin/main`", "head": "6ceaaff50712e10e857bf9a5a7ec88b530bf7b35", "scope": "sitewide design/UX review (production pages)", - "outcome": "FINDINGS CAPTURED. No P0. Confirmed defects later archived as `#070`\u2013`#074` after ID collision with main `#068`/`#069`. Updated `#010` for Compact/Detailed selected-but-disabled look. Deduped against `#007`/`#016`/`#038`\u2013`#041`/`#063`\u2013`#066`. Residual: large mobile PWA install sheet density; compare URL-state sync; axe coverage beyond home (`#040`). No product code fixes in this pass.", - "checks": "Offline: design-system-contract, type-scale, icon-scale, brand:check, design-sweep evidence. Live: `npm run ensure` \u2192 `http://localhost:4461` identity OK; mode-home/detail HTTP 200 + no document overflow at 390/1280; presentation href + forced Overview navigation proof; Tools Sort/More DOM proof; `test:e2e:accessibility` 12/12. Screenshots under `/opt/cursor/artifacts/screenshots/`. No OpenAI/Supabase/GitHub/hosted CI/provider calls." + "outcome": "FINDINGS CAPTURED. No P0. Confirmed defects later archived as `#070`–`#074` after ID collision with main `#068`/`#069`. Updated `#010` for Compact/Detailed selected-but-disabled look. Deduped against `#007`/`#016`/`#038`–`#041`/`#063`–`#066`. Residual: large mobile PWA install sheet density; compare URL-state sync; axe coverage beyond home (`#040`). No product code fixes in this pass.", + "checks": "Offline: design-system-contract, type-scale, icon-scale, brand:check, design-sweep evidence. Live: `npm run ensure` → `http://localhost:4461` identity OK; mode-home/detail HTTP 200 + no document overflow at 390/1280; presentation href + forced Overview navigation proof; Tools Sort/More DOM proof; `test:e2e:accessibility` 12/12. Screenshots under `/opt/cursor/artifacts/screenshots/`. No OpenAI/Supabase/GitHub/hosted CI/provider calls." }, { "date": "2026-07-24", @@ -19401,7 +19443,7 @@ "ref": "audit-remediation (PR #1153)", "head": "c4adfe9e27e43edfdfea78f296257330cda39aca", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: behind/conflicting + PR policy FAIL (missing Clinical Governance Preflight + RAG impact). after: merged origin/main cleanly; PR policy still FAIL \u2014 body edit forbidden this sweep (needs human to add Clinical Governance Preflight + RAG impact line); no unresolved review threads worked", + "outcome": "before: behind/conflicting + PR policy FAIL (missing Clinical Governance Preflight + RAG impact). after: merged origin/main cleanly; PR policy still FAIL — body edit forbidden this sweep (needs human to add Clinical Governance Preflight + RAG impact line); no unresolved review threads worked", "checks": "merge only; no provider-backed checks run" }, { @@ -19481,7 +19523,7 @@ "ref": "codex/audit-remediation-final (PR #1158)", "head": "78fab6be0c43cf5e92361315399d393ee7742f2e", "scope": "Run PR re-sync sweep", - "outcome": "Before: CONFLICTING. After: merged origin/main clean (no RAG conflict markers). NOTE: PR still intentionally adds deterministic broad_summary queryClass shortcut in src/lib/rag/rag.ts (+17) \u2014 RAG impact behaviour change, not dropped during merge.", + "outcome": "Before: CONFLICTING. After: merged origin/main clean (no RAG conflict markers). NOTE: PR still intentionally adds deterministic broad_summary queryClass shortcut in src/lib/rag/rag.ts (+17) — RAG impact behaviour change, not dropped during merge.", "checks": "merge origin/main and/or conflict re-check only; no provider-backed checks run" }, { @@ -19657,7 +19699,7 @@ "ref": "cursor/pr-babysit-bugbot-agents-6c52 (PR #1167)", "head": "6ec7a852", "scope": "Babysit sweep: CI fix + Codex/CodeRabbit threads", - "outcome": "Before: mergeable, PR required green, 8 unresolved agent-guidance threads. After: fixed pr-babysit/pr-bugbot agents (fetch origin/main, no Run PR live-gate auth, pin target head SHA, exact bot identity, ledger-after-every-sweep). Thread reply/resolve 403 on this token \u2014 fixes pushed.", + "outcome": "Before: mergeable, PR required green, 8 unresolved agent-guidance threads. After: fixed pr-babysit/pr-bugbot agents (fetch origin/main, no Run PR live-gate auth, pin target head SHA, exact bot identity, ledger-after-every-sweep). Thread reply/resolve 403 on this token — fixes pushed.", "checks": "typecheck on agent files; no provider-backed checks run" }, { @@ -19729,7 +19771,7 @@ "ref": "cursor/search-correctness-030-075-6273 (PR #1177)", "head": "54ab9f8498751ef7e96815dd2496b8137f29dad7", "scope": "Review + follow-up hardening of #030/#075 search-correctness fixes", - "outcome": "Findings fixed: (P2) one combo-titled source could still make multi-slot allHit true via substring alias hits \u2014 `expectedFileCoverage` now assigns each retrieved top-file to at most one expected slot; (P2) label pagination could loop forever on a stuck full-page API \u2014 fail-closed page budget added; (P2 process) stale `PR_POLICY_BODY.md` from search-performance leftover was overwriting this PR body via Sync PR policy body \u2014 corrected then deleted. No remaining high-confidence P0\u2013P1 in product scope. Residual: human approving review; Unit coverage CI still finishing on later heads. RAG impact: no retrieval behaviour change \u2014 eval matching / label pagination only.", + "outcome": "Findings fixed: (P2) one combo-titled source could still make multi-slot allHit true via substring alias hits — `expectedFileCoverage` now assigns each retrieved top-file to at most one expected slot; (P2) label pagination could loop forever on a stuck full-page API — fail-closed page budget added; (P2 process) stale `PR_POLICY_BODY.md` from search-performance leftover was overwriting this PR body via Sync PR policy body — corrected then deleted. No remaining high-confidence P0–P1 in product scope. Residual: human approving review; Unit coverage CI still finishing on later heads. RAG impact: no retrieval behaviour change — eval matching / label pagination only.", "checks": "Focused Vitest 32/32; `verify:cheap` green; `verify:pr-local` green (lint/typecheck/3326 unit/build/client-bundle/offline RAG fixtures 36/36). No OpenAI/live Supabase/provider-backed canary." }, { @@ -19769,7 +19811,7 @@ "ref": "cursor/search-interactive-perf-af54 (PR #1138 follow-up)", "head": "7e2ccee0", "scope": "Bugfix pass on search interactive performance diff", - "outcome": "Fixed P1 auth-stale differential matches; P2 progressive-reveal hiding selected card; P2 deferred empty/full-catalogue flash on services/forms/formulation/therapy-compass; Prettier CI failure on universal-search test. No remaining high-confidence P0\u2013P2 in scoped diff. Residual: differential debounce skeleton flicker; RelatedDocumentsPanel memo limited by unstable callbacks.", + "outcome": "Fixed P1 auth-stale differential matches; P2 progressive-reveal hiding selected card; P2 deferred empty/full-catalogue flash on services/forms/formulation/therapy-compass; Prettier CI failure on universal-search test. No remaining high-confidence P0–P2 in scoped diff. Residual: differential debounce skeleton flicker; RelatedDocumentsPanel memo limited by unstable callbacks.", "checks": "Focused Vitest 11/11; typecheck; format:check; maintainability budgets. No provider calls." }, { @@ -19785,7 +19827,7 @@ "ref": "cursor/search-interactive-perf-af54 (PR #1138)", "head": "46597a9b", "scope": "Explicit performance + frontend-ui review of search/interactive surfaces; low-risk client deferral/cache/abort/progressive-reveal pass", - "outcome": "Prior document/universal search latency work retained (NDJSON stream, LRU, lazy PDF, content-first detail). New work: differential debounce+abort+LRU; useDeferredValue on catalogue ranking; document results Show more window; RelatedDocumentsPanel memo; universal LRU 100+TTL; deferred registry search extracted from ClinicalDashboard. No RAG/retrieval/ranking edits. No high-confidence P0\u2013P2 defect found in the shipped scope; residual risk = deferred paint lag on large catalogues and progressive reveal missing deep cards until Show more.", + "outcome": "Prior document/universal search latency work retained (NDJSON stream, LRU, lazy PDF, content-first detail). New work: differential debounce+abort+LRU; useDeferredValue on catalogue ranking; document results Show more window; RelatedDocumentsPanel memo; universal LRU 100+TTL; deferred registry search extracted from ClinicalDashboard. No RAG/retrieval/ranking edits. No high-confidence P0–P2 defect found in the shipped scope; residual risk = deferred paint lag on large catalogues and progressive reveal missing deep cards until Show more.", "checks": "Focused Vitest 10/10 (differential + universal + performance boundaries); verify:cheap exit 0 (3262 tests); typecheck clean; verify:ui exit 0 (Chromium). No provider calls." }, { @@ -19793,7 +19835,7 @@ "ref": "cursor/search-interactive-perf-af54 (PR #1138)", "head": "ff4b293d95f922e70ebf5ee9b0c156c41a8bff3b", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "Before: CONFLICTING, CI green, 0 threads. RAG impact: no retrieval behaviour change \u2014 PR is client deferred-search/UI only (no src/lib/rag/**). After: merged origin/main; conflict resolved in src/components/ui/sheet.tsx by keeping main restoreTimersRef/unmountingRef focus-restore fix; pushed ff4b293d9. Threads: none.", + "outcome": "Before: CONFLICTING, CI green, 0 threads. RAG impact: no retrieval behaviour change — PR is client deferred-search/UI only (no src/lib/rag/**). After: merged origin/main; conflict resolved in src/components/ui/sheet.tsx by keeping main restoreTimersRef/unmountingRef focus-restore fix; pushed ff4b293d9. Threads: none.", "checks": "merge origin/main only; no provider-backed checks run" }, { @@ -19825,7 +19867,7 @@ "ref": "execute-audit-code-remediation (PR #1162)", "head": "632e84c9436f1f28be9d7aaadbbe942f72618199", "scope": "Run PR sweep: CI fix + threads + drift", - "outcome": "before: CONFLICTING + PR policy FAIL + unresolved Codex P1 (conflict markers in answer/route.ts). after: conflict markers removed and pushed (80212dd91, 632e84c94); merge origin/main aborted (non-trivial conflicts: privacy/page.tsx, answer-render-policy.ts, source-authority-metadata.ts, upload/route.ts, supabase/drift-manifest.json, settings-dialog, validation/answer-request, plus UI/docs/tests); PR policy still FAIL (Clinical Governance Preflight missing \u2014 body edit forbidden this sweep); thread reply/resolve needs parent (comment 3644028277 / thread PRRT_kwDOSh5Fis6Tfkev) \u2014 ManagePullRequest/GitHub write MCP unavailable", + "outcome": "before: CONFLICTING + PR policy FAIL + unresolved Codex P1 (conflict markers in answer/route.ts). after: conflict markers removed and pushed (80212dd91, 632e84c94); merge origin/main aborted (non-trivial conflicts: privacy/page.tsx, answer-render-policy.ts, source-authority-metadata.ts, upload/route.ts, supabase/drift-manifest.json, settings-dialog, validation/answer-request, plus UI/docs/tests); PR policy still FAIL (Clinical Governance Preflight missing — body edit forbidden this sweep); thread reply/resolve needs parent (comment 3644028277 / thread PRRT_kwDOSh5Fis6Tfkev) — ManagePullRequest/GitHub write MCP unavailable", "checks": "typecheck:internal pass; vitest clinical-dashboard-merge-artifacts + visual-evidence-tabs pass (9); no provider-backed checks run" }, { @@ -19849,7 +19891,7 @@ "ref": "execute-audit-code-remediation (PR #1162)", "head": "b4675d7b", "scope": "Babysit sweep: drift skipped", - "outcome": "Before: CONFLICTING, PR policy FAIL. Merge origin/main aborted: 20+ conflict files across clinical/auth/API surfaces \u2014 needs human resolution.", + "outcome": "Before: CONFLICTING, PR policy FAIL. Merge origin/main aborted: 20+ conflict files across clinical/auth/API surfaces — needs human resolution.", "checks": "merge --abort; no provider-backed checks run" }, { @@ -19985,7 +20027,7 @@ "ref": "PR #1125 / `codex/answer-relevance-fail-closed`", "head": "8d9fb2408f13e305138749655214baa0020fcfd4", "scope": "Follow-up: clear comparison/`documentBreakdown` in untrusted clinical notes", - "outcome": "APPROVE for the scoped P2. `trustGatedAnswerForClinicalNotes` now clears `documentBreakdown`, `comparisonMatrix`, and `comparisonEvaluationState` when relevance is not source-backed, so Clinical Notes \u2192 ClinicalOutputPanel cannot rebuild comparison-detail tables from raw `best_quote` values. Prior visual/section/quote gates remain. Residual risk is still deliberate low-trust rendering for legacy payloads without `isSourceBacked: true`.", + "outcome": "APPROVE for the scoped P2. `trustGatedAnswerForClinicalNotes` now clears `documentBreakdown`, `comparisonMatrix`, and `comparisonEvaluationState` when relevance is not source-backed, so Clinical Notes → ClinicalOutputPanel cannot rebuild comparison-detail tables from raw `best_quote` values. Prior visual/section/quote gates remain. Residual risk is still deliberate low-trust rendering for legacy payloads without `isSourceBacked: true`.", "checks": "Focused jsdom/policy regressions: `tests/visual-evidence-tabs.dom.test.tsx` 5/5 after hardening the comparison case (caption + matrix values absent). Thread disposition posted and resolved. No live RAG/OpenAI/Supabase mutation." }, { @@ -20009,7 +20051,7 @@ "ref": "PR #1135 / `cursor/sitewide-design-ux-review-6176`", "head": "merge origin/main @ 3d6954a3", "scope": "babysit: re-merge main after #1133; renumber UX archive IDs", - "outcome": "CONFLICTING after `main` advanced with database-interface audit. Kept product UX fixes; rebuilt `docs/outstanding-issues.md` from `origin/main` and archived sitewide UX defects as collision-free `#070`\u2013`#074` (provisional PR IDs `#068`\u2013`#072` collided with main `#068` drift-manifest / `#069` table-facts profile). Native-`disabled` CodeRabbit ask remains declined (focusable coming-soon contract).", + "outcome": "CONFLICTING after `main` advanced with database-interface audit. Kept product UX fixes; rebuilt `docs/outstanding-issues.md` from `origin/main` and archived sitewide UX defects as collision-free `#070`–`#074` (provisional PR IDs `#068`–`#072` collided with main `#068` drift-manifest / `#069` table-facts profile). Native-`disabled` CodeRabbit ask remains declined (focusable coming-soon contract).", "checks": "Local merge conflict resolution only; hosted CI pending on merge commit. No provider-backed gates." }, { @@ -20065,7 +20107,7 @@ "ref": "PR #1175 / `cursor/ledger-009-010-032-041-063-519b`", "head": "f3986abc39468e077643611ec2d95e374c2e901f", "scope": "PR review + CI fix (ledger docs #009/#010/#032/#041/#063)", - "outcome": "FINDINGS FIXED. P1: Static PR checks failed on Prettier (5 docs). P1: leftover `PR_POLICY_BODY.md` from merged #1134 caused Sync PR policy body to overwrite this docs PR description with search-performance text \u2014 deleted the stale template. No P0. Product scope remains docs-only; gated brief follow-ups (wire coming-soon, Current Clinical Work storage, Factsheets second mode, governance ranking) correctly not implemented. Residual: human approving review once CI green.", + "outcome": "FINDINGS FIXED. P1: Static PR checks failed on Prettier (5 docs). P1: leftover `PR_POLICY_BODY.md` from merged #1134 caused Sync PR policy body to overwrite this docs PR description with search-performance text — deleted the stale template. No P0. Product scope remains docs-only; gated brief follow-ups (wire coming-soon, Current Clinical Work storage, Factsheets second mode, governance ranking) correctly not implemented. Residual: human approving review once CI green.", "checks": "Local: prettier --check on touched docs; ledger open/resolved/queue integrity for five IDs; no client fetch(`/api/jobs`); `verify:cheap` earlier on tip 95d68c6b. No OpenAI/Supabase writes." }, { @@ -20134,10 +20176,10 @@ }, { "date": "2026-07-24", - "ref": "repo-auditor (detached HEAD 037b4808 \u2014 explicit full-repo structural audit)", + "ref": "repo-auditor (detached HEAD 037b4808 — explicit full-repo structural audit)", "head": "037b4808100946f96aee28b8ff51939ae2986851", - "scope": "Full-repo structural audit: broken imports, dead files, consolidation. Scope: src/, scripts/, worker/, tests/. Pure triage \u2014 no files mutated.", - "outcome": "P0/P1: none. P2: confirmed dead file src/components/clinical-dashboard/prior-answer-turn-surface.tsx (115 lines, zero importers; superseded by answer-thread-turn.tsx per its 'Extracted from ClinicalDashboard.tsx maturity X3' comment; old file exports PriorAnswerTurn type + PriorAnswerTurnSurface component \u2014 both replaced). P3: three duplicate package.json script pairs (test:e2e = test:e2e:all; promote:public-documents = promote:public-documents:batch; postinstall = hooks:install \u2014 last pair intentional lifecycle). Unused public exports: authorization.ts (administratorRoleClaim/Value internal-only), api-client-error.ts (ApiClientError \u2014 only parseApiErrorResponse imported), rag/rag.ts (answerQuestion \u2014 superseded by answerQuestionWithScope), supabase/project.ts (isExpectedSupabaseProjectConfig + 2 types). RAG surface note only (do not touch): rag-extractive-first.ts exports hasValidatedRoutineExtractiveRecovery/hasValidatedGenericLaiManagementExtractiveAnswer with no external consumers. Knip false positives: taskkill (win32-gated), railway (opt-in --railway flag). No broken imports (typecheck + lint both exit 0, zero relative ../ imports in src/).", + "scope": "Full-repo structural audit: broken imports, dead files, consolidation. Scope: src/, scripts/, worker/, tests/. Pure triage — no files mutated.", + "outcome": "P0/P1: none. P2: confirmed dead file src/components/clinical-dashboard/prior-answer-turn-surface.tsx (115 lines, zero importers; superseded by answer-thread-turn.tsx per its 'Extracted from ClinicalDashboard.tsx maturity X3' comment; old file exports PriorAnswerTurn type + PriorAnswerTurnSurface component — both replaced). P3: three duplicate package.json script pairs (test:e2e = test:e2e:all; promote:public-documents = promote:public-documents:batch; postinstall = hooks:install — last pair intentional lifecycle). Unused public exports: authorization.ts (administratorRoleClaim/Value internal-only), api-client-error.ts (ApiClientError — only parseApiErrorResponse imported), rag/rag.ts (answerQuestion — superseded by answerQuestionWithScope), supabase/project.ts (isExpectedSupabaseProjectConfig + 2 types). RAG surface note only (do not touch): rag-extractive-first.ts exports hasValidatedRoutineExtractiveRecovery/hasValidatedGenericLaiManagementExtractiveAnswer with no external consumers. Knip false positives: taskkill (win32-gated), railway (opt-in --railway flag). No broken imports (typecheck + lint both exit 0, zero relative ../ imports in src/).", "checks": "npm run typecheck (exit 0); npm run lint (exit 0); npm run check:knip (exit 0); knip --reporter json full export/file/type analysis; rg import-graph probes across all source trees" }, { @@ -20281,31 +20323,31 @@ "ref": "PR #1087 / `codex/reconcile-product-truth`", "head": "edbc2260fef59ca2fa7c6973dffb85e32354bce1 (merged as 05dc52fd8408a65117e22a6236e43252203bea92)", "scope": "Product-truth copy, account persistence and unavailable-SSO presentation", - "outcome": "MERGED. Cross-device claims now match favourites/preferences persistence; recent searches are identified as browser-session data; the contradictory \u201cnever shared\u201d statement is removed. All unavailable setup providers and Apple elsewhere use the connected accessible \u201ccoming soon\u201d placeholder pattern. The single review finding was fixed, replied to and resolved.", + "outcome": "MERGED. Cross-device claims now match favourites/preferences persistence; recent searches are identified as browser-session data; the contradictory “never shared” statement is removed. All unavailable setup providers and Apple elsewhere use the connected accessible “coming soon” placeholder pattern. The single review finding was fixed, replied to and resolved.", "checks": "Red DOM proof; focused 19/19; `verify:cheap` 3,220 passed / 1 skipped; `verify:ui` 265/265; PR-local build/secret scan/offline RAG; final hosted required, Production UI, policy and security checks green. No provider calls or RAG spend." }, { "date": "2026-07-21", - "ref": "claude/clinical-kb-pwa-review-asi3wb (E-4 pair verdict \u2014 no code change; #1039 merged as 9b655fa)", + "ref": "claude/clinical-kb-pwa-review-asi3wb (E-4 pair verdict — no code change; #1039 merged as 9b655fa)", "head": "canary run 29800029819 (#60, main 9b655fa = E-3b+PR-B+PR-C)", "scope": "(recorded with Outcome)", - "outcome": "PHASE E-3 WAVE CLOSED \u2014 E-4 VERDICT: ADOPT (no revert). 44-case: the ONLY blocking red is the KNOWN persisting neuroleptic citation case (0.0227, identical #57 signature: generation quality-failed \u2192 extractive fallback 1 citation \u2014 the pre-declared Option A carve-out, retrieval-side, untouched by answer waves); route_ceiling_failures 0 CONFIRMED ON MAIN (E-3b: agitation 23.1s < 25s after 20.3s provider timeout; clozapine 14.5s with exactly one retrieval-exhausted audit cell); grounded 1.0 / unsupported_correct 1.0 / numeric 0 / governance-danger 0 all held; expected_source_hit 0.6136\u21920.6364 (#1020 widen); generation attempts 19\u21929 across 44 cases (10+ cases short-circuit via validated_routine_extractive_first at 2-6s, zero generation spend \u2014 the absolute wasted-generation seconds collapse; residual 6 discarded attempts are the named E-3d H2 strong/comparison slice). Targeting vs #58 baseline: rate 0.5909\u21920.6667, dose 1/5\u21922/4 (sertraline + quetiapine still miss), document_lookup 5/5\u21926/6, contraindication 2/2, red_result 2/2, pathway 1/2; readability/artifact_leaks 1.0. NOT met: monitoring_schedule flat 1/5 \u2014 per-miss lens shows answers of 73-232 chars with NO schedule token available to promote (olanzapine-lai 79ch, metabolic 73ch = single-fact extractive answers; the PR-C promotion is a no-op when no figure-bearing fact is extracted) \u2192 root is fact-extraction/retrieval depth on monitoring shapes, queued as the Option-A-wave companion diagnosis (dump artifact 8483731630, 30d retention). WATCH escalated: relevance 0.6 (#58) \u2192 0.5667 (#59) \u2192 0.5333 (#60) \u2014 two single-case steps coinciding with more terse extractive answers; fail_closed 0.9 = exactly the #58 main baseline (#59's 0.9333 was the outlier), safety texture flat. Adoption per plan criteria: targeting \u2265 baseline \u2713, grounded/refusal 1.0 \u2713, golden 36/36 \u2713 (in-run), ceilings 0 \u2713, citation red = carved known case \u2713. CodeRabbit post-review follow-up landed pre-merge (02b5c78): interval-regex full-match reorder (atom path proven to intercept the claimed exploit; reorder = drift hardening), clinicalValueAtomKey exported (mirror deleted), guard tests made honestly discriminating + genuine zero-atom \"annually\" coverage both directions. Instrument note: cost rates live on the targeting step env but eval:quality still reports cost n/a (estimator not consuming them in the 44-case path) \u2014 minor tooling residual. Spend +~$2-4 \u2192 Phase E total ~$8-16 of \u2264$20.", - "checks": "Evidence: run #60 job log read in full (Threshold Status: citation-only; Answer Metrics + 44-row diagnostics; targeting metric_rates + 7-miss list); artifact eval-canary-output 8483731630 sha256 d5c7006e\u2026 (download blocked in-session \u2014 GitHub App scope; log tee carried the targeting output)" + "outcome": "PHASE E-3 WAVE CLOSED — E-4 VERDICT: ADOPT (no revert). 44-case: the ONLY blocking red is the KNOWN persisting neuroleptic citation case (0.0227, identical #57 signature: generation quality-failed → extractive fallback 1 citation — the pre-declared Option A carve-out, retrieval-side, untouched by answer waves); route_ceiling_failures 0 CONFIRMED ON MAIN (E-3b: agitation 23.1s < 25s after 20.3s provider timeout; clozapine 14.5s with exactly one retrieval-exhausted audit cell); grounded 1.0 / unsupported_correct 1.0 / numeric 0 / governance-danger 0 all held; expected_source_hit 0.6136→0.6364 (#1020 widen); generation attempts 19→9 across 44 cases (10+ cases short-circuit via validated_routine_extractive_first at 2-6s, zero generation spend — the absolute wasted-generation seconds collapse; residual 6 discarded attempts are the named E-3d H2 strong/comparison slice). Targeting vs #58 baseline: rate 0.5909→0.6667, dose 1/5→2/4 (sertraline + quetiapine still miss), document_lookup 5/5→6/6, contraindication 2/2, red_result 2/2, pathway 1/2; readability/artifact_leaks 1.0. NOT met: monitoring_schedule flat 1/5 — per-miss lens shows answers of 73-232 chars with NO schedule token available to promote (olanzapine-lai 79ch, metabolic 73ch = single-fact extractive answers; the PR-C promotion is a no-op when no figure-bearing fact is extracted) → root is fact-extraction/retrieval depth on monitoring shapes, queued as the Option-A-wave companion diagnosis (dump artifact 8483731630, 30d retention). WATCH escalated: relevance 0.6 (#58) → 0.5667 (#59) → 0.5333 (#60) — two single-case steps coinciding with more terse extractive answers; fail_closed 0.9 = exactly the #58 main baseline (#59's 0.9333 was the outlier), safety texture flat. Adoption per plan criteria: targeting ≥ baseline ✓, grounded/refusal 1.0 ✓, golden 36/36 ✓ (in-run), ceilings 0 ✓, citation red = carved known case ✓. CodeRabbit post-review follow-up landed pre-merge (02b5c78): interval-regex full-match reorder (atom path proven to intercept the claimed exploit; reorder = drift hardening), clinicalValueAtomKey exported (mirror deleted), guard tests made honestly discriminating + genuine zero-atom \"annually\" coverage both directions. Instrument note: cost rates live on the targeting step env but eval:quality still reports cost n/a (estimator not consuming them in the 44-case path) — minor tooling residual. Spend +~$2-4 → Phase E total ~$8-16 of ≤$20.", + "checks": "Evidence: run #60 job log read in full (Threshold Status: citation-only; Answer Metrics + 44-row diagnostics; targeting metric_rates + 7-miss list); artifact eval-canary-output 8483731630 sha256 d5c7006e… (download blocked in-session — GitHub App scope; log tee carried the targeting output)" }, { "date": "2026-07-21", "ref": "claude/clinical-kb-pwa-review-asi3wb (Option A rescue review)", "head": "0abf3c9", "scope": "(recorded with Outcome)", - "outcome": "clinical-governance-reviewer on the S3 escalation rescue: APPROVE-WITH-NITS, no P0/P1. P2 = the mandated live canary pair itself (process gate, declared in the PR body; offline-green + review-approved proven insufficient for this surface 2026-07-20). P3s: multi-drug escalation-query recall edge (titled drug + untitled drug \u2014 fast-path return can skip the vector leg; recall limitation, not misattribution, mirrors the pre-existing allowlisted-class tradeoff); reviewer probe files must stay uncommitted (relocated to scratchpad). All six clinical concerns verified safe: wrong-document impossible (alias phrases must appear in the query; per-document alias groups, no cross-drug conflation), conservative availability (S3 purely additive via keyed-union merge; sibling retention test-pinned), live expansion acceptable (title-named correct-entity SOP in every firing shape), fail-closed double layer (adversarial short-circuit precedes the predicate; injection-forge case intent=protocol cannot fire \u2014 executed), governance metadata unbypassed (same attachDocumentRankingMetadata + status=indexed + access-scope filters), no PHI/provider/schema surface.", + "outcome": "clinical-governance-reviewer on the S3 escalation rescue: APPROVE-WITH-NITS, no P0/P1. P2 = the mandated live canary pair itself (process gate, declared in the PR body; offline-green + review-approved proven insufficient for this surface 2026-07-20). P3s: multi-drug escalation-query recall edge (titled drug + untitled drug — fast-path return can skip the vector leg; recall limitation, not misattribution, mirrors the pre-existing allowlisted-class tradeoff); reviewer probe files must stay uncommitted (relocated to scratchpad). All six clinical concerns verified safe: wrong-document impossible (alias phrases must appear in the query; per-document alias groups, no cross-drug conflation), conservative availability (S3 purely additive via keyed-union merge; sibling retention test-pinned), live expansion acceptable (title-named correct-entity SOP in every firing shape), fail-closed double layer (adversarial short-circuit precedes the predicate; injection-forge case intent=protocol cannot fire — executed), governance metadata unbypassed (same attachDocumentRankingMetadata + status=indexed + access-scope filters), no PHI/provider/schema surface.", "checks": "Reviewer checks: escalation-rescue suite 8/8, injection-forge intent derivation executed, static trace of the full S3 chain. Live canary pair = the trust gate, dispatched post-merge." }, { "date": "2026-07-21", - "ref": "claude/clinical-kb-pwa-review-asi3wb (Option A wave verdict \u2014 no code change; #1040 merged as cde6c5c)", + "ref": "claude/clinical-kb-pwa-review-asi3wb (Option A wave verdict — no code change; #1040 merged as cde6c5c)", "head": "canary run 29827012719 (#61, main cde6c5c) vs banked #60 (29800029819)", "scope": "(recorded with Outcome)", - "outcome": "OPTION A WAVE ADOPTED \u2014 FIRST FULLY-GREEN 44-CASE CANARY IN PROGRAM HISTORY (Blocking failures: None). (1) Option A payoff EXCEEDED: citation_failure_rate 0.0227\u21920; the neuroleptic-side-effect-escalation case flipped from wrong-doc\u2192failed-generation\u21921-citation-fallback to **strong route, successful gpt-5.6-sol generation, passed in 15.4s with no fallback marker** \u2014 the rescued S3 retrieval fixed generation itself, not just the citation count; expected_source_hit 0.6364\u21920.6591. (2) Golden held exactly as the blast-radius analysis promised: 36/36 PASS, content_recall 1.0, mrr@10 0.8921 BYTE-IDENTICAL to the pre-wave baseline (zero ordering movement \u2014 no golden case fires the predicate), irrelevant@10 0.1083\u21920.0917 (slightly better). (3) Parity payoff PARTIAL: monitoring targeting 1/5\u21922/5 (olanzapine-lai flipped \u2014 previously called a retrieval-depth residual; quetiapine-dose also flipped on the dose side); lithium-range (232ch) + metabolic (73ch, byte-identical answer to #60) did NOT flip despite offline-proven fixes \u2014 their live chunk sets evidently contain no admissible schedule sentence even under the widened gate \u2192 reclassified as retrieval-depth/live-content residuals joining adhd; below the \u22653/5 target but strictly improved, no regression anywhere. Dose 2/5 vs 2/4: same passing count, applicable set grew (new quality-metformin-renal-dosing miss = eval-set churn, not regression). (4) No-worse EXCEEDED: relevance 0.5333\u21920.6 (the two-step watch-item slide FULLY REVERSED to the #58 level), targeting_rate 0.6667\u21920.6957, fail_closed 0.9 held, readability/artifact_leaks 1.0, route ceilings 0, grounded 1.0, unsupported_correct 1.0, numeric 0, p95 22.8s, red_result 3/3. Adoption per the measured-gain rule: primary goal achieved, three case flips, relevance recovered, zero regressions. Residual queue: monitoring retrieval-depth trio (lithium-range/metabolic/adhd), E-3d H2 discards, weekly ANSWER_CASE_LIMIT 8\u219244 raise now unblocked (gate would be green), comparison-class coverage. Wave spend +~$2-4 \u2192 Phase E + Option A total ~$12-20 of \u2264$20.", + "outcome": "OPTION A WAVE ADOPTED — FIRST FULLY-GREEN 44-CASE CANARY IN PROGRAM HISTORY (Blocking failures: None). (1) Option A payoff EXCEEDED: citation_failure_rate 0.0227→0; the neuroleptic-side-effect-escalation case flipped from wrong-doc→failed-generation→1-citation-fallback to **strong route, successful gpt-5.6-sol generation, passed in 15.4s with no fallback marker** — the rescued S3 retrieval fixed generation itself, not just the citation count; expected_source_hit 0.6364→0.6591. (2) Golden held exactly as the blast-radius analysis promised: 36/36 PASS, content_recall 1.0, mrr@10 0.8921 BYTE-IDENTICAL to the pre-wave baseline (zero ordering movement — no golden case fires the predicate), irrelevant@10 0.1083→0.0917 (slightly better). (3) Parity payoff PARTIAL: monitoring targeting 1/5→2/5 (olanzapine-lai flipped — previously called a retrieval-depth residual; quetiapine-dose also flipped on the dose side); lithium-range (232ch) + metabolic (73ch, byte-identical answer to #60) did NOT flip despite offline-proven fixes — their live chunk sets evidently contain no admissible schedule sentence even under the widened gate → reclassified as retrieval-depth/live-content residuals joining adhd; below the ≥3/5 target but strictly improved, no regression anywhere. Dose 2/5 vs 2/4: same passing count, applicable set grew (new quality-metformin-renal-dosing miss = eval-set churn, not regression). (4) No-worse EXCEEDED: relevance 0.5333→0.6 (the two-step watch-item slide FULLY REVERSED to the #58 level), targeting_rate 0.6667→0.6957, fail_closed 0.9 held, readability/artifact_leaks 1.0, route ceilings 0, grounded 1.0, unsupported_correct 1.0, numeric 0, p95 22.8s, red_result 3/3. Adoption per the measured-gain rule: primary goal achieved, three case flips, relevance recovered, zero regressions. Residual queue: monitoring retrieval-depth trio (lithium-range/metabolic/adhd), E-3d H2 discards, weekly ANSWER_CASE_LIMIT 8→44 raise now unblocked (gate would be green), comparison-class coverage. Wave spend +~$2-4 → Phase E + Option A total ~$12-20 of ≤$20.", "checks": "Evidence: run #61 job log read (Threshold Status: None; Answer Metrics; neuroleptic diagnostics row; targeting metric_rates + 6-miss list; golden 36 PASS lines + summary). Revert drill NOT triggered." }, { @@ -20313,15 +20355,15 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (Option A: title-supported escalation rescue)", "head": "0abf3c9 (parent 1aebf02)", "scope": "rag-retrieval-reviewer PROTECTED-surface review of the S3 document-lookup escalation rescue: shouldAttemptDocumentLookupFastPath exported + gains medication_dose_risk branch firing ONLY when analysis.intent===\"escalation_risk\" && documentTitleTerms.length>0; call site passes queryAnalysis; new tests/rag-document-lookup-escalation-rescue.test.ts.", - "outcome": "APPROVE-WITH-NITS. No P0/P1/P2. Binding constraints held: released-search-order.ts + retrieval-selection.ts clamp + rag-candidate-sources.ts imputation all byte-identical to parent (git diff empty); imputation-contract test green; 0.66/0.055 floor (rag.ts:1765) unmodified and still gates rescued pools (S3 block sits after the 2513 fast-path return + re-runs decideTextFastPath at 2631). BLAST RADIUS empirically proven via 110-case offline probe (44 ragEvalCases + 30 answerQualityEvalCases + 36 golden): EXACTLY 1 fires (neuroleptic-side-effect-escalation, intent=escalation_risk tt=3); all 8 named dose cases non-firing (clozapine-monitoring general, paraphrase general, agitation-pharm general, im-po drug_dosing, typo-dosing drug_dosing, missed-dose-table drug_dosing, LAI general/tt0, prompt-injection-forge intent=protocol). intentFromSignals precedence (clinical-search.ts:575-585) returns drug_dosing before escalation_risk so pure-dose structurally cannot fire \u2014 confirmed by construction AND empirically. ADVERSARIAL: prompt-injection-forge intent=protocol => cannot fire (empirical); unsupported short-circuit (rag.ts:2371) precedes S3 block. DOWNSTREAM: buildRetrievalIntent for the escalation query yields EMPTY requiredTermSignals => demote/promote arms (retrieval-selection.ts:354-355/529/555) + wrong-medication cap (rag.ts:730-737, gated on clinical_subject) all inert; end-to-end test proves neuroleptic-doc rank#1 with >=2 citations, sibling retained, arrival-order invariant. golden vector-\\* probes = broad_summary (already allowlisted) => predicate byte-identical => unaffected. TEST HONESTY: S3 fixture (0.92/0.34/0.94/synthetic_text) faithful to searchDocumentLookupFastPath (rag-candidate-sources.ts:570 caps alias documentScore at 0.34 => sim=min(0.92,0.58+0.34+bonus)=0.92, hybrid=min(0.94,0.94)); differently-relevant fixtures (not identical-content); red-proof structurally airtight (e2e gates its own fixture pool on the predicate). EFFORT: one S3 RPC (same call allowlisted classes issue), rescue-only in the non-forceEmbedding path (floor already rejected => query was headed to embedding anyway; successful rescue short-circuits at 2646 pre-embedding = net-neutral/positive). NITS (P3, non-blocking, no code change pre-canary): (1) redundant analysis?. on the documentTitleTerms clause (&& short-circuit already guarantees analysis defined there); (2) a queryMode forcing medication_dose_risk over an originally-escalation-shaped table_threshold could newly fire S3, but table_threshold already ran S3 so behavior-consistent, not a regression; (3) \"forceEmbedding discards S3 merges\" is imprecise \u2014 line 2649 merges S3 even under forceEmbedding; the accurate unaffected-reason for vector-\\* probes is broad_summary allowlisting. TRUST GATE = the mandated live canary pair (correctly deferred by the commit).", + "outcome": "APPROVE-WITH-NITS. No P0/P1/P2. Binding constraints held: released-search-order.ts + retrieval-selection.ts clamp + rag-candidate-sources.ts imputation all byte-identical to parent (git diff empty); imputation-contract test green; 0.66/0.055 floor (rag.ts:1765) unmodified and still gates rescued pools (S3 block sits after the 2513 fast-path return + re-runs decideTextFastPath at 2631). BLAST RADIUS empirically proven via 110-case offline probe (44 ragEvalCases + 30 answerQualityEvalCases + 36 golden): EXACTLY 1 fires (neuroleptic-side-effect-escalation, intent=escalation_risk tt=3); all 8 named dose cases non-firing (clozapine-monitoring general, paraphrase general, agitation-pharm general, im-po drug_dosing, typo-dosing drug_dosing, missed-dose-table drug_dosing, LAI general/tt0, prompt-injection-forge intent=protocol). intentFromSignals precedence (clinical-search.ts:575-585) returns drug_dosing before escalation_risk so pure-dose structurally cannot fire — confirmed by construction AND empirically. ADVERSARIAL: prompt-injection-forge intent=protocol => cannot fire (empirical); unsupported short-circuit (rag.ts:2371) precedes S3 block. DOWNSTREAM: buildRetrievalIntent for the escalation query yields EMPTY requiredTermSignals => demote/promote arms (retrieval-selection.ts:354-355/529/555) + wrong-medication cap (rag.ts:730-737, gated on clinical_subject) all inert; end-to-end test proves neuroleptic-doc rank#1 with >=2 citations, sibling retained, arrival-order invariant. golden vector-\\* probes = broad_summary (already allowlisted) => predicate byte-identical => unaffected. TEST HONESTY: S3 fixture (0.92/0.34/0.94/synthetic_text) faithful to searchDocumentLookupFastPath (rag-candidate-sources.ts:570 caps alias documentScore at 0.34 => sim=min(0.92,0.58+0.34+bonus)=0.92, hybrid=min(0.94,0.94)); differently-relevant fixtures (not identical-content); red-proof structurally airtight (e2e gates its own fixture pool on the predicate). EFFORT: one S3 RPC (same call allowlisted classes issue), rescue-only in the non-forceEmbedding path (floor already rejected => query was headed to embedding anyway; successful rescue short-circuits at 2646 pre-embedding = net-neutral/positive). NITS (P3, non-blocking, no code change pre-canary): (1) redundant analysis?. on the documentTitleTerms clause (&& short-circuit already guarantees analysis defined there); (2) a queryMode forcing medication_dose_risk over an originally-escalation-shaped table_threshold could newly fire S3, but table_threshold already ran S3 so behavior-consistent, not a regression; (3) \"forceEmbedding discards S3 merges\" is imprecise — line 2649 merges S3 even under forceEmbedding; the accurate unaffected-reason for vector-\\* probes is broad_summary allowlisting. TRUST GATE = the mandated live canary pair (correctly deferred by the commit).", "checks": "Offline only, no provider calls: new test 10/10 + imputation-contract 2/2; protected-surface batch 31/31 (escalation-rescue + imputation-contract + fast-path-ordering + released-search-order + retrieval-selection); 110-case classifier probe (temp test, removed); npm run typecheck exit 0. Not run (provider-gated): eval:retrieval:quality, eval:rag, the live canary pair." }, { "date": "2026-07-21", - "ref": "claude/clinical-kb-pwa-review-asi3wb (pair verdict \u2014 no code change; main stays at 22b6a2e)", + "ref": "claude/clinical-kb-pwa-review-asi3wb (pair verdict — no code change; main stays at 22b6a2e)", "head": "canary run 29794759627 (#59, branch head 7310cb3 = merged PR-B content)", "scope": "(recorded with Outcome)", - "outcome": "E-3b + E-3c PR-B LIVE-VALIDATED (pair vs banked #57/#58): route_ceiling_failures 2\u21920 (E-3b proven: agitation timeout now fits inside budget; clozapine retrieval-exhausted ceiling honestly excused via the triple-condition cross-region carve-out \u2014 exactly one \"retrieval-exhausted\" audit cell in the report); p95 17.4s\u219215.47s (-11%); golden retrieval SUCCESS 36/36 (stop-ship criterion held); validated_routine_extractive_first fired on 4 of the 6 target cases (patient-safety-plan 3.3s, treatment-team-process 2.6s, ect-procedure 2.2s, illegal-substances 2.2s \u2014 all pure extractive, zero generation, was 6-9s each with a discarded attempt), the other 2 (community-home-visits, best-practice-prescribing) stayed on generation+fallback because their extractive candidates legitimately fail validation gates = the designed-conservative outcome; ZERO new failing cases (list 5\u21922, both known residuals: neuroleptic citation red = Option A territory, admission-comparison expected-doc = non-blocking labeling residual); grounded 1.0 + unsupported_correct 1.0 held; targeting 0.5909\u21920.619, fail_closed 0.9\u21920.9333, readability/artifact_leaks/intent_coverage unchanged; relevance 0.6\u21920.5667 = single-case wobble on n=30, WATCH in E-4, not a gate. Discarded-generation rate materially down (4 conversions; residual = the H2 strong-route slice named as E-3d candidate, per design's 20-33% expectation band). MERGE STANDS (user had armed auto-merge pre-verdict; revert drill not triggered). Spend +~$3-6 \u2192 Phase E total ~$6-12 of \u2264$20.", + "outcome": "E-3b + E-3c PR-B LIVE-VALIDATED (pair vs banked #57/#58): route_ceiling_failures 2→0 (E-3b proven: agitation timeout now fits inside budget; clozapine retrieval-exhausted ceiling honestly excused via the triple-condition cross-region carve-out — exactly one \"retrieval-exhausted\" audit cell in the report); p95 17.4s→15.47s (-11%); golden retrieval SUCCESS 36/36 (stop-ship criterion held); validated_routine_extractive_first fired on 4 of the 6 target cases (patient-safety-plan 3.3s, treatment-team-process 2.6s, ect-procedure 2.2s, illegal-substances 2.2s — all pure extractive, zero generation, was 6-9s each with a discarded attempt), the other 2 (community-home-visits, best-practice-prescribing) stayed on generation+fallback because their extractive candidates legitimately fail validation gates = the designed-conservative outcome; ZERO new failing cases (list 5→2, both known residuals: neuroleptic citation red = Option A territory, admission-comparison expected-doc = non-blocking labeling residual); grounded 1.0 + unsupported_correct 1.0 held; targeting 0.5909→0.619, fail_closed 0.9→0.9333, readability/artifact_leaks/intent_coverage unchanged; relevance 0.6→0.5667 = single-case wobble on n=30, WATCH in E-4, not a gate. Discarded-generation rate materially down (4 conversions; residual = the H2 strong-route slice named as E-3d candidate, per design's 20-33% expectation band). MERGE STANDS (user had armed auto-merge pre-verdict; revert drill not triggered). Spend +~$3-6 → Phase E total ~$6-12 of ≤$20.", "checks": "Pair evidence: run #59 job log (Blocking failures = citation only; Answer Case Diagnostics markers; metric_rates + targeting blocks); dump artifact populated for PR-C diagnosis" }, { @@ -20329,23 +20371,23 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (parity commit review)", "head": "1aebf02 (fix landed a3b9a54)", "scope": "(recorded with Outcome)", - "outcome": "rag-retrieval-reviewer on the monitoring evidence-gate parity commit: REQUEST-CHANGES (soft) \u2014 P2 reproduced: inflected monitoring kind tokens (monitor\\w*/annual(?:ly)?/blood tests?/ecgs?/lfts?) steal sole-dose-value sentences from the dose arm; dose-intent answers then reject the monitoring-kind fact (\"Quetiapine is monitored at a dose of 200 mg daily\" flipped grounded true\u2192false, source-gap \u2014 fails CLOSED, never a wrong dose). P3: monitoring figure escape lacked the dose escape's multi-drug bare-row guard. Clean: over-admission bounded (broad vocab lives in gate/filter only, promotion still corpus-guarded, claim-support unchanged); regex cost negligible; mismatched-unit test relaxation legitimate (synopsis is corpus-verbatim; weeks pin enforced by atom identity + adjacent_context exclusion from both gate and claim corpora).", - "checks": "BOTH FINDINGS FIXED in a3b9a54: kind arm classifies legacy tokens byte-identically and new-inflection-only sentences fall through to the dose arm when they carry a clinicalDoseValuePattern value (both repro sentences pinned as dose-intent tests); multi-drug bare-row guard extended to monitoring_schedule with a discriminating test \u2014 red-proven both directions. Reviewer checks: formatting 38/38, focused 644/644; targeting eval deferred to the wave's live canary pair." + "outcome": "rag-retrieval-reviewer on the monitoring evidence-gate parity commit: REQUEST-CHANGES (soft) — P2 reproduced: inflected monitoring kind tokens (monitor\\w*/annual(?:ly)?/blood tests?/ecgs?/lfts?) steal sole-dose-value sentences from the dose arm; dose-intent answers then reject the monitoring-kind fact (\"Quetiapine is monitored at a dose of 200 mg daily\" flipped grounded true→false, source-gap — fails CLOSED, never a wrong dose). P3: monitoring figure escape lacked the dose escape's multi-drug bare-row guard. Clean: over-admission bounded (broad vocab lives in gate/filter only, promotion still corpus-guarded, claim-support unchanged); regex cost negligible; mismatched-unit test relaxation legitimate (synopsis is corpus-verbatim; weeks pin enforced by atom identity + adjacent_context exclusion from both gate and claim corpora).", + "checks": "BOTH FINDINGS FIXED in a3b9a54: kind arm classifies legacy tokens byte-identically and new-inflection-only sentences fall through to the dose arm when they carry a clinicalDoseValuePattern value (both repro sentences pinned as dose-intent tests); multi-drug bare-row guard extended to monitoring_schedule with a discriminating test — red-proven both directions. Reviewer checks: formatting 38/38, focused 644/644; targeting eval deferred to the wave's live canary pair." }, { "date": "2026-07-21", "ref": "claude/clinical-kb-pwa-review-asi3wb (parity commit review)", "head": "1aebf02 (fix landed a3b9a54)", "scope": "(recorded with Outcome)", - "outcome": "clinical-governance-reviewer on the same commit: APPROVE-WITH-NITS. P2 (independently converged with the retrieval reviewer's P3): monitoring figure-escape lacked the dose-path multi-drug cross-entity guard \u2014 a bare wrong-drug schedule/level row in a multi-drug chunk could be entity-prefixed for a named-drug monitoring query; downstream gates verify text-vs-source presence, never attribution (worked lithium/valproate LFT path traced through finalize). FIXED in a3b9a54 exactly as its smallest-fix prescribed (guard at the :872-881 site now fires for monitoring_schedule; negative multi-drug test added, red-proven). Clean: unsupported figures impossible (admission-only change; promotion corpus guard + numeric verification + claim support all byte-unchanged); conservative failure intact (figure-bearing-only escape, schedule-free refusal pinned); adjacent-context safety held (sourceEvidenceText excludes adjacent_context; weeks refusal confirmed by probe); no PHI/provider/ranking surface. P3s: RAG impact line (present in the PR body \u2014 behaviour-change form, correct since the PR also carries the Option A retrieval change); multi-drug negative test (landed in a3b9a54).", + "outcome": "clinical-governance-reviewer on the same commit: APPROVE-WITH-NITS. P2 (independently converged with the retrieval reviewer's P3): monitoring figure-escape lacked the dose-path multi-drug cross-entity guard — a bare wrong-drug schedule/level row in a multi-drug chunk could be entity-prefixed for a named-drug monitoring query; downstream gates verify text-vs-source presence, never attribution (worked lithium/valproate LFT path traced through finalize). FIXED in a3b9a54 exactly as its smallest-fix prescribed (guard at the :872-881 site now fires for monitoring_schedule; negative multi-drug test added, red-proven). Clean: unsupported figures impossible (admission-only change; promotion corpus guard + numeric verification + claim support all byte-unchanged); conservative failure intact (figure-bearing-only escape, schedule-free refusal pinned); adjacent-context safety held (sourceEvidenceText excludes adjacent_context; weeks refusal confirmed by probe); no PHI/provider/ranking surface. P3s: RAG impact line (present in the PR body — behaviour-change form, correct since the PR also carries the Option A retrieval change); multi-drug negative test (landed in a3b9a54).", "checks": "Offline guard-chain trace + targeted vitest probes (named-drug guard, bare-figure admission, conservative gap, adjacent refusal). Provider/release gates deferred per confirmation boundary." }, { "date": "2026-07-21", "ref": "claude/clinical-kb-pwa-review-asi3wb (PR: E-3b budget-aware generation deadlines)", "head": "314d03f", - "scope": "Clinical-governance review of E-3b diff `git diff origin/main...HEAD` (commits 1078264 + 314d03f): answer-side generation timing/gating + telemetry \u2014 reserve-aware generation timeout (`generationRequestTimeoutMs`), truncation self-heal budget gate (`deadlineAllowsGenerationRetry`), `route_budget_exhausted_by_retrieval` telemetry, and the cross-region eval carve-out in scripts/eval-quality.ts.", - "outcome": "APPROVE-WITH-NITS. No P0/P1/P2. (a) Conservative failure preserved: reserve-aware timeout fires ~2s early producing the SAME error type \u2014 an internal SDK timeout is mapped by mapOpenAIError to PublicApiError(openai_timeout) (openai.ts:525-529), NOT a bare DOMException, so the rag.ts:4636 re-throw guard is not tripped and the existing source-backed fallback/extractive recovery is reached; truncation-skip falls through to the terminal throw (rag.ts:4309-4313) into the same catch. No new answer-producing path. (b) Safety gates intact: all recovery answers finalize through finalizeAnswer\u2192finalizeRagAnswerQuality and isSafeExtractiveFallbackCandidate (grounded/confidence/quality/numeric) \u2014 none touched. (c) Eval carve-out env-gated: crossRegionRunner && budgetExhaustedByRetrieval && generationMs===0; EVAL_LATENCY_CONTEXT set only in eval-canary.yml:164, prod caller (eval-quality.ts:1095) passes no options \u2192 inert in release/local; generationMs===0 requirement means a generation-side failure (generationMs>0) is never suppressed. (d)/(e) Telemetry additions non-PHI (boolean + mechanical retry-reason strings); no privacy/query-privacy/cross-border/verification source files touched; no new provider call. Nits (P3, non-blocking): carve-out also excuses fast/strong routes when generationMs===0 (sound \u2014 provably no generation ran); `requestTimeoutMs` now prod-dead (test-only); report label \"retrieval-exhausted\" (routeDeadlineExceeded && flag) is broader than actual gate suppression (audit label only, gate stays strict).", + "scope": "Clinical-governance review of E-3b diff `git diff origin/main...HEAD` (commits 1078264 + 314d03f): answer-side generation timing/gating + telemetry — reserve-aware generation timeout (`generationRequestTimeoutMs`), truncation self-heal budget gate (`deadlineAllowsGenerationRetry`), `route_budget_exhausted_by_retrieval` telemetry, and the cross-region eval carve-out in scripts/eval-quality.ts.", + "outcome": "APPROVE-WITH-NITS. No P0/P1/P2. (a) Conservative failure preserved: reserve-aware timeout fires ~2s early producing the SAME error type — an internal SDK timeout is mapped by mapOpenAIError to PublicApiError(openai_timeout) (openai.ts:525-529), NOT a bare DOMException, so the rag.ts:4636 re-throw guard is not tripped and the existing source-backed fallback/extractive recovery is reached; truncation-skip falls through to the terminal throw (rag.ts:4309-4313) into the same catch. No new answer-producing path. (b) Safety gates intact: all recovery answers finalize through finalizeAnswer→finalizeRagAnswerQuality and isSafeExtractiveFallbackCandidate (grounded/confidence/quality/numeric) — none touched. (c) Eval carve-out env-gated: crossRegionRunner && budgetExhaustedByRetrieval && generationMs===0; EVAL_LATENCY_CONTEXT set only in eval-canary.yml:164, prod caller (eval-quality.ts:1095) passes no options → inert in release/local; generationMs===0 requirement means a generation-side failure (generationMs>0) is never suppressed. (d)/(e) Telemetry additions non-PHI (boolean + mechanical retry-reason strings); no privacy/query-privacy/cross-border/verification source files touched; no new provider call. Nits (P3, non-blocking): carve-out also excuses fast/strong routes when generationMs===0 (sound — provably no generation ran); `requestTimeoutMs` now prod-dead (test-only); report label \"retrieval-exhausted\" (routeDeadlineExceeded && flag) is broader than actual gate suppression (audit label only, gate stays strict).", "checks": "88 offline unit tests PASS (tests/rag-route-budget.test.ts, tests/eval-quality.test.ts, tests/rag-offline-answer.test.ts, tests/rag-answer-fallback.test.ts); no provider/Supabase/OpenAI calls; no files mutated except this ledger row" }, { @@ -20353,7 +20395,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (PR: E-3b budget-aware generation deadlines)", "head": "314d03f (+eb08ec5 review row)", "scope": "(recorded with Outcome)", - "outcome": "ADDENDUM 5 wave E-3b implemented per the design-agent plan: generation attempts clamped to route budget minus a measured 2s recovery reserve (single call-site, all four attempt kinds); truncation self-heal gated on retry viability (reserve+5s floor) with observable truncation_retry_skipped_budget_reserve marker; additive route_budget_exhausted_by_retrieval runtime flag; eval route-ceiling gains the triple-condition cross-region carve-out (context + runtime flag + zero generation) with retrieval-exhausted audit cells \u2014 local/release gates provably strict. Fixes I3 (54ms budget overrun after 22.6s provider timeout), I5 (82s truncation waste class), resolves I2 (clozapine 13.3s retrieval vs 12s runtime budget = geography, now suppressed ONLY in the sanctioned cross-region context with full auditability). Reviewer verdicts: rag-retrieval-reviewer APPROVE-WITH-NITS (2 P3: prod-dead requestTimeoutMs retained for symmetry; report-cell coupling cosmetic; cached-replay invariant PROVEN \u2014 budget-exhausted answers never cached, carve-out unreachable via replay; marker isolation proven \u2014 SLO counters key on fallback_reason not answer_retry_reasons); clinical-governance-reviewer APPROVE-WITH-NITS (prior row) \u2014 internal-timeout\u2192PublicApiError\u2192existing-fallback path verified, all safety gates still applied to recovery answers. ALSO BANKED \u2014 E-2 targeting baseline (canary run #58, 29788404357, all-green incl. first execution of the !cancelled()-fixed instrument, ~$1-2): metric_rates relevance 0.6 / readability 1.0 / artifact_leaks 1.0 / intent_coverage 0.9333 / fail_closed 0.9; targeting_rate 0.5909 (13/22); by intent: document_lookup 5/5, red_result_action 3/3, contraindication 2/2, dose 1/5, monitoring_schedule 1/5, pathway_referral 1/2; all 9 misses = missing dose figure/schedule-interval (answer lengths 73-232 chars) \u2192 E-3c co-primary target alongside the wasted-generation class. Phase E spend \u2248$3-6 of \u2264$20.", + "outcome": "ADDENDUM 5 wave E-3b implemented per the design-agent plan: generation attempts clamped to route budget minus a measured 2s recovery reserve (single call-site, all four attempt kinds); truncation self-heal gated on retry viability (reserve+5s floor) with observable truncation_retry_skipped_budget_reserve marker; additive route_budget_exhausted_by_retrieval runtime flag; eval route-ceiling gains the triple-condition cross-region carve-out (context + runtime flag + zero generation) with retrieval-exhausted audit cells — local/release gates provably strict. Fixes I3 (54ms budget overrun after 22.6s provider timeout), I5 (82s truncation waste class), resolves I2 (clozapine 13.3s retrieval vs 12s runtime budget = geography, now suppressed ONLY in the sanctioned cross-region context with full auditability). Reviewer verdicts: rag-retrieval-reviewer APPROVE-WITH-NITS (2 P3: prod-dead requestTimeoutMs retained for symmetry; report-cell coupling cosmetic; cached-replay invariant PROVEN — budget-exhausted answers never cached, carve-out unreachable via replay; marker isolation proven — SLO counters key on fallback_reason not answer_retry_reasons); clinical-governance-reviewer APPROVE-WITH-NITS (prior row) — internal-timeout→PublicApiError→existing-fallback path verified, all safety gates still applied to recovery answers. ALSO BANKED — E-2 targeting baseline (canary run #58, 29788404357, all-green incl. first execution of the !cancelled()-fixed instrument, ~$1-2): metric_rates relevance 0.6 / readability 1.0 / artifact_leaks 1.0 / intent_coverage 0.9333 / fail_closed 0.9; targeting_rate 0.5909 (13/22); by intent: document_lookup 5/5, red_result_action 3/3, contraindication 2/2, dose 1/5, monitoring_schedule 1/5, pathway_referral 1/2; all 9 misses = missing dose figure/schedule-interval (answer lengths 73-232 chars) → E-3c co-primary target alongside the wasted-generation class. Phase E spend ≈$3-6 of ≤$20.", "checks": "Red-proofs: reserve pinned 3 independent ways (exact 23000ms grant, deadline flag clear, total under budget); self-heal skip pins exact marker + single provider call; offline flag pinned true/false. Focused: route-budget 9/9, eval-quality 27/27, fallback+offline 52/52, parser/abort regressions 15/15. Full suite 3043 passed / 1 known container pdf artifact. typecheck+lint+prettier clean. No provider calls; live proof = E-4 paired run" }, { @@ -20361,7 +20403,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (PR: E-3c PR-B short-circuit)", "head": "f7e6cbb + hardening commit", "scope": "(recorded with Outcome)", - "outcome": "E-3c PR-B: pre-generation validated-extractive short-circuit for gate-passed routine procedural \"What...process/include/required\" queries (marker validated_routine_extractive_first), generalizing the LAI + blocked-recovery precedents via new rag-extractive-first.ts (3 predicates moved byte-verbatim, machine-verified; rag.ts 5029\u21924908 vs 5030 budget). Kills the run-#57 6x wasted-generation class. REVIEWS (both pre-push): rag-retrieval-reviewer APPROVE-WITH-NITS \u2014 move fidelity brace-diff verified byte-identical; confidence-gate skip PROVEN safe (passed-gate is a no-op in applyConfidenceGate; markers pairwise mutually exclusive); comparison false-positives blocked by unchanged classifier precedence; offline/source-only idempotent; zero retrieval/ranking/selection/threshold change; P2 = eval-only assertions (intent_coverage/artifact_leaks/expected-file) unverifiable offline for flip candidates (quality-nocc-document-support, quality-form-required-documentation, quality-discharge-documentation, quality-duress-pathway + rag-set siblings) \u2192 pre-merge BRANCH canary recommended and ADOPTED (offline-green + review-approved proven insufficient for this surface, 2026-07-20). clinical-governance-reviewer APPROVE-WITH-NITS \u2014 full gate-stack trace: nothing bypassed (same finalizeRagAnswerQuality, same citation scoping, numeric verification not fail-open, ungrounded-finalize defense at rag.ts:3694); P2 = pre-existing bare-cross-reference-with-overlap gap, NOT materially widened (new trigger anti-correlates), hardening recommended \u2192 APPLIED this PR: !isBareCrossReferenceAnswer screen in hasValidatedExtractiveCandidate (closes all three short-circuit paths; discriminating test added; disclosed post-review delta, strictly narrows shipping). MERGE GATE: draft until the branch canary pair (baseline #57/#58 vs branch run with answer_case_limit=44 + answer_quality_eval=true, est $3-6 of authorized envelope) is green \u2014 zero per-case regressions, recalls 1.0, quality/targeting rates >= baseline.", + "outcome": "E-3c PR-B: pre-generation validated-extractive short-circuit for gate-passed routine procedural \"What...process/include/required\" queries (marker validated_routine_extractive_first), generalizing the LAI + blocked-recovery precedents via new rag-extractive-first.ts (3 predicates moved byte-verbatim, machine-verified; rag.ts 5029→4908 vs 5030 budget). Kills the run-#57 6x wasted-generation class. REVIEWS (both pre-push): rag-retrieval-reviewer APPROVE-WITH-NITS — move fidelity brace-diff verified byte-identical; confidence-gate skip PROVEN safe (passed-gate is a no-op in applyConfidenceGate; markers pairwise mutually exclusive); comparison false-positives blocked by unchanged classifier precedence; offline/source-only idempotent; zero retrieval/ranking/selection/threshold change; P2 = eval-only assertions (intent_coverage/artifact_leaks/expected-file) unverifiable offline for flip candidates (quality-nocc-document-support, quality-form-required-documentation, quality-discharge-documentation, quality-duress-pathway + rag-set siblings) → pre-merge BRANCH canary recommended and ADOPTED (offline-green + review-approved proven insufficient for this surface, 2026-07-20). clinical-governance-reviewer APPROVE-WITH-NITS — full gate-stack trace: nothing bypassed (same finalizeRagAnswerQuality, same citation scoping, numeric verification not fail-open, ungrounded-finalize defense at rag.ts:3694); P2 = pre-existing bare-cross-reference-with-overlap gap, NOT materially widened (new trigger anti-correlates), hardening recommended → APPLIED this PR: !isBareCrossReferenceAnswer screen in hasValidatedExtractiveCandidate (closes all three short-circuit paths; discriminating test added; disclosed post-review delta, strictly narrows shipping). MERGE GATE: draft until the branch canary pair (baseline #57/#58 vs branch run with answer_case_limit=44 + answer_quality_eval=true, est $3-6 of authorized envelope) is green — zero per-case regressions, recalls 1.0, quality/targeting rates >= baseline.", "checks": "Red-proof + 3 negative guards; focused 61/61 + fallback/offline/contract suites; full suite 3061 passed / 1 known container artifact (pre-hardening tree; hardening re-verified focused); typecheck+lint+prettier clean; maintainability budget passed (4908/5030)" }, { @@ -20369,7 +20411,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (PR: E-3c PR-C figure-aware selection)", "head": "043b030 + P2-fix commit", "scope": "(recorded with Outcome)", - "outcome": "E-3c PR-C: dose/monitoring extractive answers now carry the asked-for figure/schedule when the cited chunk verbatim supports it \u2014 lead-slot promotion (dose swaps last of 2 slots, monitoring appends 2nd sentence; no-op when a lead already carries a figure) guarded by the claim-support atom corpus (sourceEvidenceText exported, promotionAtomKey byte-identical to claim-support's atomKey), plus the dose/threshold generation-fallback preferring the safe figure-carrying candidate (safety gate unchanged, filter-order-stable). Fallback helpers extracted to rag-extractive-answer (cycle-check verified); rag.ts 4908\u21924901. Six discriminating tests each verified red-on-prior-code incl. proving the nuke-guard load-bearing by disabling it. REVIEWS (both pre-push on 043b030): rag-retrieval-reviewer APPROVE-WITH-NITS \u2014 no-op path byte-identical verified, atom-key identity verified, filter-vs-find proven side-effect-free, 2-sentence append gate-safe, intent double-gated, zero retrieval/ordering change, imputation contract green; P2 = zero-atom monitoring figures (\"every 6 weeks\" yields no value atom) pass the guard trivially and can be nuked by claim support if sourced only from adjacent context (fails SAFE \u2014 evidence gap, never a wrong figure). clinical-governance-reviewer APPROVE-WITH-NITS \u2014 all six clinical concerns CLEARED end-to-end (verbatim-support guarantee, citation binding preserved, conservative failure test-proven, unsafe candidates impossible, wrong-drug risk controlled by pre-existing entity/multi-drug guards, no PHI); same zero-atom finding as P3 + one comment-precision nit. P2 FIXED post-review (disclosed): zero-atom figures now require the matched figure substring verbatim in sourceEvidenceText (intentFigureMatchText); proven both directions by 3 new tests (promotes from content, refuses from adjacent-context-only); comment-precision nit folded in.", + "outcome": "E-3c PR-C: dose/monitoring extractive answers now carry the asked-for figure/schedule when the cited chunk verbatim supports it — lead-slot promotion (dose swaps last of 2 slots, monitoring appends 2nd sentence; no-op when a lead already carries a figure) guarded by the claim-support atom corpus (sourceEvidenceText exported, promotionAtomKey byte-identical to claim-support's atomKey), plus the dose/threshold generation-fallback preferring the safe figure-carrying candidate (safety gate unchanged, filter-order-stable). Fallback helpers extracted to rag-extractive-answer (cycle-check verified); rag.ts 4908→4901. Six discriminating tests each verified red-on-prior-code incl. proving the nuke-guard load-bearing by disabling it. REVIEWS (both pre-push on 043b030): rag-retrieval-reviewer APPROVE-WITH-NITS — no-op path byte-identical verified, atom-key identity verified, filter-vs-find proven side-effect-free, 2-sentence append gate-safe, intent double-gated, zero retrieval/ordering change, imputation contract green; P2 = zero-atom monitoring figures (\"every 6 weeks\" yields no value atom) pass the guard trivially and can be nuked by claim support if sourced only from adjacent context (fails SAFE — evidence gap, never a wrong figure). clinical-governance-reviewer APPROVE-WITH-NITS — all six clinical concerns CLEARED end-to-end (verbatim-support guarantee, citation binding preserved, conservative failure test-proven, unsafe candidates impossible, wrong-drug risk controlled by pre-existing entity/multi-drug guards, no PHI); same zero-atom finding as P3 + one comment-precision nit. P2 FIXED post-review (disclosed): zero-atom figures now require the matched figure substring verbatim in sourceEvidenceText (intentFigureMatchText); proven both directions by 3 new tests (promotes from content, refuses from adjacent-context-only); comment-precision nit folded in.", "checks": "Focused post-fix: extractive-formatting 32/32 + fallback/eval-cases/offline/contract/extractive-first 98/98 incl. imputation contract; typecheck+prettier+budgets clean; full-suite 3068-passed baseline pre-P2-fix (fix re-verified focused). Live proof = E-4 pair next" }, { @@ -20377,7 +20419,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (PR: I9 weekly coverage raise)", "head": "see PR head", "scope": "(recorded with Outcome)", - "outcome": "ADDENDUM 5 post-green item I9 (plan-authorized \"after reds fixed\"): weekly scheduled canary ANSWER_CASE_LIMIT default 8\u219244 \u2014 the Sunday 18:00 UTC cron now guards the FULL answer-quality case set instead of the first 8 (both #57 blocking reds historically lived OUTSIDE the first 8, leaving the weekly gate blind to them). Unblocked by run #61 proving the citation gate green on the full 44. Cost: est +$1-2/week (user-authorized in the plan). Contract test pin updated in lockstep (eval-canary-workflow.test.ts). Dispatch shapes unchanged (input override still wins); operational-risk diff, plain-revert rollback.", + "outcome": "ADDENDUM 5 post-green item I9 (plan-authorized \"after reds fixed\"): weekly scheduled canary ANSWER_CASE_LIMIT default 8→44 — the Sunday 18:00 UTC cron now guards the FULL answer-quality case set instead of the first 8 (both #57 blocking reds historically lived OUTSIDE the first 8, leaving the weekly gate blind to them). Unblocked by run #61 proving the citation gate green on the full 44. Cost: est +$1-2/week (user-authorized in the plan). Contract test pin updated in lockstep (eval-canary-workflow.test.ts). Dispatch shapes unchanged (input override still wins); operational-risk diff, plain-revert rollback.", "checks": "check:github-actions PASS; check:ci-scope PASS; check:gate-manifest PASS (20/20); eval-canary-workflow contract 4/4; prettier clean; no provider calls" }, { @@ -20385,7 +20427,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted from 87815f4; PR: E-3a cost self-reporting)", "head": "see PR head + follow-up pin", "scope": "(recorded with Outcome)", - "outcome": "Phase E-3a wave (all $0 diagnostics complete, recorded here) + I8 fix: eval-canary env gains the three RAG_EVAL__\\_USD_PER_MILLION rates (gpt-5.6-terra standard tier, verified from the live OpenAI pricing page 2026-07-21; documented as a LOWER BOUND since gpt-5.6-sol strong retries cost 2x and the estimator applies one rate set) so estimated_cost_usd stops reading n/a in CI. E-3a findings: (1) discarded-generation histogram from run #57 \u2014 fast_quality_retry_strong\u2192extractive x6, generation_quality_failed x4, provider_timeout x2; gate sub-reasons fragment_like x2, bad_final_answer_quality x1, ungrounded_extractive_fallback x1 \u2192 E-3c targets the fast-attempt-fails-extractive-wins shape first. (2) I2 resolved: routeCeilingExceeded (eval-quality.ts:157/171) keys on the RUNTIME's own route_budget_ms + deadline flag, NOT the cross-region-widened eval gates \u2014 clozapine case = 13.3s retrieval vs the runtime's 12s extractive budget, geography-amplified; design \u2192 E-3b. (3) FIXTURE-CORPUS DRIFT (major): the live corpus contains ZERO MHSP_-named files; the 44-case fixture's expectedFiles are all MHSP._/CG.MHSP._ and pass only via the eval-document-matching alias tier. All three expected-doc failures triaged: neuroleptic-side-effect-escalation = REAL retrieval-coverage gap (alias exists; Neuroleptic Side Effects (AKG).pdf indexed 11 chunks, 3 contain escalat%, yet answer retrieval returned a single off-point source) \u2192 protected-path item awaiting user go-ahead; admission-discharge x2 = top-5 preference for sibling NMHS/RKPG policies over the existing aliased AKG doc \u2192 labeling-vs-ranking decision presented to user. No fixture/alias edits made (ground truth requires sign-off).", + "outcome": "Phase E-3a wave (all $0 diagnostics complete, recorded here) + I8 fix: eval-canary env gains the three RAG_EVAL__\\_USD_PER_MILLION rates (gpt-5.6-terra standard tier, verified from the live OpenAI pricing page 2026-07-21; documented as a LOWER BOUND since gpt-5.6-sol strong retries cost 2x and the estimator applies one rate set) so estimated_cost_usd stops reading n/a in CI. E-3a findings: (1) discarded-generation histogram from run #57 — fast_quality_retry_strong→extractive x6, generation_quality_failed x4, provider_timeout x2; gate sub-reasons fragment_like x2, bad_final_answer_quality x1, ungrounded_extractive_fallback x1 → E-3c targets the fast-attempt-fails-extractive-wins shape first. (2) I2 resolved: routeCeilingExceeded (eval-quality.ts:157/171) keys on the RUNTIME's own route_budget_ms + deadline flag, NOT the cross-region-widened eval gates — clozapine case = 13.3s retrieval vs the runtime's 12s extractive budget, geography-amplified; design → E-3b. (3) FIXTURE-CORPUS DRIFT (major): the live corpus contains ZERO MHSP_-named files; the 44-case fixture's expectedFiles are all MHSP._/CG.MHSP._ and pass only via the eval-document-matching alias tier. All three expected-doc failures triaged: neuroleptic-side-effect-escalation = REAL retrieval-coverage gap (alias exists; Neuroleptic Side Effects (AKG).pdf indexed 11 chunks, 3 contain escalat%, yet answer retrieval returned a single off-point source) → protected-path item awaiting user go-ahead; admission-discharge x2 = top-5 preference for sibling NMHS/RKPG policies over the existing aliased AKG doc → labeling-vs-ranking decision presented to user. No fixture/alias edits made (ground truth requires sign-off).", "checks": "check:github-actions PASS; check:ci-scope PASS; check:gate-manifest PASS; prettier clean; Supabase access read-only (documents/document_chunks SELECTs); OpenAI pricing page read via WebFetch" }, { @@ -20393,7 +20435,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted from c308fdc; PR: labeling widen)", "head": "see PR head", "scope": "(recorded with Outcome)", - "outcome": "USER-APPROVED ground-truth widening (AskUserQuestion 2026-07-21: \"Widen to accept siblings\") for the two admission-discharge cases: the WIDER alias tier's AdmissionCommunityPts entry gains the two NMHS \"Admission to Discharge\" titles (Community Mental Health + Mental Health Inpatients). Deliberate exclusions documented in-code: discharge-only docs must not satisfy the admission slot; the MHHITH programme policy is too narrow. STRICT golden tier untouched (bulk-merge prohibition respected). Verified by replaying run #57's actual top-5 lists through expectedFileCoverage: admission-discharge-coverage-paraphrase now passes; admission-discharge-comparison STILL FAILS honestly (its top-5 carries no admission-side doc at all \u2014 dup discharge-planning + Falls Prevention) and is retained as a genuine comparison-class retrieval-coverage signal, folded into the same investigation as the neuroleptic case.", + "outcome": "USER-APPROVED ground-truth widening (AskUserQuestion 2026-07-21: \"Widen to accept siblings\") for the two admission-discharge cases: the WIDER alias tier's AdmissionCommunityPts entry gains the two NMHS \"Admission to Discharge\" titles (Community Mental Health + Mental Health Inpatients). Deliberate exclusions documented in-code: discharge-only docs must not satisfy the admission slot; the MHHITH programme policy is too narrow. STRICT golden tier untouched (bulk-merge prohibition respected). Verified by replaying run #57's actual top-5 lists through expectedFileCoverage: admission-discharge-coverage-paraphrase now passes; admission-discharge-comparison STILL FAILS honestly (its top-5 carries no admission-side doc at all — dup discharge-planning + Falls Prevention) and is retained as a genuine comparison-class retrieval-coverage signal, folded into the same investigation as the neuroleptic case.", "checks": "typecheck PASS; prettier clean; probe script replay recorded (paraphrase allHit true / comparison allHit false, missing admission slot); no retrieval code touched; protected-file edit (eval-document-matching.ts) per explicit user authorization" }, { @@ -20401,23 +20443,23 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted from e02ba3d; PR: E-3c PR-A instrument)", "head": "see PR head", "scope": "(recorded with Outcome)", - "outcome": "ADDENDUM 5 wave E-3c design accepted (Plan agent, full report in session record) and PR-A delivered: eval-answer-quality gains --dump-answers (per-case answer TEXT + sections + targeting verdict JSON for the canary artifact \u2014 answers are not retained at rest by privacy design, so miss diagnosis needs eval-time capture), parseArgs/buildAnswerDumpRecord exported behind an import.meta main-guard (eval-quality precedent), canary targeting step wired with the flag. Design highlights for the record: DEFECT 1 root confirmed as fast-attempt-doomed-then-discarded on strong_routine_retrieval procedural shapes \u2014 PR-B generalizes the EXISTING validated-extractive short-circuit pattern (LAI + blocked-recovery precedents, hasValidatedExtractiveCandidate) to the measured shape via a new rag-extractive-first.ts module (net ~-110 rag.ts lines against the 5030 budget); DEFECT 2 rank-1 root = extractive lead-slot selection prefers shortest sentence and admits figure-less leads (sort at rag-extractive-answer.ts:917, 1-slot monitoring leads) \u2014 PR-C adds intent-figure-aware lead promotion with a claim-support atom-corpus nuke-proofing guard + dose/threshold fallback candidate preference (find(safe && figure) ?? find(safe)); answer-verification CLEARED as direct cause (whole-answer gap or unbold only, never per-figure deletion). H2 (strong-route comparison/complex residual) explicitly deferred as the named E-3d candidate. E-4 metrics set: discarded-generation <20% from ~47%, dose \u22653/5, monitoring \u22653/5, no intent below #58, recalls pinned 1.0, relevance/fail_closed/readability/artifact_leaks \u2265 #58.", + "outcome": "ADDENDUM 5 wave E-3c design accepted (Plan agent, full report in session record) and PR-A delivered: eval-answer-quality gains --dump-answers (per-case answer TEXT + sections + targeting verdict JSON for the canary artifact — answers are not retained at rest by privacy design, so miss diagnosis needs eval-time capture), parseArgs/buildAnswerDumpRecord exported behind an import.meta main-guard (eval-quality precedent), canary targeting step wired with the flag. Design highlights for the record: DEFECT 1 root confirmed as fast-attempt-doomed-then-discarded on strong_routine_retrieval procedural shapes — PR-B generalizes the EXISTING validated-extractive short-circuit pattern (LAI + blocked-recovery precedents, hasValidatedExtractiveCandidate) to the measured shape via a new rag-extractive-first.ts module (net ~-110 rag.ts lines against the 5030 budget); DEFECT 2 rank-1 root = extractive lead-slot selection prefers shortest sentence and admits figure-less leads (sort at rag-extractive-answer.ts:917, 1-slot monitoring leads) — PR-C adds intent-figure-aware lead promotion with a claim-support atom-corpus nuke-proofing guard + dose/threshold fallback candidate preference (find(safe && figure) ?? find(safe)); answer-verification CLEARED as direct cause (whole-answer gap or unbold only, never per-figure deletion). H2 (strong-route comparison/complex residual) explicitly deferred as the named E-3d candidate. E-4 metrics set: discarded-generation <20% from ~47%, dose ≥3/5, monitoring ≥3/5, no intent below #58, recalls pinned 1.0, relevance/fail_closed/readability/artifact_leaks ≥ #58.", "checks": "PR-A gates: new tests/eval-answer-quality.test.ts 4/4; typecheck, check:github-actions, check:ci-scope, eval-canary-workflow test, prettier all clean; no provider calls" }, { "date": "2026-07-21", - "ref": "claude/database-governance-audit-10b6ed (PR #1051: source-governance audit \u2014 safe subset)", + "ref": "claude/database-governance-audit-10b6ed (PR #1051: source-governance audit — safe subset)", "head": "cee396730", "scope": "Governance-metadata observability + UI display + provenance flow test; no ranking/retrieval/generation surface touched.", - "outcome": "IMPLEMENTED + handed off (not a review of prior work). Resolved audit #1 (logger.warn on unrecognized enum values; return value unchanged), #2 (review_due_source added to frontendVisibleWarningCodes \u2192 answer-level badge; warning-severity, no refusal impact), #9 (source_metadata retained on safety-finding citations + governance pill in SafetyFindingsListContent), #13 (new tests/provenance-flow.test.ts: DB-normalize\u2192governance\u2192client payload sources+safety citations\u2192render policy). Deferred #4/5/6/8/10 (RAG-protected ranking/selection/LLM-context/cache \u2014 need live eval-canary+approval), #11/#5 flag debt (D5/D4), #3 (is_public schema/RLS), #7 (conflict-detection scope), #12 (canary automation). Rebased onto origin/main (was 18 behind; conflict-free \u2014 none of the 18 commits touched the 8 files). PR-policy CI green (confirmed no ragRankingPatterns match).", - "checks": "verify:pr-local exit 0 (351 files/3129 tests, production build, client-bundle secret scan, offline RAG fixtures 36/36); typecheck + lint + prettier green. verify:ui NOT run locally: pre-existing globals.css Tailwind/Turbopack dev-compile error (git-clean, unrelated; prod build passed) \u2014 CI Production UI job covers it. check:production-readiness deferred (offline env/config validator; PR changes no env/secret/config inputs; secretless worktree). No provider calls." + "outcome": "IMPLEMENTED + handed off (not a review of prior work). Resolved audit #1 (logger.warn on unrecognized enum values; return value unchanged), #2 (review_due_source added to frontendVisibleWarningCodes → answer-level badge; warning-severity, no refusal impact), #9 (source_metadata retained on safety-finding citations + governance pill in SafetyFindingsListContent), #13 (new tests/provenance-flow.test.ts: DB-normalize→governance→client payload sources+safety citations→render policy). Deferred #4/5/6/8/10 (RAG-protected ranking/selection/LLM-context/cache — need live eval-canary+approval), #11/#5 flag debt (D5/D4), #3 (is_public schema/RLS), #7 (conflict-detection scope), #12 (canary automation). Rebased onto origin/main (was 18 behind; conflict-free — none of the 18 commits touched the 8 files). PR-policy CI green (confirmed no ragRankingPatterns match).", + "checks": "verify:pr-local exit 0 (351 files/3129 tests, production build, client-bundle secret scan, offline RAG fixtures 36/36); typecheck + lint + prettier green. verify:ui NOT run locally: pre-existing globals.css Tailwind/Turbopack dev-compile error (git-clean, unrelated; prod build passed) — CI Production UI job covers it. check:production-readiness deferred (offline env/config validator; PR changes no env/secret/config inputs; secretless worktree). No provider calls." }, { "date": "2026-07-21", "ref": "claude/patient-profile-input-bounds-123366 (PR #1045: FV-03 fail-safe input bounds)", "head": "75303e8b8", - "scope": "Clinical-governance verification of FV-03 (patient-profile numeric fields \u2192 medication-safety alert engine). 4-agent adversarial workflow (consumer map + suppression audit + physiological bounds + synthesis).", - "outcome": "ADJUST\u2192implemented. Consumer map: evaluatePatientAlerts is the ONLY numeric consumer, no dose arithmetic, sanitize() is the sole guaranteed chokepoint. Suppression audit found naive null-routing UNSAFE via the bare-renal both-null hole (medication-patient-alerts.ts:286) \u2014 nulling one out-of-range renal input while the other is present-normal \u2192 false all-clear; fixed with &&\u2192|| (0 bare-renal contraindication rows in corpus \u2192 no-op on current data). Bounds VALIDATED (age 0-130, egfr 0-250, crcl 0-400, qtc 240-800, scr \u00b5mol/L 15-3000 unit-aware): never reject a legitimate clinical extreme. Reject-to-null (never clamp).", + "scope": "Clinical-governance verification of FV-03 (patient-profile numeric fields → medication-safety alert engine). 4-agent adversarial workflow (consumer map + suppression audit + physiological bounds + synthesis).", + "outcome": "ADJUST→implemented. Consumer map: evaluatePatientAlerts is the ONLY numeric consumer, no dose arithmetic, sanitize() is the sole guaranteed chokepoint. Suppression audit found naive null-routing UNSAFE via the bare-renal both-null hole (medication-patient-alerts.ts:286) — nulling one out-of-range renal input while the other is present-normal → false all-clear; fixed with &&→|| (0 bare-renal contraindication rows in corpus → no-op on current data). Bounds VALIDATED (age 0-130, egfr 0-250, crcl 0-400, qtc 240-800, scr µmol/L 15-3000 unit-aware): never reject a legitimate clinical extreme. Reject-to-null (never clamp).", "checks": "typecheck, lint, format:check, full unit+jsdom 349 files/3120 passed/0 failed (incl. 38 new/updated FV-03 tests), design-system-contract (baselines unchanged), type-scale, icon-scale, check:production-readiness READY. verify:ui in CI. No provider calls." }, { @@ -20425,7 +20467,7 @@ "ref": "claude/x4-sast-gate (PR #1012)", "head": "0d4985e63", "scope": "Maturity X4: blocking SAST gate on the untrusted-document parsing surface", - "outcome": "Triage-first per workorder: CI-pinned semgrep/semgrep:1.168.0 over worker/**, src/lib/ingestion*.ts, src/lib/extractors, src/app/api/{ingestion,upload} = 0 ERROR findings (24 TS rules/17 files; 55 Python rules/3 files) \u2014 gate starts green with no suppressions. Shipped `semgrep-ingestion-gate` job (no continue-on-error; container digest-pinned to the triage-verified 1.168.0 image) with p/python added for the worker OCR stack; repo-wide advisory job untouched. check-github-action-pins.mjs now enforces both policy halves fail-closed (advisory repo-wide / blocking-and-scoped gate / digest-pinned gate container). Residuals: registry-pack mutability accepted for the narrow surface; making the workflow a branch-protection required check is an operator decision outside this PR.", + "outcome": "Triage-first per workorder: CI-pinned semgrep/semgrep:1.168.0 over worker/**, src/lib/ingestion*.ts, src/lib/extractors, src/app/api/{ingestion,upload} = 0 ERROR findings (24 TS rules/17 files; 55 Python rules/3 files) — gate starts green with no suppressions. Shipped `semgrep-ingestion-gate` job (no continue-on-error; container digest-pinned to the triage-verified 1.168.0 image) with p/python added for the worker OCR stack; repo-wide advisory job untouched. check-github-action-pins.mjs now enforces both policy halves fail-closed (advisory repo-wide / blocking-and-scoped gate / digest-pinned gate container). Residuals: registry-pack mutability accepted for the narrow surface; making the workflow a branch-protection required check is an operator decision outside this PR.", "checks": "Exact gate command exit 0 in pinned container; check:github-actions (new assertions verified fail-closed); check:ci-scope; yaml-contract vitest 1/1; verify:cheap 3031 tests green. No provider calls (local Docker only)." }, { @@ -20438,26 +20480,26 @@ }, { "date": "2026-07-20", - "ref": "claude/clinical-kb-pwa-review-asi3wb (Phase B live pair \u2014 no code change; recorded for eval-history completeness)", + "ref": "claude/clinical-kb-pwa-review-asi3wb (Phase B live pair — no code change; recorded for eval-history completeness)", "head": "canary runs 29763761133 (#53 baseline) + 29769050798 (#54 tuned)", - "scope": "ADDENDUM 4 Phase B verdict: staged 3-class tuner weights produced ZERO live movement \u2014 NOT adopted per the measured-gain rule", - "outcome": "Offline tuner recommendations (document_lookup titleSection\u21920.9, table_threshold clinicalEvidence\u21920.95, comparison hybridRelevance\u21920.95; proxy comparison-mrr 0.833\u21921.0) staged via the B-PR-1 rag_ranking_config input; #54 log proves the override active (validation step echo). Result vs re-gated baseline: mrr@10 0.8921 vs 0.8922, irrelevant@10 0.1083 vs 0.1083, recalls 1.0/1.0 both, 36/36 both, all four headroom cases byte-identical rr (flowchart 0.20, ciwa-threshold 0.25, patient-safety 0.33, opioid 0.33). Learning: the 5-candidate linear proxy saturates; real headroom lives in fast-path saturated-tie structure (Phase C trigger condition mrr < 0.90 formally met; user authorized C). Nothing to roll back (per-run override). Spend \u2248$2-4 of user-raised \u2264$20 cap.", + "scope": "ADDENDUM 4 Phase B verdict: staged 3-class tuner weights produced ZERO live movement — NOT adopted per the measured-gain rule", + "outcome": "Offline tuner recommendations (document_lookup titleSection→0.9, table_threshold clinicalEvidence→0.95, comparison hybridRelevance→0.95; proxy comparison-mrr 0.833→1.0) staged via the B-PR-1 rag_ranking_config input; #54 log proves the override active (validation step echo). Result vs re-gated baseline: mrr@10 0.8921 vs 0.8922, irrelevant@10 0.1083 vs 0.1083, recalls 1.0/1.0 both, 36/36 both, all four headroom cases byte-identical rr (flowchart 0.20, ciwa-threshold 0.25, patient-safety 0.33, opioid 0.33). Learning: the 5-candidate linear proxy saturates; real headroom lives in fast-path saturated-tie structure (Phase C trigger condition mrr < 0.90 formally met; user authorized C). Nothing to roll back (per-run override). Spend ≈$2-4 of user-raised ≤$20 cap.", "checks": "Both canary runs green (36/36 + answer-quality); override-active proof in #54 job log; no adoption = no code diff" }, { "date": "2026-07-20", - "ref": "claude/clinical-kb-pwa-review-asi3wb (Phase C live verdict \u2014 no code change; main stays reverted at 0a498e6)", + "ref": "claude/clinical-kb-pwa-review-asi3wb (Phase C live verdict — no code change; main stays reverted at 0a498e6)", "head": "canary run 29773198933 (#55, on f96217c)", - "scope": "ADDENDUM 4 Phase C LIVE-REFUTED: canary on the merged tail code FAILED 3/36 (doc_recall 1.0\u21920.9167, mrr@10 0.8921\u21920.8138) \u2014 the user-ordered revert (#1005) was correct and STANDS", - "outcome": "Failures: patient-safety-plan-include (PtSafetyPlan out of top-5, rr 0.33\u21920.14), patient-property-visual-table (rr 1.00\u21920.11) and schizophrenia-overview (rr 1.00\u21920.14) \u2014 two previously rank-1 cases destroyed. Root cause (post-hoc): the S1 lexical-chunk lift spreads hybrid_score, which is the PRIMARY release sort key \u2014 inside the dead (0.48,0.5) band it still PREEMPTS every downstream key, so raw ts_rank order overrode the boost/title/subject-aware relevance order that previously decided all-tied-at-0.48 pools. Lexically-loud chunks leapfrogged title-boosted correct documents = the #118 mechanism, reproduced live. The offline S1 test used identical-content candidates (coverage tie) and could not see it. The S2 similarity tail (tie-break-position key) remains reviewer-verified safe in isolation \u2014 retrieval reviewer verdict on the full diff: APPROVE-WITH-NITS, P3 only (0.49-lowering proven unreachable via the SQL 0.48 cap; no gate crossings in (0.92,0.94); hardening nits recorded). DISPOSITION: no re-land as-is. Any retry = S2-only + S1 redesigned to a key BELOW relevance in the comparator chain, new design + fresh pair. The staged-rollback discipline (canary pair + instant revert) worked exactly as designed. Spend \u2248$4-8 of \u2264$20.", + "scope": "ADDENDUM 4 Phase C LIVE-REFUTED: canary on the merged tail code FAILED 3/36 (doc_recall 1.0→0.9167, mrr@10 0.8921→0.8138) — the user-ordered revert (#1005) was correct and STANDS", + "outcome": "Failures: patient-safety-plan-include (PtSafetyPlan out of top-5, rr 0.33→0.14), patient-property-visual-table (rr 1.00→0.11) and schizophrenia-overview (rr 1.00→0.14) — two previously rank-1 cases destroyed. Root cause (post-hoc): the S1 lexical-chunk lift spreads hybrid_score, which is the PRIMARY release sort key — inside the dead (0.48,0.5) band it still PREEMPTS every downstream key, so raw ts_rank order overrode the boost/title/subject-aware relevance order that previously decided all-tied-at-0.48 pools. Lexically-loud chunks leapfrogged title-boosted correct documents = the #118 mechanism, reproduced live. The offline S1 test used identical-content candidates (coverage tie) and could not see it. The S2 similarity tail (tie-break-position key) remains reviewer-verified safe in isolation — retrieval reviewer verdict on the full diff: APPROVE-WITH-NITS, P3 only (0.49-lowering proven unreachable via the SQL 0.48 cap; no gate crossings in (0.92,0.94); hardening nits recorded). DISPOSITION: no re-land as-is. Any retry = S2-only + S1 redesigned to a key BELOW relevance in the comparator chain, new design + fresh pair. The staged-rollback discipline (canary pair + instant revert) worked exactly as designed. Spend ≈$4-8 of ≤$20.", "checks": "Canary #55 read from job log (3 FAIL lines + summary); reviewer verdict from subagent report; main verified reverted (0 saturationTailUnit refs at 0a498e6)" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (PR: DB easy wins)", "head": "see PR head", - "scope": "User-requested database + process easy-wins pass: read-only Supabase advisor sweep (user-authorized) \u2192 canary-liveness probe + advisor-disposition docs; live mutations withheld for per-item confirmation", - "outcome": "Advisors (live, read-only): security = 1 INFO (document_title_words RLS-no-policy = the deliberate fail-closed pattern \u2014 now comment-documented at the schema block so it is never 'fixed'); performance = ~33 unused-index INFOs + auth connection-strategy note \u2192 docs/db-maintenance.md TRIAGE list with retrieval-surface trgm indexes flagged RAG-protected (dropping = full canary protocol), owner-scoped indexes retained for multi-tenant design, operational candidates deferred (negligible benefit at corpus size). Implemented: ci.yml static-pr warn-only eval-canary staleness probe (actions:read, github-script pinned, >8 days \u2192 warning; never fails) \u2014 needed because #923 (2026-07-19) moved the canary cadence from daily to weekly Sunday 18:00 UTC, where a dropped fire would go unnoticed for a week (the failure-issue step only reacts to runs that happen). CORRECTION (CodeRabbit review on this PR): the initially recorded \"2026-07-20 dropped Sunday fire\" incident did not occur \u2014 2026-07-20 is a Monday; the Sunday 2026-07-19 slot fired as scheduled run #48 (19:03 UTC, success), and under the weekly cron no 2026-07-20 slot existed. Probe stands as proactive hardening, staleness now measured from updated_at with a finite-timestamp guard. Presented for confirmation (NOT implemented): scheduled telemetry retention (purge:query-logs is owner-scoped + unscheduled; needs owner/window/policy decision), auth percentage connection strategy (dashboard config), any index drops.", + "scope": "User-requested database + process easy-wins pass: read-only Supabase advisor sweep (user-authorized) → canary-liveness probe + advisor-disposition docs; live mutations withheld for per-item confirmation", + "outcome": "Advisors (live, read-only): security = 1 INFO (document_title_words RLS-no-policy = the deliberate fail-closed pattern — now comment-documented at the schema block so it is never 'fixed'); performance = ~33 unused-index INFOs + auth connection-strategy note → docs/db-maintenance.md TRIAGE list with retrieval-surface trgm indexes flagged RAG-protected (dropping = full canary protocol), owner-scoped indexes retained for multi-tenant design, operational candidates deferred (negligible benefit at corpus size). Implemented: ci.yml static-pr warn-only eval-canary staleness probe (actions:read, github-script pinned, >8 days → warning; never fails) — needed because #923 (2026-07-19) moved the canary cadence from daily to weekly Sunday 18:00 UTC, where a dropped fire would go unnoticed for a week (the failure-issue step only reacts to runs that happen). CORRECTION (CodeRabbit review on this PR): the initially recorded \"2026-07-20 dropped Sunday fire\" incident did not occur — 2026-07-20 is a Monday; the Sunday 2026-07-19 slot fired as scheduled run #48 (19:03 UTC, success), and under the weekly cron no 2026-07-20 slot existed. Probe stands as proactive hardening, staleness now measured from updated_at with a finite-timestamp guard. Presented for confirmation (NOT implemented): scheduled telemetry retention (purge:query-logs is owner-scoped + unscheduled; needs owner/window/policy decision), auth percentage connection strategy (dashboard config), any index drops.", "checks": "check:github-actions PASS; check:ci-scope PASS; check:function-grants 28/28 PASS; docs:check-links 1034 PASS; supabase-schema vitest 66/66; lint+typecheck+prettier clean; Supabase access read-only only" }, { @@ -20465,7 +20507,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (PR: matcher + artifact follow-ups)", "head": "ab145f6", "scope": "Remaining documented improvements implemented: word-boundary textContainsClinicalTerm + top-10 canary artifact rows", - "outcome": "Matcher: boundaries + internal separators widened to any non-alphanumeric run \u2014 PROVEN strict superset by artifact replay on canary #53 (1,126 term\u00d7alias\u00d7result comparisons, 0 lost matches, 7 gained = exactly the previously-documented punctuation-joined occurrences: treatment,/mood,/(opioid/ptsd.[35]/ciwa-ar \u00d73). More-tolerant measurement cannot fail a passing case \u2192 weekly scheduled canary = free live confirmation. Exported + 3 direct unit-test groups (superset preservation, audit classes incl. line-broken 'ciwa- ar' and 'full-blood-count', substring-inside-word rejections). Artifact: topResultSummary 5\u219210 rows so rr@10/irrelevant@10 metrics' actual inputs are captured \u2014 unblocks the offline irrelevant@10 labeling audit next artifact. docs/rag-behaviour updated to implemented state. Phase E remains gated on separate approval.", + "outcome": "Matcher: boundaries + internal separators widened to any non-alphanumeric run — PROVEN strict superset by artifact replay on canary #53 (1,126 term×alias×result comparisons, 0 lost matches, 7 gained = exactly the previously-documented punctuation-joined occurrences: treatment,/mood,/(opioid/ptsd.[35]/ciwa-ar ×3). More-tolerant measurement cannot fail a passing case → weekly scheduled canary = free live confirmation. Exported + 3 direct unit-test groups (superset preservation, audit classes incl. line-broken 'ciwa- ar' and 'full-blood-count', substring-inside-word rejections). Artifact: topResultSummary 5→10 rows so rr@10/irrelevant@10 metrics' actual inputs are captured — unblocks the offline irrelevant@10 labeling audit next artifact. docs/rag-behaviour updated to implemented state. Phase E remains gated on separate approval.", "checks": "Targeted vitest 59/59; npm run test 3028 passed / 1 known container pdf-budget artifact; lint+typecheck+prettier clean; audit script run recorded above; no provider calls" }, { @@ -20473,7 +20515,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (PR: RAG memory + safeguards)", "head": "see PR head", "scope": "(recorded with Outcome)", - "outcome": "User-directed close-out: durable RAG behaviour memory (docs/rag-behaviour/, 4 files) + AGENTS.md standing protection rules + ENFORCED safeguards \u2014 pr-policy blocking `RAG impact:` gate on protected surfaces (self-tested: undeclared/vague blocked, no-change/canary declarations pass) + source-pin contract test on imputation formulas and release comparator key order (red-proven vs a mutated constant). Confirmation canary #56 (29774459706, reverted main 0a498e6): SUCCESS \u2014 36/36 restored, closing the #55-regression\u2192revert\u2192restore arc live. Phase D complete (D-1 ref input #1003, D-2 eval:trend #1006, D-3 policy \u00a73.1 #1006, D-4 latency in trend rows); remaining documented plans: word-boundary matcher (own PR), irrelevant@10 labeling audit, Phase E (separate approval). Spend \u2248$5-10 of \u2264$20.", + "outcome": "User-directed close-out: durable RAG behaviour memory (docs/rag-behaviour/, 4 files) + AGENTS.md standing protection rules + ENFORCED safeguards — pr-policy blocking `RAG impact:` gate on protected surfaces (self-tested: undeclared/vague blocked, no-change/canary declarations pass) + source-pin contract test on imputation formulas and release comparator key order (red-proven vs a mutated constant). Confirmation canary #56 (29774459706, reverted main 0a498e6): SUCCESS — 36/36 restored, closing the #55-regression→revert→restore arc live. Phase D complete (D-1 ref input #1003, D-2 eval:trend #1006, D-3 policy §3.1 #1006, D-4 latency in trend rows); remaining documented plans: word-boundary matcher (own PR), irrelevant@10 labeling audit, Phase E (separate approval). Spend ≈$5-10 of ≤$20.", "checks": "pr-policy self-test + workflow guard PASS; contract test 4/4 + red-proof; npm run test 3025 passed / 1 known container pdf-budget artifact; lint+typecheck+prettier clean; docs:check-links 1030 refs PASS; check:github-actions PASS" }, { @@ -20481,7 +20523,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (PR: revert Phase C pending review)", "head": "revert of f96217c", "scope": "User-requested revert of #1004 (Phase C saturation-tail primaries): auto-merge fired before the adversarial rag-retrieval-reviewer pass landed; retrieval code returns to the last reviewed state until that verdict is in", - "outcome": "Clean single-commit revert (the documented rollback path \u2014 helpers + 2 expression sites + 1 map call; no schema/config/cache surface). Ledger history rows from f96217c retained (docs are append-only record, not behavior). The 19:44Z post-merge canary dispatched on f96217c completes regardless and stands as Phase C's live validation datapoint; re-land decision = reviewer verdict + that pair result together. Offline state of the reverted change remains fully proven (red-proof + 121/121 + envelope tests).", + "outcome": "Clean single-commit revert (the documented rollback path — helpers + 2 expression sites + 1 map call; no schema/config/cache surface). Ledger history rows from f96217c retained (docs are append-only record, not behavior). The 19:44Z post-merge canary dispatched on f96217c completes regardless and stands as Phase C's live validation datapoint; re-land decision = reviewer verdict + that pair result together. Offline state of the reverted change remains fully proven (red-proof + 121/121 + envelope tests).", "checks": "Revert verified by vitest fast-path suite returning to pre-C 5/5 shape expected in CI; ladder on the revert = hosted pr-required" }, { @@ -20489,47 +20531,47 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted from 5b4098d; PR: E-2 baseline record + instrument fix)", "head": "see PR head", "scope": "(recorded with Outcome)", - "outcome": "ADDENDUM Phase E-2 BASELINE BANKED (canary dispatch #57, run 29786560936, main 5b4098d, answer_case_limit=44): golden retrieval 36/36 green in-run (no-regression net held); eval:quality full-44 RED on exactly two gates \u2014 citation_failure_rate 0.0227 (1/44: neuroleptic-side-effect-escalation \u2014 expected doc never retrieved, generation quality-failed, extractive fallback with 1 citation) and route_ceiling_failure_count 2 (clozapine-anc-withhold-threshold: 13.3s pure retrieval vs 12s extractive budget, RPC 9.3s, zero generation; agitation-arousal-typo-dosing: 25054ms vs 25000ms after provider_timeout ate 22.6s pre-recovery). Green gates: grounded_supported 1.0, unsupported_correct 1.0 (all 14 refusals incl. both prompt-injection probes at 2ms), numeric grounding failures 0, governance danger 0, p95 17.4s. Non-blocking signals: expected_source_hit 0.6136 (both admission-discharge cases miss MHSP.AdmissionCommunityPts.pdf to sibling NMHS/RKPG policies \u2014 labeling-vs-ranking question, \u00a73.1 class), source governance warning rate 0.8182 (metadata debt, waivable class). SYSTEMIC E-3 TARGET: ~9 of 19 generation attempts discarded (fast output fails quality gate \u2192 extractive fallback wins; ~7 cases carry fast_quality_retry_strong\u2192extractive reasons) = ~half of generation latency+spend wasted. Instrument defect found+fixed this PR: targeting step was skipped after the red gate (GitHub failure-skip semantics) \u2192 if: gains !cancelled() so baselines observe red gates. Spend: est ~$1-2 actual (19 OpenAI-request cases; cost rates unset in CI so report shows n/a) of \u2264$20 Phase E envelope. Next: cheap re-dispatch (default limit 8 + answer_quality_eval=true) to bank the skipped 30-case targeting baseline.", + "outcome": "ADDENDUM Phase E-2 BASELINE BANKED (canary dispatch #57, run 29786560936, main 5b4098d, answer_case_limit=44): golden retrieval 36/36 green in-run (no-regression net held); eval:quality full-44 RED on exactly two gates — citation_failure_rate 0.0227 (1/44: neuroleptic-side-effect-escalation — expected doc never retrieved, generation quality-failed, extractive fallback with 1 citation) and route_ceiling_failure_count 2 (clozapine-anc-withhold-threshold: 13.3s pure retrieval vs 12s extractive budget, RPC 9.3s, zero generation; agitation-arousal-typo-dosing: 25054ms vs 25000ms after provider_timeout ate 22.6s pre-recovery). Green gates: grounded_supported 1.0, unsupported_correct 1.0 (all 14 refusals incl. both prompt-injection probes at 2ms), numeric grounding failures 0, governance danger 0, p95 17.4s. Non-blocking signals: expected_source_hit 0.6136 (both admission-discharge cases miss MHSP.AdmissionCommunityPts.pdf to sibling NMHS/RKPG policies — labeling-vs-ranking question, §3.1 class), source governance warning rate 0.8182 (metadata debt, waivable class). SYSTEMIC E-3 TARGET: ~9 of 19 generation attempts discarded (fast output fails quality gate → extractive fallback wins; ~7 cases carry fast_quality_retry_strong→extractive reasons) = ~half of generation latency+spend wasted. Instrument defect found+fixed this PR: targeting step was skipped after the red gate (GitHub failure-skip semantics) → if: gains !cancelled() so baselines observe red gates. Spend: est ~$1-2 actual (19 OpenAI-request cases; cost rates unset in CI so report shows n/a) of ≤$20 Phase E envelope. Next: cheap re-dispatch (default limit 8 + answer_quality_eval=true) to bank the skipped 30-case targeting baseline.", "checks": "Gates this PR: check:github-actions PASS; check:ci-scope PASS; check:gate-manifest PASS; prettier clean. Baseline evidence: job log run 29786560936 (5 failing-case diagnostics + Answer Metrics table read in full)" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted from e6cd6cb; PR: telemetry-retention correction)", "head": "01368ff (+0144e69 main merge-in)", - "scope": "User-directed \"implement your recommendation for all decisions\" close-out: the scheduled-retention recommendation is RETRACTED as founded on a false premise \u2014 telemetry retention is ALREADY ACTIVE inside the database via pg_cron; docs corrected, nothing built, no live mutations", - "outcome": "Fresh read-only cron.job verification (2026-07-20) matches docs/privacy-impact-assessment.md \u00a76 exactly: jobid 11 purge-expired-rag-queries daily 03:30 (30d), jobid 12 purge-rag-retrieval-logs daily 03:00 (90d), jobid 13 purge-rag-query-misses daily 03:45 (90d), jobid 16 purge-rag-response-cache hourly (bounded 1000); v3 worker jobs present-inactive under backlog auto-toggle (jobid 10); obsolete unbounded cache job absent; audit_logs indefinite by design. db-maintenance.md \"open decision\" section replaced with the resolved state; purge:query-logs clarified as the MANUAL owner-scoped tool (not the retention mechanism). A GitHub-side weekly deleter would have duplicated pg_cron with window drift (a 90d rag_queries sweep can never out-delete the live 30d job). Remaining decisions stand as documented no-action: auth percentage connection strategy deferred to next instance resize; operational index drops not recommended.", + "scope": "User-directed \"implement your recommendation for all decisions\" close-out: the scheduled-retention recommendation is RETRACTED as founded on a false premise — telemetry retention is ALREADY ACTIVE inside the database via pg_cron; docs corrected, nothing built, no live mutations", + "outcome": "Fresh read-only cron.job verification (2026-07-20) matches docs/privacy-impact-assessment.md §6 exactly: jobid 11 purge-expired-rag-queries daily 03:30 (30d), jobid 12 purge-rag-retrieval-logs daily 03:00 (90d), jobid 13 purge-rag-query-misses daily 03:45 (90d), jobid 16 purge-rag-response-cache hourly (bounded 1000); v3 worker jobs present-inactive under backlog auto-toggle (jobid 10); obsolete unbounded cache job absent; audit_logs indefinite by design. db-maintenance.md \"open decision\" section replaced with the resolved state; purge:query-logs clarified as the MANUAL owner-scoped tool (not the retention mechanism). A GitHub-side weekly deleter would have duplicated pg_cron with window drift (a 90d rag_queries sweep can never out-delete the live 30d job). Remaining decisions stand as documented no-action: auth percentage connection strategy deferred to next instance resize; operational index drops not recommended.", "checks": "prettier + docs:check-links PASS; Supabase access read-only (single cron.job SELECT, user-authorized read-only envelope); no workflow/schema/config changes" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted from f33890a; PR: Phase E instrument input)", "head": "see PR head + follow-up SHA pin", - "scope": "Phase E kickoff (user-approved with budget): eval-canary gains opt-in `answer_quality_eval` dispatch input running the 30-case eval:answer-quality fixture (5 quality metrics + per-intent targeting) \u2014 the instrument was previously never run in CI. Dispatch-only, default-off, informational (exit 0, no --targeting-floor): scheduled runs and existing dispatch shapes byte-identical; gates stay owned by eval:quality. Follows the #1003 input-only precedent.", - "outcome": "E-1 recon (all $0/read-only) recorded here: canary answer gate samples only 8 of 44 eval:quality cases (ANSWER_CASE_LIMIT default); eval:quality --provider-mode offline is a real $0 harness (provider deleted, deterministic source-only path) usable as an E-3 regression guard; live 30-day answer telemetry (34 answer-path rows): 25 full answers, misses = evidence_gap \u00d74 (avg 26s spent before gap), provider_incomplete_max_output_tokens \u00d72 (avg 82s wasted then discarded), provider_generation_failed \u00d71, retrieval_gap_or_conflict \u00d71, source_only_no_api \u00d71; success latency avg 13.1s / p90 25.2s. Headroom classes for E-3: truncation waste (rag.ts:4265 self-heal insufficient live), late evidence-gap detection, p90 latency, thin CI answer coverage. Next: E-2 baseline dispatch (answer_case_limit=44 + answer_quality_eval=true, est $3-8 of user-authorized \u2264$20 Phase E envelope) after this merges.", - "checks": "check:github-actions PASS; check:ci-scope PASS; check:gate-manifest PASS; prettier clean; no provider calls this PR (workflow change only); RAG impact: none \u2014 retrieval steps untouched" + "scope": "Phase E kickoff (user-approved with budget): eval-canary gains opt-in `answer_quality_eval` dispatch input running the 30-case eval:answer-quality fixture (5 quality metrics + per-intent targeting) — the instrument was previously never run in CI. Dispatch-only, default-off, informational (exit 0, no --targeting-floor): scheduled runs and existing dispatch shapes byte-identical; gates stay owned by eval:quality. Follows the #1003 input-only precedent.", + "outcome": "E-1 recon (all $0/read-only) recorded here: canary answer gate samples only 8 of 44 eval:quality cases (ANSWER_CASE_LIMIT default); eval:quality --provider-mode offline is a real $0 harness (provider deleted, deterministic source-only path) usable as an E-3 regression guard; live 30-day answer telemetry (34 answer-path rows): 25 full answers, misses = evidence_gap ×4 (avg 26s spent before gap), provider_incomplete_max_output_tokens ×2 (avg 82s wasted then discarded), provider_generation_failed ×1, retrieval_gap_or_conflict ×1, source_only_no_api ×1; success latency avg 13.1s / p90 25.2s. Headroom classes for E-3: truncation waste (rag.ts:4265 self-heal insufficient live), late evidence-gap detection, p90 latency, thin CI answer coverage. Next: E-2 baseline dispatch (answer_case_limit=44 + answer_quality_eval=true, est $3-8 of user-authorized ≤$20 Phase E envelope) after this merges.", + "checks": "check:github-actions PASS; check:ci-scope PASS; check:gate-manifest PASS; prettier clean; no provider calls this PR (workflow change only); RAG impact: none — retrieval steps untouched" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted; PR #1001: A-PR-2 measurement-floor completion)", "head": "3d8f798 + 5b664f8 + e58c827", - "scope": "First provenance-stamped snapshot regeneration from a live canary artifact + alias tiering docs + fixture-length pin + lithium doc-gate \u2014 Phase A of ADDENDUM 4 functionally complete", - "outcome": "Artifact chain: user-authorized paid dispatch (canary #53, run 29763761133, 36/36 green, doc_recall 1.0 / content_recall 1.0 \u2014 first perfect content recall, ciwa alias confirmed live; mrr@10 0.8644, irrelevant@10 0.1083) emitted the first eval-canary-output artifact (51787 bytes, sha256 5af5b802\u2026 verified byte-identical after user transfer into the sandbox \u2014 this container cannot download run artifacts). Work: (1) two-tier alias documentation \u2014 investigation of the governance-review P3 showed src/lib/eval-document-matching.ts is a deliberately WIDER captured-case tier (e.g. \"Clozapine GP Shared Care\"); bulk-merge would loosen golden ground truth, so both files now carry cross-referencing do-not-merge headers instead; (2) snapshot case count pinned to live golden fixture length (regeneration instructions in failure message) \u2014 closes the coarse-floor P3; (3) snapshot regenerated via the alias-aware builder with --source-run-id provenance: agitation-im-po-options 0\u21925 graded positives (EMHS alias working on real data), flowchart-next-step confirmed sole zero-positive case; generatedAt promoted to validator-REQUIRED (closes the hand-edit P3); two stale data pins updated (missing-positives 2\u21921; broad_summary defaults-equality pin dropped \u2014 defaults' provenance was the retired snapshot, fresh recommendations are Phase B input); (4) artifact-grounded punctuation audit: 7 joined-token occurrences in top-5 previews \u2014 3 ciwa-ar (alias-covered, incl. line-broken \"ciwa- ar\"), 4 ORDINARY-PROSE punctuation (\"treatment,\" / \"mood,\" / \"(opioid\" / \"ptsd.[35]\") \u2014 matcher word-boundary change proposed as its OWN reviewed follow-up per plan (systemic class, not bundled); (5) lithium-therapy-monitoring was the ONLY ungated case (rr@10 hardcoded 0.00 = measurement noise): expectedDocumentSubstrings [\"Lithium\"] added from live evidence (deliberately broad across the corpus's multiple legitimate lithium guidelines), snapshot rebuilt in lockstep from the same artifact, measured mrr@10 +~0.028 from de-noising. Deferred with reasons: NEW-query fixture cases (saturated-tie shapes, captured rag_query_misses) need live validation before they may gate \u2014 unlocked by Phase D-1 branch-eval dispatch or a dedicated validation dispatch; real ordering headroom for Phase B = flowchart 0.20, alcohol-ciwa 0.25, patient-safety 0.33, opioid 0.33, all text_fast_path.", - "checks": "Targeted vitest 76/76 \u00d73 (after each stage); npm run test 3019 passed / 1 known container-only pdf-budget artifact; prettier clean; freshness gate ACTIVE and green; no provider calls beyond the user-authorized dispatch (~$1-2, ADDENDUM 4 spend now ~$1-2 of \u2264$10)" + "scope": "First provenance-stamped snapshot regeneration from a live canary artifact + alias tiering docs + fixture-length pin + lithium doc-gate — Phase A of ADDENDUM 4 functionally complete", + "outcome": "Artifact chain: user-authorized paid dispatch (canary #53, run 29763761133, 36/36 green, doc_recall 1.0 / content_recall 1.0 — first perfect content recall, ciwa alias confirmed live; mrr@10 0.8644, irrelevant@10 0.1083) emitted the first eval-canary-output artifact (51787 bytes, sha256 5af5b802… verified byte-identical after user transfer into the sandbox — this container cannot download run artifacts). Work: (1) two-tier alias documentation — investigation of the governance-review P3 showed src/lib/eval-document-matching.ts is a deliberately WIDER captured-case tier (e.g. \"Clozapine GP Shared Care\"); bulk-merge would loosen golden ground truth, so both files now carry cross-referencing do-not-merge headers instead; (2) snapshot case count pinned to live golden fixture length (regeneration instructions in failure message) — closes the coarse-floor P3; (3) snapshot regenerated via the alias-aware builder with --source-run-id provenance: agitation-im-po-options 0→5 graded positives (EMHS alias working on real data), flowchart-next-step confirmed sole zero-positive case; generatedAt promoted to validator-REQUIRED (closes the hand-edit P3); two stale data pins updated (missing-positives 2→1; broad_summary defaults-equality pin dropped — defaults' provenance was the retired snapshot, fresh recommendations are Phase B input); (4) artifact-grounded punctuation audit: 7 joined-token occurrences in top-5 previews — 3 ciwa-ar (alias-covered, incl. line-broken \"ciwa- ar\"), 4 ORDINARY-PROSE punctuation (\"treatment,\" / \"mood,\" / \"(opioid\" / \"ptsd.[35]\") — matcher word-boundary change proposed as its OWN reviewed follow-up per plan (systemic class, not bundled); (5) lithium-therapy-monitoring was the ONLY ungated case (rr@10 hardcoded 0.00 = measurement noise): expectedDocumentSubstrings [\"Lithium\"] added from live evidence (deliberately broad across the corpus's multiple legitimate lithium guidelines), snapshot rebuilt in lockstep from the same artifact, measured mrr@10 +~0.028 from de-noising. Deferred with reasons: NEW-query fixture cases (saturated-tie shapes, captured rag_query_misses) need live validation before they may gate — unlocked by Phase D-1 branch-eval dispatch or a dedicated validation dispatch; real ordering headroom for Phase B = flowchart 0.20, alcohol-ciwa 0.25, patient-safety 0.33, opioid 0.33, all text_fast_path.", + "checks": "Targeted vitest 76/76 ×3 (after each stage); npm run test 3019 passed / 1 known container-only pdf-budget artifact; prettier clean; freshness gate ACTIVE and green; no provider calls beyond the user-authorized dispatch (~$1-2, ADDENDUM 4 spend now ~$1-2 of ≤$10)" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted; PR: #901 rerank regression closeout)", "head": "fd5dcd1582e1c7aa8bf92ff097575e0c68aa930d", "scope": "#901 rerank regression: baseline re-eval + offline guard net + saturated-tie fix", - "outcome": "Baseline eval-canary dispatch on remediated main b3ae061 (run 29731533081) PASSED \u2014 golden retrieval 36/36 + answer-quality green, confirming #913-#926 closed the live 4/36 regression (July 19 failing run tested the raw #901 state; fixes landed 1-8h after it, never re-evaled until now). Residual defect found by new offline repro and fixed: with byte-identical imputed fast-path primaries, selection's clamped keys tie exactly and the chunk-id fallback decides, which secondStageScore's position adjustment launders into releaseRankScore (buried the CIWA answer doc in repro); fix = contentRankScore carried on RetrievalCandidate as tie-break between clamped rerankScore and chunk id, never added to scores. Amended #901's own never-live-validated saturated-tie pin to content-rank-then-id. Guards: tests/rag-fast-path-ordering.test.ts (4 end-to-end eval-shape repros) + ranking-tuning gates (4 golden-mapped hard negatives at production weights + full-snapshot high-risk). Fixture aliases NOT changed (Step C not triggered \u2014 identity cases pass live).", + "outcome": "Baseline eval-canary dispatch on remediated main b3ae061 (run 29731533081) PASSED — golden retrieval 36/36 + answer-quality green, confirming #913-#926 closed the live 4/36 regression (July 19 failing run tested the raw #901 state; fixes landed 1-8h after it, never re-evaled until now). Residual defect found by new offline repro and fixed: with byte-identical imputed fast-path primaries, selection's clamped keys tie exactly and the chunk-id fallback decides, which secondStageScore's position adjustment launders into releaseRankScore (buried the CIWA answer doc in repro); fix = contentRankScore carried on RetrievalCandidate as tie-break between clamped rerankScore and chunk id, never added to scores. Amended #901's own never-live-validated saturated-tie pin to content-rank-then-id. Guards: tests/rag-fast-path-ordering.test.ts (4 end-to-end eval-shape repros) + ranking-tuning gates (4 golden-mapped hard negatives at production weights + full-snapshot high-risk). Fixture aliases NOT changed (Step C not triggered — identity cases pass live).", "checks": "Targeted 4-suite vitest 37/37; npm run test 2981 passed (sole fail = container-only pdf-extraction-budget artifact); verify:cheap green through all 18 pre-test checks incl. lint+typecheck; check:production-readiness PASS on substantive checks (2 FAILs = documented missing-secret class in this container); build + client-bundle scan + check:rag:fixtures PASS" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted; PR: B-PR-1 canary dispatch inputs)", "head": "see PR head", - "scope": "eval-canary.yml workflow_dispatch gains rag_ranking_config (staged Phase B weight evals, loud malformed-JSON validation to prevent silent fallback corrupting pair comparisons) + ref (Phase D-1 pre-merge branch evals) \u2014 schedule runs unaffected (empty inputs = today's behavior)", - "outcome": "Tuner (offline, $0) on the A-PR-2 regenerated snapshot recommends 3 constrained per-class improvements (document_lookup titleSectionRelevance\u21920.9; table_threshold clinicalEvidence\u21920.95; comparison hybridRelevance\u21920.95 with proxy mrr 0.833\u21921.0), all with recall non-regression + zero high-risk hard-negative failures; medication_dose_risk + broad_summary stay neutral. Staged config JSON banked for the live pair; baseline = canary #53 re-gated (mrr@10 \u22480.8922 after lithium de-noising). Targets per approved plan: mrr@10 \u22650.90, irrelevant@10 \u22640.08, zero case regressions. Budget: user raised cap to \u2264$20 (spent \u2248$1-2). Security note: ref input runs branch code with eval secrets \u2014 dispatch requires repo write access (sole trusted collaborator), documented in PR risk.", + "scope": "eval-canary.yml workflow_dispatch gains rag_ranking_config (staged Phase B weight evals, loud malformed-JSON validation to prevent silent fallback corrupting pair comparisons) + ref (Phase D-1 pre-merge branch evals) — schedule runs unaffected (empty inputs = today's behavior)", + "outcome": "Tuner (offline, $0) on the A-PR-2 regenerated snapshot recommends 3 constrained per-class improvements (document_lookup titleSectionRelevance→0.9; table_threshold clinicalEvidence→0.95; comparison hybridRelevance→0.95 with proxy mrr 0.833→1.0), all with recall non-regression + zero high-risk hard-negative failures; medication_dose_risk + broad_summary stay neutral. Staged config JSON banked for the live pair; baseline = canary #53 re-gated (mrr@10 ≈0.8922 after lithium de-noising). Targets per approved plan: mrr@10 ≥0.90, irrelevant@10 ≤0.08, zero case regressions. Budget: user raised cap to ≤$20 (spent ≈$1-2). Security note: ref input runs branch code with eval secrets — dispatch requires repo write access (sole trusted collaborator), documented in PR risk.", "checks": "check:github-actions PASS; check:ci-scope PASS; prettier clean; no provider calls (workflow change only)" }, { @@ -20537,63 +20579,63 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted; PR: ci.yml concurrency)", "head": "79aaacf04e64f753c480dd957a81ac9be6acbb43", "scope": "CI workflow concurrency: stop main churn cancelling dispatch/schedule runs", - "outcome": "One-line group expression: workflow_dispatch/schedule events now get a per-run concurrency group (github.run_id) while push/PR keep the shared ref group with cancel-in-progress \u2014 fixes the release-browser-matrix livelock (cancelled twice on 2026-07-19/20 by main merges mid-run; the weekly Sunday 18:00 UTC scheduled run was subject to the same cancellation). release-browser-matrix is not a required branch-protection check; pin/scope checkers do not constrain the concurrency block. Accepted side effect: deliberate runs can overlap push runs. Rollback: plain revert.", + "outcome": "One-line group expression: workflow_dispatch/schedule events now get a per-run concurrency group (github.run_id) while push/PR keep the shared ref group with cancel-in-progress — fixes the release-browser-matrix livelock (cancelled twice on 2026-07-19/20 by main merges mid-run; the weekly Sunday 18:00 UTC scheduled run was subject to the same cancellation). release-browser-matrix is not a required branch-protection check; pin/scope checkers do not constrain the concurrency block. Accepted side effect: deliberate runs can overlap push runs. Rollback: plain revert.", "checks": "check:github-actions PASS; check:ci-scope PASS; format:check PASS (repo files; local-only .claude/settings.local.json warning is gitignored)" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted; PR: coverage tie-break follow-up)", "head": "57ec880b306a8e2b31c5f20dacc47256fc93b4e2", - "scope": "Post-merge live-eval finding on #982 + corrective fix: saturated-tie key rankScore \u2192 query-term coverage", - "outcome": "Post-#982 golden dispatch (eval-canary run #50, 29735004222, main b9057f0 + deps) came back 35/36: the three verifiable July-19 failures (lithium-therapy-monitoring, clozapine-anc-threshold, patient-safety-plan-include) all PASS live, but alcohol-ciwa-threshold flipped pass\u2192FAIL vs the same-morning pre-#982 run #49 (29731533081, 36/36) \u2014 failing top-3 ordered by descending rankScore (1.85/1.75/1.53, all finalScore-saturated, releaseRankScore 1.09/1.086/1.07), i.e. #982's tie-break let generic clinicalSignalBoost stacking outvote the ciwa/score/threshold-bearing chunk; #982 is the only retrieval-path delta in the window. Fix: contentRankScore \u2192 contentCoverageScore sourced from lexicalCoverageScore (query-term coverage, immune to boost stacking; ties still fall to chunk id); saturated-tie contract test re-pinned so coverage beats a HIGHER rankScore (discriminating \u2014 old key fails it); fast-path CIWA guard gains the run-#50 screening-chunk shape + content-term assertion. Live validation: tonight's 18:00 UTC scheduled canary (dispatch cap 2/2 spent \u2248$2-4). Separately: ci.yml dispatch 4012 survived 30+ min of main churn under #979's per-run concurrency group (fix working); duplicate dispatch 4017 cancelled.", + "scope": "Post-merge live-eval finding on #982 + corrective fix: saturated-tie key rankScore → query-term coverage", + "outcome": "Post-#982 golden dispatch (eval-canary run #50, 29735004222, main b9057f0 + deps) came back 35/36: the three verifiable July-19 failures (lithium-therapy-monitoring, clozapine-anc-threshold, patient-safety-plan-include) all PASS live, but alcohol-ciwa-threshold flipped pass→FAIL vs the same-morning pre-#982 run #49 (29731533081, 36/36) — failing top-3 ordered by descending rankScore (1.85/1.75/1.53, all finalScore-saturated, releaseRankScore 1.09/1.086/1.07), i.e. #982's tie-break let generic clinicalSignalBoost stacking outvote the ciwa/score/threshold-bearing chunk; #982 is the only retrieval-path delta in the window. Fix: contentRankScore → contentCoverageScore sourced from lexicalCoverageScore (query-term coverage, immune to boost stacking; ties still fall to chunk id); saturated-tie contract test re-pinned so coverage beats a HIGHER rankScore (discriminating — old key fails it); fast-path CIWA guard gains the run-#50 screening-chunk shape + content-term assertion. Live validation: tonight's 18:00 UTC scheduled canary (dispatch cap 2/2 spent ≈$2-4). Separately: ci.yml dispatch 4012 survived 30+ min of main churn under #979's per-run concurrency group (fix working); duplicate dispatch 4017 cancelled.", "checks": "Targeted vitest 38/38; npm run test 3012 passed / 1 known container-only pdf-budget artifact; verify:cheap green to the same artifact; build + client-bundle scan + check:rag:fixtures PASS; check:production-readiness expected missing-secret FAILs only (no secrets in container)" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted; PR: eval measurement floor, ADDENDUM 4 A-PR-1)", "head": "81ab9696da4b330ca0b2e5519891a9942f90421b", - "scope": "Measurement floor for evidence-gated ranking tuning: canary artifact emission, alias-aware snapshot builder, snapshot provenance/freshness \u2014 no ranking behavior change", - "outcome": "Closes the three gaps blocking safe tuning (Phase B): (1) eval-canary's golden step now writes the per-case JSON artifact (--json-out decoupled from --json so the tee'd log keeps the human-readable lines the failure-issue analyzer parses) and uploads .local/eval-canary/ via pinned upload-artifact (30-day retention, include-hidden-files for the dot-dir, contents = same class as the already-public step logs: titles/telemetry/220-char previews of the all-public corpus) \u2014 snapshot regeneration stops costing a paid dispatch; (2) clinicalDocumentAliases/clinicalContentAliases moved verbatim to shared scripts/lib/clinical-aliases.ts and the snapshot builder grades documentMatch/contentMatch through them (discriminating tests: EMHS agitation title and spelled-out \"absolute neutrophil count\" grade as hits only via aliases \u2014 raw labelMatches pinned false), ending tuner ground truth disagreeing with the live gates; (3) snapshots carry generatedAt + optional sourceRunId, validator accepts them, exactly-36 relaxed to at-least-36 (floor still rejects truncated artifacts; sourceCaseCount + per-case candidate minimums unchanged), and a 30-day freshness test (activates on first regeneration) blocks silent corpus drift. Builder smoke-verified end-to-end on a synthetic 36-case artifact (alias grading + provenance stamped + validator green). Static hyphen audit of all 36 cases' terms: no currently-blocked term (canary #52 = 36/36); residual risk classes documented for the A-PR-2 artifact-grounded pass \u2014 punctuation-joined tokens (IM/PO, schizo-affective, post-natal) and inert stem entries (obsess/compuls/hyperactiv/impuls can never match whole-token) that currently ride on whole-word OR-alternates.", - "checks": "Targeted vitest 52/52 (ranking-tuning + eval-retrieval + eval-quality); npm run test 3019 passed / 1 known container-only pdf-budget artifact; lint + typecheck clean; check:github-actions + check:ci-scope PASS; prettier clean; check:production-readiness expected missing-secret FAILs only (demo-mode container); no provider calls \u2014 live validation = tonight's scheduled canary emits the first artifact at $0" + "scope": "Measurement floor for evidence-gated ranking tuning: canary artifact emission, alias-aware snapshot builder, snapshot provenance/freshness — no ranking behavior change", + "outcome": "Closes the three gaps blocking safe tuning (Phase B): (1) eval-canary's golden step now writes the per-case JSON artifact (--json-out decoupled from --json so the tee'd log keeps the human-readable lines the failure-issue analyzer parses) and uploads .local/eval-canary/ via pinned upload-artifact (30-day retention, include-hidden-files for the dot-dir, contents = same class as the already-public step logs: titles/telemetry/220-char previews of the all-public corpus) — snapshot regeneration stops costing a paid dispatch; (2) clinicalDocumentAliases/clinicalContentAliases moved verbatim to shared scripts/lib/clinical-aliases.ts and the snapshot builder grades documentMatch/contentMatch through them (discriminating tests: EMHS agitation title and spelled-out \"absolute neutrophil count\" grade as hits only via aliases — raw labelMatches pinned false), ending tuner ground truth disagreeing with the live gates; (3) snapshots carry generatedAt + optional sourceRunId, validator accepts them, exactly-36 relaxed to at-least-36 (floor still rejects truncated artifacts; sourceCaseCount + per-case candidate minimums unchanged), and a 30-day freshness test (activates on first regeneration) blocks silent corpus drift. Builder smoke-verified end-to-end on a synthetic 36-case artifact (alias grading + provenance stamped + validator green). Static hyphen audit of all 36 cases' terms: no currently-blocked term (canary #52 = 36/36); residual risk classes documented for the A-PR-2 artifact-grounded pass — punctuation-joined tokens (IM/PO, schizo-affective, post-natal) and inert stem entries (obsess/compuls/hyperactiv/impuls can never match whole-token) that currently ride on whole-word OR-alternates.", + "checks": "Targeted vitest 52/52 (ranking-tuning + eval-retrieval + eval-quality); npm run test 3019 passed / 1 known container-only pdf-budget artifact; lint + typecheck clean; check:github-actions + check:ci-scope PASS; prettier clean; check:production-readiness expected missing-secret FAILs only (demo-mode container); no provider calls — live validation = tonight's scheduled canary emits the first artifact at $0" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted; PR: matrix-remainder fixes)", "head": "ec070ccb20b9a067216e64e8399d9cd795027024", "scope": "Run-4012 remainder: 7 root-caused fixes (SW navigation hijack, WebKit focus/forced-colors/stale-style, Firefox tab order, CIWA alias, helper extraction)", - "outcome": "Agent-diagnosed with probe evidence: (1) production-build PWA worker registers in EVERY matrix test (pwa-lifecycle.tsx:287 NODE_ENV gate), clients.claim()s the page and serves all navigations \u2014 Chromium probe proved SW-served reloads bypass page.route entirely (routeSawNav=[]); Playwright-Firefox wedges on its only two reloads (ui-smoke 2206/2932, both deterministic) \u2192 playwright.config.ts serviceWorkers:'block' + ui-pwa 'allow' opt-in (offline/CacheStorage journey verified passing locally under the opt-in). (2) Mode-menu dismissal relied solely on wrapper focusout; WebKit Tab navigation can move focus nowhere (links excluded) or wrap into the menu \u2192 keydown Tab-close in handleModeTriggerKeyDown (agent verified no test depends on old forward-Tab behavior). (3) WebKit has no forced-colors implementation \u2192 capability skip on the token-remap test. (4) WebKit stale :disabled computed style feeds axe a phantom 1.93 contrast for the re-enabled Previous button (blend arithmetic exact: 0.4\u00d7#475467+0.6\u00d7#fff=#b5bbc2) \u2192 toBeEnabled+opacity-1 pin before the scan, failure-at-pin = direct proof. (5) Firefox includes scrollable containers in tab order (sheet body scrollHeight 1125 vs 707 measured) \u2192 conditional step-over. (6) canary #50/#51 CIWA failure root cause: whitespace-delimited textContainsClinicalTerm can never match hyphenated 'CIWA-Ar' though the dosing-table region ranks top-5 \u2192 clinicalContentAliases ciwa:[ciwa, ciwa-ar] (plan-authorized fixture-alias route; content substance unchanged). (7) tests/helpers/zero-touch.ts shared helper replaces six #995 inline stubs (CodeRabbit follow-up). NOT claimed: ui-stress 409 overflow, ui-tools 2087 navigation race, webkit answer-flow subset \u2014 next matrix run (post-merge dispatch) measures these vs the 28-failure baseline; ui-smoke 2932 webkit-side is a distinct mock-data class deliberately deferred pending that run.", - "checks": "Targeted vitest 25/25 (eval-retrieval + search-command-surface); npm run test 3012 passed / 1 known container pdf-budget artifact; verify:cheap green to same artifact; build + client-bundle scan PASS; prettier/eslint/typecheck clean; chromium ui-pwa under new SW config: offline/CacheStorage privacy journey PASS, installability = known container in-incognito artifact; UI verification not run locally beyond that: chromium ui suites carry documented container artifacts \u2014 hosted ui-critical/ui-advisory + next matrix authoritative" + "outcome": "Agent-diagnosed with probe evidence: (1) production-build PWA worker registers in EVERY matrix test (pwa-lifecycle.tsx:287 NODE_ENV gate), clients.claim()s the page and serves all navigations — Chromium probe proved SW-served reloads bypass page.route entirely (routeSawNav=[]); Playwright-Firefox wedges on its only two reloads (ui-smoke 2206/2932, both deterministic) → playwright.config.ts serviceWorkers:'block' + ui-pwa 'allow' opt-in (offline/CacheStorage journey verified passing locally under the opt-in). (2) Mode-menu dismissal relied solely on wrapper focusout; WebKit Tab navigation can move focus nowhere (links excluded) or wrap into the menu → keydown Tab-close in handleModeTriggerKeyDown (agent verified no test depends on old forward-Tab behavior). (3) WebKit has no forced-colors implementation → capability skip on the token-remap test. (4) WebKit stale :disabled computed style feeds axe a phantom 1.93 contrast for the re-enabled Previous button (blend arithmetic exact: 0.4×#475467+0.6×#fff=#b5bbc2) → toBeEnabled+opacity-1 pin before the scan, failure-at-pin = direct proof. (5) Firefox includes scrollable containers in tab order (sheet body scrollHeight 1125 vs 707 measured) → conditional step-over. (6) canary #50/#51 CIWA failure root cause: whitespace-delimited textContainsClinicalTerm can never match hyphenated 'CIWA-Ar' though the dosing-table region ranks top-5 → clinicalContentAliases ciwa:[ciwa, ciwa-ar] (plan-authorized fixture-alias route; content substance unchanged). (7) tests/helpers/zero-touch.ts shared helper replaces six #995 inline stubs (CodeRabbit follow-up). NOT claimed: ui-stress 409 overflow, ui-tools 2087 navigation race, webkit answer-flow subset — next matrix run (post-merge dispatch) measures these vs the 28-failure baseline; ui-smoke 2932 webkit-side is a distinct mock-data class deliberately deferred pending that run.", + "checks": "Targeted vitest 25/25 (eval-retrieval + search-command-surface); npm run test 3012 passed / 1 known container pdf-budget artifact; verify:cheap green to same artifact; build + client-bundle scan PASS; prettier/eslint/typecheck clean; chromium ui-pwa under new SW config: offline/CacheStorage privacy journey PASS, installability = known container in-incognito artifact; UI verification not run locally beyond that: chromium ui suites carry documented container artifacts — hosted ui-critical/ui-advisory + next matrix authoritative" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted; PR: Phase C saturation-tail primaries)", "head": "7572c7f", - "scope": "ADDENDUM 4 Phase C (user-authorized): per-candidate discriminative primaries for saturated fast-path ties \u2014 design-agent planned (consumer map + dead-band envelope proof), red-proven, tie-conservation guarded", - "outcome": "Mechanism: min(text_rank,1) collapses all tr\u22651 candidates to byte-identical imputed primaries; ordering fell to chunk id at release. Fix: saturationTailUnit (pure, monotone, SET-INDEPENDENT \u2014 rejected per-query min-max + rank-tier designs for set-dependence/#118 authority risk; rejected full-range log rescale for moving sub-knee values across the 0.62-0.82 gate ladder) scales the excess into DEAD cap bands only: S2 table-fact similarity (0.92, 0.94) with hybrid byte-identical (gates/triggers/selection provably unchanged; similarity = the release tie-break key), S1 lexical-chunk hybrid (0.48, 0.5) behind the truthful-contract signature (sub-0.5 bars hold). Sub-knee byte-identical (fixtures now DERIVE from the helper; 0.45\u21920.755/0.795 pinned). Discriminating test verified RED on old formulas (2 fail: discriminating + envelope) \u2192 green with tail; equal-tr tie-conservation pins the #987 coverage comparator; second-stage-engaged pools documented out of scope (position-derived releaseRankScore sorts first there) \u2014 matches live evidence that non-engaged pools (patient-safety, opioid, flowchart) are where id-order decided. S3/S4 = C-PR-2 candidates, evidence-gated on the post-merge canary vs #54 baseline (doc/content recall MUST stay 1.0, zero per-case regressions; success signal = rr lift on the headroom cases). Rollback: single revert (helpers + 2 expression sites + 1 map call; no schema/config/cache surface).", + "scope": "ADDENDUM 4 Phase C (user-authorized): per-candidate discriminative primaries for saturated fast-path ties — design-agent planned (consumer map + dead-band envelope proof), red-proven, tie-conservation guarded", + "outcome": "Mechanism: min(text_rank,1) collapses all tr≥1 candidates to byte-identical imputed primaries; ordering fell to chunk id at release. Fix: saturationTailUnit (pure, monotone, SET-INDEPENDENT — rejected per-query min-max + rank-tier designs for set-dependence/#118 authority risk; rejected full-range log rescale for moving sub-knee values across the 0.62-0.82 gate ladder) scales the excess into DEAD cap bands only: S2 table-fact similarity (0.92, 0.94) with hybrid byte-identical (gates/triggers/selection provably unchanged; similarity = the release tie-break key), S1 lexical-chunk hybrid (0.48, 0.5) behind the truthful-contract signature (sub-0.5 bars hold). Sub-knee byte-identical (fixtures now DERIVE from the helper; 0.45→0.755/0.795 pinned). Discriminating test verified RED on old formulas (2 fail: discriminating + envelope) → green with tail; equal-tr tie-conservation pins the #987 coverage comparator; second-stage-engaged pools documented out of scope (position-derived releaseRankScore sorts first there) — matches live evidence that non-engaged pools (patient-safety, opioid, flowchart) are where id-order decided. S3/S4 = C-PR-2 candidates, evidence-gated on the post-merge canary vs #54 baseline (doc/content recall MUST stay 1.0, zero per-case regressions; success signal = rr lift on the headroom cases). Rollback: single revert (helpers + 2 expression sites + 1 map call; no schema/config/cache surface).", "checks": "Targeted vitest 121/121 (fast-path 11/11 incl. 6 new, retrieval-selection, rag-routing, rag-answer-fallback, ranking-tuning, second-stage); npm run test 3025 passed / 1 known container pdf-budget artifact; lint + typecheck + prettier clean; red-proof executed and recorded; live validation = post-merge canary dispatch (~$1-2)" }, { "date": "2026-07-20", "ref": "claude/clinical-kb-pwa-review-asi3wb (restarted; PR: WebKit matrix diagnosis)", "head": "caa298972846ef52d472bfbff98c90fc26481ed8", - "scope": "First completed release-browser-matrix in weeks (run 4012, main b9057f0, 38 min uncancelled under #979) \u2014 full triage of 28 failures + fix for the dominant cluster", - "outcome": "Run 4012: 716 passed / 28 failed (25 webkit, 3 firefox) / 4 skipped. Dominant cluster (root-caused, FIXED here): all 8 ui-universal-search webkit failures share one signature \u2014 typeahead content never enters the DOM \u2014 because commandDropdownCanDisplay (added 42a3e3c 2026-07-17, AFTER the last completed matrix; never ran on WebKit until 4012) requires fine-pointer OR zero-touch; headless browsers fail the (hover:hover)+(pointer:fine) query (proven by the zero-touch escape existing for CI at all), Chromium/Firefox pass via maxTouchPoints===0, and Playwright's Linux WebKit build advertises phantom touch points \u2014 flunking both branches and disabling useUniversalSearch entirely. Fix: beforeEach addInitScript in ui-universal-search/ui-smoke/ui-tools specs stubbing Navigator.prototype.maxTouchPoints to the runner's true 0 (inert on Chromium/Firefox; product gate + tests/search-command-surface.test.ts pins untouched). Local chromium runs of ui-universal-search fail 16/20 IDENTICALLY on unmodified main (container artifact \u2014 hosted CI chromium green in 4012 is authoritative; verified by stash/run/pop baseline). Expected delta next matrix: \u22658 webkit failures clear; candidates ui-tools:1244 + several ui-smoke answer-flow cases (same surface). NOT yet root-caused (triaged remainder, hosted-matrix-only reproduction): webkit ui-stress overflow 330/409 (360px overflow at mobile), webkit ui-accessibility 195/252 (focus dismissal; forced-colors labels), webkit ui-formulation 132, webkit ui-smoke copy-table/retry/recovery/recent-searches/source-only/differential-context/viewer-hydration/document-questions, webkit ui-tools 2087 (goto interrupted by ?q= navigation), webkit ui-universal-search 183 strict-mode duplicate options (fallback-surface rendering; likely clears with the gate fix), firefox ui-smoke 946/2206/2932 (@critical document search fails on BOTH firefox and webkit \u2014 cross-browser, highest-priority remainder).", - "checks": "prettier PASS; eslint PASS; typecheck PASS; chromium stash-baseline no-delta (16 fail pre AND post \u2014 container artifact); webkit validation lands via tonight's 18:00 UTC scheduled matrix" + "scope": "First completed release-browser-matrix in weeks (run 4012, main b9057f0, 38 min uncancelled under #979) — full triage of 28 failures + fix for the dominant cluster", + "outcome": "Run 4012: 716 passed / 28 failed (25 webkit, 3 firefox) / 4 skipped. Dominant cluster (root-caused, FIXED here): all 8 ui-universal-search webkit failures share one signature — typeahead content never enters the DOM — because commandDropdownCanDisplay (added 42a3e3c 2026-07-17, AFTER the last completed matrix; never ran on WebKit until 4012) requires fine-pointer OR zero-touch; headless browsers fail the (hover:hover)+(pointer:fine) query (proven by the zero-touch escape existing for CI at all), Chromium/Firefox pass via maxTouchPoints===0, and Playwright's Linux WebKit build advertises phantom touch points — flunking both branches and disabling useUniversalSearch entirely. Fix: beforeEach addInitScript in ui-universal-search/ui-smoke/ui-tools specs stubbing Navigator.prototype.maxTouchPoints to the runner's true 0 (inert on Chromium/Firefox; product gate + tests/search-command-surface.test.ts pins untouched). Local chromium runs of ui-universal-search fail 16/20 IDENTICALLY on unmodified main (container artifact — hosted CI chromium green in 4012 is authoritative; verified by stash/run/pop baseline). Expected delta next matrix: ≥8 webkit failures clear; candidates ui-tools:1244 + several ui-smoke answer-flow cases (same surface). NOT yet root-caused (triaged remainder, hosted-matrix-only reproduction): webkit ui-stress overflow 330/409 (360px overflow at mobile), webkit ui-accessibility 195/252 (focus dismissal; forced-colors labels), webkit ui-formulation 132, webkit ui-smoke copy-table/retry/recovery/recent-searches/source-only/differential-context/viewer-hydration/document-questions, webkit ui-tools 2087 (goto interrupted by ?q= navigation), webkit ui-universal-search 183 strict-mode duplicate options (fallback-surface rendering; likely clears with the gate fix), firefox ui-smoke 946/2206/2932 (@critical document search fails on BOTH firefox and webkit — cross-browser, highest-priority remainder).", + "checks": "prettier PASS; eslint PASS; typecheck PASS; chromium stash-baseline no-delta (16 fail pre AND post — container artifact); webkit validation lands via tonight's 18:00 UTC scheduled matrix" }, { "date": "2026-07-20", "ref": "claude/phone-scroll-fix (PR #993)", "head": "f0f4c42e7", "scope": "Phone scroll \"locks to bottom\" regression from #964 + all-pages phone scroll audit + guardrails", - "outcome": "Root cause: #964's phone mode-home dock made one hide-on-scroll event release ~180-260px of scroll geometry (header grid collapse + reserve-pad shrink) \u2014 more than a short mode home's remaining runway, so scrollTop clamps onto the new bottom and a 12px up-drag snaps it back (oscillation; measured 266\u219284px runway, 2 flips/gesture on /formulation @390\u00d7844). Invisible to all gates because the suite-wide reducedMotion:\"reduce\" disables the causal transitions. Fix: collapse-budget gate in computeScrollHideUpdate (hosts report the would-be geometry release via readChromeCollapseBudget; hide refused without runway to absorb it; budget-less consumers unchanged; bottom-clamp guard untouched). Bonus latent bug fixed: DocumentViewer's one-shot #main-content discovery could hold a detached node after shell remounts (viewer hide-on-scroll dead); observer now persists. ui-smoke bottom-hide scenario updated to the gate contract. New 18-test sweep tests/ui-phone-scroll.spec.ts (10 mode homes + 3 dashboard modes + 4 long routes, motion enabled, simulated PWA insets) verified to fail red pre-fix. Residual: real-device iOS momentum clamping is device-only \u2014 user PWA confirmation requested post-deploy.", + "outcome": "Root cause: #964's phone mode-home dock made one hide-on-scroll event release ~180-260px of scroll geometry (header grid collapse + reserve-pad shrink) — more than a short mode home's remaining runway, so scrollTop clamps onto the new bottom and a 12px up-drag snaps it back (oscillation; measured 266→84px runway, 2 flips/gesture on /formulation @390×844). Invisible to all gates because the suite-wide reducedMotion:\"reduce\" disables the causal transitions. Fix: collapse-budget gate in computeScrollHideUpdate (hosts report the would-be geometry release via readChromeCollapseBudget; hide refused without runway to absorb it; budget-less consumers unchanged; bottom-clamp guard untouched). Bonus latent bug fixed: DocumentViewer's one-shot #main-content discovery could hold a detached node after shell remounts (viewer hide-on-scroll dead); observer now persists. ui-smoke bottom-hide scenario updated to the gate contract. New 18-test sweep tests/ui-phone-scroll.spec.ts (10 mode homes + 3 dashboard modes + 4 long routes, motion enabled, simulated PWA insets) verified to fail red pre-fix. Residual: real-device iOS momentum clamping is device-only — user PWA confirmation requested post-deploy.", "checks": "vitest focused 24/24 + mobile-composer-reserve; verify:cheap 3020 green; ui-phone-scroll chromium 18/18 + webkit advisory 18/18; ui-formulation+ui-tools+ui-smoke 180/180; verify:ui 264/264; verify:pr-local green (format/build/bundle-scan/RAG fixtures). No provider calls." }, { "date": "2026-07-20", - "ref": "Credentialed release-gate checkpoint closeout (workflow_dispatch on main `7ec25d9`; user-authorized \u2264$10, single dispatch each)", + "ref": "Credentialed release-gate checkpoint closeout (workflow_dispatch on main `7ec25d9`; user-authorized ≤$10, single dispatch each)", "head": "7ec25d9675dea13635fa4a895af88c93da694a42", "scope": "Credentialed half of the release gate: CI dispatch + live eval canary", - "outcome": "CI dispatch: 9/10 jobs green (unit coverage, build, Chromium production journeys, migration replay on local Supabase emulator, production-readiness CI-safe, policy self-tests, static/safety/scope). `release-browser-matrix` (WebKit/Firefox) CANCELLED twice by main-churn: ci.yml `concurrency: CI-${ref}, cancel-in-progress: true` kills in-flight dispatch runs on every main push and this repo merges every few minutes \u2014 livelock confirmed at the 2-attempt cap; WebKit/iOS verification remains outstanding with three human options (quiet-window dispatch, the weekly scheduled run, or a one-line dedicated concurrency group for the matrix job \u2014 operational-risk change, not applied). Eval canary: golden retrieval eval FAILED 4/36 (document_recall@5 0.944, ndcg@10 0.923, force_embedding_failure_count 0, no 429s \u2014 vector layer healthy, NOT the documented vector-ptsd transient class); the July 17 dispatch PASSED this step pre-#901, so the regression window implicates #901's deterministic semantic reranking (lithium-therapy-monitoring shows three unrelated documents with byte-identical rerank scores burying the lithium guideline; two other failures add fixture-vs-corpus identity components; answer-quality subset \u2014 the July 17 failure \u2014 never ran). NO canary re-run per plan (deterministic, not transient); retrieval is clinical-path and deferred to a human decision. Provider spend \u2248 $1\u20132 (one canary run's embeddings); matrix/CI runs $0.", + "outcome": "CI dispatch: 9/10 jobs green (unit coverage, build, Chromium production journeys, migration replay on local Supabase emulator, production-readiness CI-safe, policy self-tests, static/safety/scope). `release-browser-matrix` (WebKit/Firefox) CANCELLED twice by main-churn: ci.yml `concurrency: CI-${ref}, cancel-in-progress: true` kills in-flight dispatch runs on every main push and this repo merges every few minutes — livelock confirmed at the 2-attempt cap; WebKit/iOS verification remains outstanding with three human options (quiet-window dispatch, the weekly scheduled run, or a one-line dedicated concurrency group for the matrix job — operational-risk change, not applied). Eval canary: golden retrieval eval FAILED 4/36 (document_recall@5 0.944, ndcg@10 0.923, force_embedding_failure_count 0, no 429s — vector layer healthy, NOT the documented vector-ptsd transient class); the July 17 dispatch PASSED this step pre-#901, so the regression window implicates #901's deterministic semantic reranking (lithium-therapy-monitoring shows three unrelated documents with byte-identical rerank scores burying the lithium guideline; two other failures add fixture-vs-corpus identity components; answer-quality subset — the July 17 failure — never ran). NO canary re-run per plan (deterministic, not transient); retrieval is clinical-path and deferred to a human decision. Provider spend ≈ $1–2 (one canary run's embeddings); matrix/CI runs $0.", "checks": "actions_run_trigger dispatches + rerun_failed_jobs (attempt 2); job-level conclusions and log excerpts from runs 29675875530 (both attempts), 29675878737 (July 19 canary), and 29567502452 (July 17 baseline). No local provider calls; secrets never left GitHub Actions." }, { @@ -20617,7 +20659,7 @@ "ref": "origin/main PWA-surface review, window `ef042ca..e128384` (44+ commits; explicit user request) + phone install-sheet redesign (this branch, content commit d8d8c4a)", "head": "e1283846647b20cd49ca6ae6920a7c76f2b945d7", "scope": "PWA-version review of new progress + install-notification design elevation", - "outcome": "Sweep verdict (agent-verified): only #905/#897 (this program's own work) touched PWA surfaces in the window \u2014 sw.js CACHE_VERSION `2026-07-18-v1` and its offline.html binding, manifest (7 icons incl. monochrome; screenshots deliberately absent), icons route, kill-switch, and next.config headers all unchanged, so the privacy contract holds by construction. Geometric risk from five composer/dock-space reworks (#933 mobile-composer-reserve, #932, #930, #922, #899) probed live at 390\u00d7844: the non-install notice stack keeps correct clearance at rest (offline card bottom 744/844 with the 5.5rem gutter) and the stack's offset is now a custom property (`--pwa-notice-bottom-gap`) for one-line re-anchoring if composer geometry moves again. Redesign: install prompt + iOS hint present as a native bottom sheet on phones (full-bleed, flush bottom, grip bar matching #935's sheet language, real app icon identity via /icons/icon-192, Free/no-store meta row, two accent step chips for Share\u2192Add to Home Screen as aria-hidden reinforcement of the unchanged accessible sentence); \u2265640px keeps the #905 card/toast placements; region names, button names, and test-locked sentences unchanged.", + "outcome": "Sweep verdict (agent-verified): only #905/#897 (this program's own work) touched PWA surfaces in the window — sw.js CACHE_VERSION `2026-07-18-v1` and its offline.html binding, manifest (7 icons incl. monochrome; screenshots deliberately absent), icons route, kill-switch, and next.config headers all unchanged, so the privacy contract holds by construction. Geometric risk from five composer/dock-space reworks (#933 mobile-composer-reserve, #932, #930, #922, #899) probed live at 390×844: the non-install notice stack keeps correct clearance at rest (offline card bottom 744/844 with the 5.5rem gutter) and the stack's offset is now a custom property (`--pwa-notice-bottom-gap`) for one-line re-anchoring if composer geometry moves again. Redesign: install prompt + iOS hint present as a native bottom sheet on phones (full-bleed, flush bottom, grip bar matching #935's sheet language, real app icon identity via /icons/icon-192, Free/no-store meta row, two accent step chips for Share→Add to Home Screen as aria-hidden reinforcement of the unchanged accessible sentence); ≥640px keeps the #905 card/toast placements; region names, button names, and test-locked sentences unchanged.", "checks": "Focused vitest 56/56 across the four PWA suites; `verify:cheap` 2971/2975 (sole fail = known container-only pdf-extraction-budget artifact); `test:e2e:pwa` privacy/offline green (installability fail = known container `in-incognito` artifact); `verify:ui` 243 passed/2 failed (the two long-baselined container artifacts); production build + client-bundle secret scan + bundle budget within tolerance (1303.4 vs 1278.6 KiB baseline; sheet adds ~0 JS); visual evidence at 390 light/dark/iOS-hint + 768 + 1440 with bounding-box math (full-bleed flush-bottom on phone; card/toast intact above). No provider-backed checks run." }, { @@ -20654,7 +20696,7 @@ }, { "date": "2026-07-19", - "ref": "`origin/main` through PR #903 plus fixed 48-hour PR snapshot (`#689`\u2013`#902`)", + "ref": "`origin/main` through PR #903 plus fixed 48-hour PR snapshot (`#689`–`#902`)", "head": "4034d2e60ebb6616130ff17bf3cb69368f36f8f6", "scope": "whole-repository, all-lens regression and PR-activity review", "outcome": "Changes requested. No P0. Confirmed five P1 defects: stale publication approvals are not bound to reviewed document state; invalid supplied credentials can become anonymous uploads; pooled duplicate uploads expose another uploader's metadata; readiness is fail-open for database usability errors; and settings promise clinical tailoring/alerts with no consumers. Eighteen P2 findings cover semantic rerank effectiveness/privacy, summary prompt trust, PDF resource limits, cancellation, auth-state loss, public storage-path exposure, query validation, provider-boundary/CI/test gaps, factsheet/Therapy behavior, Therapy startup cost, and the PR #903 ledger's incorrect claim that PR #901 has zero unresolved threads. GitHub GraphQL still reports two current unresolved P2 threads on merged PR #901.", @@ -20681,7 +20723,7 @@ "ref": "claude/audit-recent-changes-kde66i (audit-remediation follow-up to the ef042cacd audit row)", "head": "see PR head", "scope": "remediation of the three 2026-07-19 audit findings", - "outcome": "Fixed all three findings from the 24-hour merged-window audit. (1) Inert settings honesty (P2): every preference the app does not yet consume \u2014 jurisdiction, population, answer style, landing, both home-content toggles, compact citations, and all three notification toggles \u2014 now renders an explicit \"Saved for later \u2014 not active yet\" marker in `settings-dialog.tsx`; the functional appearance/density/motion rows stay unmarked. Wiring the preferences into answer generation was deliberately NOT done here (clinical-behavior change requiring governance review); the new dom test documents the contract for flipping a control live. (2) Auth offline resolution (P2/P3): `resolveInitialAuthState` gains `verificationUnavailable`, set from `isAuthRetryableFetchError(getUser().error)`, so an unreachable auth server keeps the stored session signed in while a reachable server that rejects the token still resolves signed_out; server-side bearer validation is unchanged. (3) `/medications` redirect (P3): now preserves the sanitized q/focus/run search context with the same allowlist as the root legacy-mode redirect.", + "outcome": "Fixed all three findings from the 24-hour merged-window audit. (1) Inert settings honesty (P2): every preference the app does not yet consume — jurisdiction, population, answer style, landing, both home-content toggles, compact citations, and all three notification toggles — now renders an explicit \"Saved for later — not active yet\" marker in `settings-dialog.tsx`; the functional appearance/density/motion rows stay unmarked. Wiring the preferences into answer generation was deliberately NOT done here (clinical-behavior change requiring governance review); the new dom test documents the contract for flipping a control live. (2) Auth offline resolution (P2/P3): `resolveInitialAuthState` gains `verificationUnavailable`, set from `isAuthRetryableFetchError(getUser().error)`, so an unreachable auth server keeps the stored session signed in while a reachable server that rejects the token still resolves signed_out; server-side bearer validation is unchanged. (3) `/medications` redirect (P3): now preserves the sanitized q/focus/run search context with the same allowlist as the root legacy-mode redirect.", "checks": "Focused Vitest 30/30 across `settings-inert-preferences.dom` (new), `private-client-auth` (3 new cases), `audit-navigation-auth-regressions` (query-preservation case), `app-preferences`, and `site-map`. Full `verify:cheap` run recorded on the PR. No OpenAI, Supabase, deployment, or provider-backed check ran." }, { @@ -20689,15 +20731,15 @@ "ref": "claude/audit-recent-changes-kde66i (preference wiring + session-start hook follow-up to the #906 remediation)", "head": "see PR head", "scope": "wiring the wireable inert preferences live and fixing the stale-node_modules session-start gap", - "outcome": "Wired three of the seven remaining inert preferences into real behavior and removed their \"Saved for later\" markers: (1) Default landing view \u2014 `GlobalSearchShellClient` applies a one-shot `router.replace` to the saved landing mode (`search`\u2192documents, `browse`\u2192tools via `landingModeForPreference`) on a bare \"/\" load only; explicit mode/query/run params always win, and the dashboard's existing URL-sync effect performs the switch. (2) Recent searches on home \u2014 `AnswerEmptyState` now gates its recent-query chips on `showRecentOnHome`. (3) Compact citations \u2014 the answer source capsule drops its text label to icon+count when `compactCitations` is on, with the \"No direct source found\" warning explicitly exempted so compact mode can never hide a missing-source signal. Still marked inactive with reasons documented in the test contract: jurisdiction/population/answer-style (wiring them into answer generation is provider-eval-gated per the confirmation boundary), saved-protocols-on-home (no protocols module exists), and the three notification toggles (no delivery infrastructure). Separately, `.claude/hooks/session-start.sh` now stamps the `package-lock.json` sha256 into `node_modules/.session-start-lock-hash` after `npm ci` and reinstalls when the lockfile no longer matches, closing the stale-container gap that faked a typecheck regression during the 24h audit.", - "checks": "New `tests/answer-preferences.dom.test.tsx` (recents gate on/off, compact capsule display incl. the missing-source exemption, landing mapping) and the updated `settings-inert-preferences.dom` contract (3 rows moved inert\u2192functional) pass with `app-preferences` and `private-client-auth`: 26/26 focused. Full typecheck, scoped zero-warning ESLint, and the full Vitest suite recorded on the PR; `bash -n` on the hook. `check:production-readiness` not run: no secrets in this container (documented demo-mode expectation) and no answer-generation, retrieval, or source-governance logic changed \u2014 the capsule change is presentational with the missing-source warning locked by test. No OpenAI, Supabase, deployment, or provider-backed check ran." + "outcome": "Wired three of the seven remaining inert preferences into real behavior and removed their \"Saved for later\" markers: (1) Default landing view — `GlobalSearchShellClient` applies a one-shot `router.replace` to the saved landing mode (`search`→documents, `browse`→tools via `landingModeForPreference`) on a bare \"/\" load only; explicit mode/query/run params always win, and the dashboard's existing URL-sync effect performs the switch. (2) Recent searches on home — `AnswerEmptyState` now gates its recent-query chips on `showRecentOnHome`. (3) Compact citations — the answer source capsule drops its text label to icon+count when `compactCitations` is on, with the \"No direct source found\" warning explicitly exempted so compact mode can never hide a missing-source signal. Still marked inactive with reasons documented in the test contract: jurisdiction/population/answer-style (wiring them into answer generation is provider-eval-gated per the confirmation boundary), saved-protocols-on-home (no protocols module exists), and the three notification toggles (no delivery infrastructure). Separately, `.claude/hooks/session-start.sh` now stamps the `package-lock.json` sha256 into `node_modules/.session-start-lock-hash` after `npm ci` and reinstalls when the lockfile no longer matches, closing the stale-container gap that faked a typecheck regression during the 24h audit.", + "checks": "New `tests/answer-preferences.dom.test.tsx` (recents gate on/off, compact capsule display incl. the missing-source exemption, landing mapping) and the updated `settings-inert-preferences.dom` contract (3 rows moved inert→functional) pass with `app-preferences` and `private-client-auth`: 26/26 focused. Full typecheck, scoped zero-warning ESLint, and the full Vitest suite recorded on the PR; `bash -n` on the hook. `check:production-readiness` not run: no secrets in this container (documented demo-mode expectation) and no answer-generation, retrieval, or source-governance logic changed — the capsule change is presentational with the missing-source warning locked by test. No OpenAI, Supabase, deployment, or provider-backed check ran." }, { "date": "2026-07-19", "ref": "claude/clinical-kb-pwa-review-asi3wb (PR #905; commits b2afe66 visuals + 6531178 policy + this ledger follow-up)", "head": "6531178c1a3427dfd58c4bfcf8e29020c5731179", "scope": "PWA install/update notice redesign (all breakpoints) + review-follow-up policy fix", - "outcome": "Redesigned the five PWA notices (install, update, iOS hint, offline, restored) as glass lux cards: per-type semantic icon tiles, heading-ink titles, corner dismiss buttons, reduced-motion-safe 280ms entrance. Deliberate placement per screen size: phones keep the bottom card above the fixed composer (thumb zone, safe areas); \u2265640px floats a 25rem card bottom-right; \u22651280px moves the stack to a top-right toast under the header (same 4.25rem+safe-area offset constant as the mode-menu popover) with the animation direction flipped. Copy, roles, and button names unchanged. Plus the outline-aware pr-policy section parser fix from the same-session review (see the review row above).", + "outcome": "Redesigned the five PWA notices (install, update, iOS hint, offline, restored) as glass lux cards: per-type semantic icon tiles, heading-ink titles, corner dismiss buttons, reduced-motion-safe 280ms entrance. Deliberate placement per screen size: phones keep the bottom card above the fixed composer (thumb zone, safe areas); ≥640px floats a 25rem card bottom-right; ≥1280px moves the stack to a top-right toast under the header (same 4.25rem+safe-area offset constant as the mode-menu popover) with the animation direction flipped. Copy, roles, and button names unchanged. Plus the outline-aware pr-policy section parser fix from the same-session review (see the review row above).", "checks": "Focused vitest pwa-lifecycle.dom 9/9 + pwa-manifest 8/8; `check:pr-policy` self-test green incl. new sub-heading case; `verify:cheap` 2828/2831 (sole fail = known container-only pdf-extraction-budget artifact); `test:e2e:pwa` privacy/offline green (installability fail = known container `in-incognito` artifact); `verify:ui` 236 passed/2 failed (the two long-baselined container artifacts); production build + client-bundle secret scan + bundle budget within tolerance (1293.4 vs 1278.6 KiB baseline); visual evidence at 390/768/1440 light+dark+offline in session scratchpad. Dev caveat recorded: Turbopack persistent `.next` cache served stale globals.css across restarts twice; fixed by setting the cache aside. No provider-backed checks run." }, { @@ -20721,7 +20763,7 @@ "ref": "cursor/hide-favourites-guest-mode-a26d (PR #934)", "head": "04192653", "scope": "Final Favourites total guest-blackout review + merge readiness", - "outcome": "No P0/P1. Fixed residual P2s: rankToolRecords now fails closed by default; mode/chip filters stop double-ORing demoMode; gated deep-link mode chrome falls back to Answer; MasterSearchHeader mode-menu DOM tests added. Guest discovery closed for mode menu, sidebar, cross-mode chips, Tools Saved, universal tools ranking, also-matches, prefetch. Intentional residual: direct /favourites signup gate; mockup routes. PR body appears overwritten by unrelated Sync PR policy content \u2014 agent posted corrective comment (403 on body edit).", + "outcome": "No P0/P1. Fixed residual P2s: rankToolRecords now fails closed by default; mode/chip filters stop double-ORing demoMode; gated deep-link mode chrome falls back to Answer; MasterSearchHeader mode-menu DOM tests added. Guest discovery closed for mode menu, sidebar, cross-mode chips, Tools Saved, universal tools ranking, also-matches, prefetch. Intentional residual: direct /favourites signup gate; mockup routes. PR body appears overwritten by unrelated Sync PR policy content — agent posted corrective comment (403 on body edit).", "checks": "Focused Vitest 37/37; verify:cheap green; verify:pr-local green (build + client-secret scan + RAG fixtures); browser guest Tools/sidebar/favourites proof earlier. No OpenAI/Supabase writes." }, { @@ -20782,18 +20824,18 @@ }, { "date": "2026-07-19", - "ref": "origin/main 24-hour merged window (d1937d78e..ef042cacd, ~30 PRs incl. #853/#859/#861/#865/#868/#871\u2013#874/#879/#885\u2013#888/#890\u2013#894/#896)", + "ref": "origin/main 24-hour merged window (d1937d78e..ef042cacd, ~30 PRs incl. #853/#859/#861/#865/#868/#871–#874/#879/#885–#888/#890–#894/#896)", "head": "ef042cacd", "scope": "integrated post-merge regression audit of the full 24h window (code review + design/performance/defect angles)", - "outcome": "No P0/P1 regression found at the merged tip. One confirmed P2: the new settings surface (`use-app-preferences.ts` + `settings-dialog.tsx`) presents jurisdiction, population, answer-style, landing, home-content, compact-citations, and all notification preferences as live controls, but no consumer reads them \u2014 only density/motion (html attributes + globals.css) and theme are functional; a clinician selecting \"Conservative\" answer style reasonably but wrongly believes generation changed. One plausible P2/P3: `AuthProvider.initializeSession` now requires a live `getUser()` round-trip, so a transient network failure on load resolves a valid stored session to signed_out (INITIAL_SESSION replay is also skipped); the deliberate stale/tampered-token defense does not distinguish retryable network errors. One P3: `/medications` legacy redirect drops the query string while `/applications` and `/differentials/presentations` preserve theirs. Cleared after inspection: worker image-placement dedupe (key symmetric on both sides), title-word purge/scope migration (matches its replayed review), RPC-layer-only cancellation consolidation (intentional per PR #861), services route-chunk fix intact with no other heavy client value-imports (type-only imports verified), forced-colors ButtonFace/ButtonText flip, codex-autofix/pr-policy workflow changes conform to AGENTS.md (pin retained, rename-aware routing, workflow_sha checkout), audit-metadata allowlist exhaustive over the closed AuditAction union, answer-stream merged abort signals. Environment note (not a repo defect): the session-start hook skips `npm install` when node_modules exists, so this window's dependency bumps left the container stale and `verify:cheap` failed at typecheck until `npm ci`; the hook should compare a lockfile hash.", - "checks": "`npm ci` then typecheck clean and full Vitest 2828 passed / 1 failed / 2 skipped \u2014 the sole failure is the long-baselined container-only `tests/pdf-extraction-budget.test.ts` artifact (hosted-CI-green through #826/#835/#872/#890). First `verify:cheap` run passed every static guard (runtime, actions-pin, ci-scope, ci-triage, pr-policy, sitemap, brand, type-scale, icon-scale, function-grants, owner-scope, lint) before the stale-deps typecheck stop. No OpenAI, Supabase, deployment, or provider-backed check ran." + "outcome": "No P0/P1 regression found at the merged tip. One confirmed P2: the new settings surface (`use-app-preferences.ts` + `settings-dialog.tsx`) presents jurisdiction, population, answer-style, landing, home-content, compact-citations, and all notification preferences as live controls, but no consumer reads them — only density/motion (html attributes + globals.css) and theme are functional; a clinician selecting \"Conservative\" answer style reasonably but wrongly believes generation changed. One plausible P2/P3: `AuthProvider.initializeSession` now requires a live `getUser()` round-trip, so a transient network failure on load resolves a valid stored session to signed_out (INITIAL_SESSION replay is also skipped); the deliberate stale/tampered-token defense does not distinguish retryable network errors. One P3: `/medications` legacy redirect drops the query string while `/applications` and `/differentials/presentations` preserve theirs. Cleared after inspection: worker image-placement dedupe (key symmetric on both sides), title-word purge/scope migration (matches its replayed review), RPC-layer-only cancellation consolidation (intentional per PR #861), services route-chunk fix intact with no other heavy client value-imports (type-only imports verified), forced-colors ButtonFace/ButtonText flip, codex-autofix/pr-policy workflow changes conform to AGENTS.md (pin retained, rename-aware routing, workflow_sha checkout), audit-metadata allowlist exhaustive over the closed AuditAction union, answer-stream merged abort signals. Environment note (not a repo defect): the session-start hook skips `npm install` when node_modules exists, so this window's dependency bumps left the container stale and `verify:cheap` failed at typecheck until `npm ci`; the hook should compare a lockfile hash.", + "checks": "`npm ci` then typecheck clean and full Vitest 2828 passed / 1 failed / 2 skipped — the sole failure is the long-baselined container-only `tests/pdf-extraction-budget.test.ts` artifact (hosted-CI-green through #826/#835/#872/#890). First `verify:cheap` run passed every static guard (runtime, actions-pin, ci-scope, ci-triage, pr-policy, sitemap, brand, type-scale, icon-scale, function-grants, owner-scope, lint) before the stale-deps typecheck stop. No OpenAI, Supabase, deployment, or provider-backed check ran." }, { "date": "2026-07-19", "ref": "origin/main foreign merges post-#896 landing (541da7b #871 remediation + f4557ca #892 policy parsing; explicit user review request)", "head": "ef042ca6a34d33862936e77e4b71068978382c1e", "scope": "Bug review of recent main changes (diff-review protocol)", - "outcome": "One P2 confirmed and fixed in PR #905: #892's widened heading matcher ended a required PR-body section at ANY next heading, so `###` sub-structure inside `## Verification` truncated the section and false-rejected valid bodies (fail-closed; repo template unaffected; repro via direct evaluatePullRequestPolicy probe old-vs-new). No P0/P1. Cleared after verification: `src/lib/client-env.ts` (no env leakage; production demote-to-demo removal deliberate and fail-safe \u2014 upload gating still locked via canUsePrivateApis), applications/medications redirect routes (fixed targets, 307+HEAD alias, no open-redirect/header-injection), test infra (no weakened assertions; route-coverage spec added to all projects), and the three biggest #871 UI diffs read inline (ClinicalDashboard upload tablist roving-tabindex + hydration-safe useSyncExternalStore role switch; visual-evidence unavailable-source rows became real non-interactive elements; favourites library demo-gates prototype items with sound menu keyboard nav). Residual (report-only): pr-policy `section()` remains fence-unaware (headings inside fenced code can satisfy required-section checks \u2014 pre-existing class, author-controlled attestation surface); dev-only Turbopack persistent-cache staleness served an old globals.css compile across restarts twice this session (fixed by setting `.next` aside).", + "outcome": "One P2 confirmed and fixed in PR #905: #892's widened heading matcher ended a required PR-body section at ANY next heading, so `###` sub-structure inside `## Verification` truncated the section and false-rejected valid bodies (fail-closed; repo template unaffected; repro via direct evaluatePullRequestPolicy probe old-vs-new). No P0/P1. Cleared after verification: `src/lib/client-env.ts` (no env leakage; production demote-to-demo removal deliberate and fail-safe — upload gating still locked via canUsePrivateApis), applications/medications redirect routes (fixed targets, 307+HEAD alias, no open-redirect/header-injection), test infra (no weakened assertions; route-coverage spec added to all projects), and the three biggest #871 UI diffs read inline (ClinicalDashboard upload tablist roving-tabindex + hydration-safe useSyncExternalStore role switch; visual-evidence unavailable-source rows became real non-interactive elements; favourites library demo-gates prototype items with sound menu keyboard nav). Residual (report-only): pr-policy `section()` remains fence-unaware (headings inside fenced code can satisfy required-section checks — pre-existing class, author-controlled attestation surface); dev-only Turbopack persistent-cache staleness served an old globals.css compile across restarts twice this session (fixed by setting `.next` aside).", "checks": "Reviewer fan-out: general lane completed with concrete probes (pr-policy self-test, node repro on old parser from f4557ca^, adversarial body probes); UI lane agent lost to session limit and re-done inline on the three biggest diffs, leaning on the merged tree's green gates (verify:ui 236-passed run in this session covers #871's own new specs). No provider-backed checks run." }, { @@ -20801,7 +20843,7 @@ "ref": "PR #935 / `cursor/mobile-mode-menu-sheet-efee`", "head": "87d4a479cd320220c91eba5c91e253e843dcc98f", "scope": "final Mode phone-sheet review + merge-readiness", - "outcome": "No remaining high-confidence P0/P1. Fixed residual P2 Sheet backdrop drag-dismiss (gesture must start on dimmed area). Phone \u2264639px Mode menu uses bottom Sheet; desktop absolute dropdown/keyboard/blur contracts preserved. Python PDF extractor resolves python/python3 and process-group kills reliably. Clinical governance: UI + fail-closed extractor binary resolution only; no answer/source/privacy surface change. Safe to merge after hosted required checks green on this HEAD.", + "outcome": "No remaining high-confidence P0/P1. Fixed residual P2 Sheet backdrop drag-dismiss (gesture must start on dimmed area). Phone ≤639px Mode menu uses bottom Sheet; desktop absolute dropdown/keyboard/blur contracts preserved. Python PDF extractor resolves python/python3 and process-group kills reliably. Clinical governance: UI + fail-closed extractor binary resolution only; no answer/source/privacy surface change. Safe to merge after hosted required checks green on this HEAD.", "checks": "`verify:cheap` 2954 passed; Mode Playwright 5/5 (phone sheet/backdrop/desktop/keyboard/a11y); `check:production-readiness:ci` READY; prettier format check fixed for CI Static; no OpenAI/live Supabase writes; full `verify:ui`/`verify:release` not required beyond Mode proofs." }, { @@ -20809,7 +20851,7 @@ "ref": "PR #938 / `cursor/fix-differentials-results-top-d760`", "head": "2df3181859345339d777ac814908b3095cea36fd", "scope": "ModeHomeMain contentAlign fix for differentials mobile clipping", - "outcome": "No high-confidence P0\u2013P2. Fix correctly introduces exclusive `contentAlign` (`center` | `start` | `startOnPhone`), migrates therapy/formulation/specifiers off broken className justify overrides, top-aligns differentials results via `autoRunSearch`, and guards with static + Playwright fold assertions. Residual: DSM/forms/services still default-center; justify-strip leaves variant prefixes; Playwright `0.55*vh` upper bound may flake if header band grows; Chip compact overrides still dual-utility via `cn()`.", + "outcome": "No high-confidence P0–P2. Fix correctly introduces exclusive `contentAlign` (`center` | `start` | `startOnPhone`), migrates therapy/formulation/specifiers off broken className justify overrides, top-aligns differentials results via `autoRunSearch`, and guards with static + Playwright fold assertions. Residual: DSM/forms/services still default-center; justify-strip leaves variant prefixes; Playwright `0.55*vh` upper bound may flake if header band grows; Chip compact overrides still dual-utility via `cn()`.", "checks": "Static diff vs `origin/main`; inventory of all `ModeHomeMain` call sites; justify-strip regex probe; `npx vitest run tests/mode-home-main-align.test.ts` 4/4. Not run: Playwright/`verify:ui` (browser), `verify:cheap`/`verify:pr-local`, provider-backed checks." }, { @@ -20817,7 +20859,7 @@ "ref": "PR #938 / `cursor/fix-differentials-results-top-d760`", "head": "3a775d4fd9a44e97388c0041cb421f06265a7721", "scope": "fresh final review (user-requested) + main sync (#937)", - "outcome": "No high-confidence P0\u2013P2. Product delta unchanged vs prior merge-ready head; #933 reserve + #938 contentAlign remain complementary. Merged `origin/main` (#937) cleanly. Follow-up: dropped `PR_POLICY_BODY.md` when syncing #942 so this PR does not reintroduce the stale template; live PR description already correct. Residual: required human approving review.", + "outcome": "No high-confidence P0–P2. Product delta unchanged vs prior merge-ready head; #933 reserve + #938 contentAlign remain complementary. Merged `origin/main` (#937) cleanly. Follow-up: dropped `PR_POLICY_BODY.md` when syncing #942 so this PR does not reintroduce the stale template; live PR description already correct. Residual: required human approving review.", "checks": "Local: align+composer-reserve Vitest 9/9; focused Chromium overlap+fold+compare 14/14. Hosted CI green on prior tip." }, { @@ -20825,7 +20867,7 @@ "ref": "PR #938 / `cursor/fix-differentials-results-top-d760`", "head": "74c370d81342dd729398dc2b40ba3158ea30f1db", "scope": "follow-up review + residual polish (policy body, align API, UI flake)", - "outcome": "Prior residuals closed: `PR_POLICY_BODY.md` rewritten for #938 (Sync PR policy body was overwriting with stale #932 text); `withoutJustifyUtilities` strips prefixed utilities; Chip uses exclusive `density` type scale; DSM/forms/services use `startOnPhone`; Best Answer fold bound uses header+240px; `ui-overlap` waits for a single `header#search`. No remaining high-confidence P0\u2013P2 in the ModeHomeMain/differentials mobile scope.", + "outcome": "Prior residuals closed: `PR_POLICY_BODY.md` rewritten for #938 (Sync PR policy body was overwriting with stale #932 text); `withoutJustifyUtilities` strips prefixed utilities; Chip uses exclusive `density` type scale; DSM/forms/services use `startOnPhone`; Best Answer fold bound uses header+240px; `ui-overlap` waits for a single `header#search`. No remaining high-confidence P0–P2 in the ModeHomeMain/differentials mobile scope.", "checks": "`npx vitest run tests/mode-home-main-align.test.ts` 5/5; Prettier on touched files. Playwright focused rerun and hosted Production UI expected after push." }, { @@ -20833,7 +20875,7 @@ "ref": "PR #938 / `cursor/fix-differentials-results-top-d760`", "head": "b62d414ca9001fbc1ac0d50b315450e107751d67", "scope": "merge-readiness after policy + hosted UI", - "outcome": "No remaining high-confidence P0\u2013P2. PR description sync + `verify:ui` evidence keep PR policy green; hosted Production UI / PR required green on exact head.", + "outcome": "No remaining high-confidence P0–P2. PR description sync + `verify:ui` evidence keep PR policy green; hosted Production UI / PR required green on exact head.", "checks": "Local: align Vitest 5/5; ui-overlap 12/12; differentials fold Playwright 1/1. Hosted: Production UI, Advisory UI, Static, Unit, Build, PR policy, PR required, Sync PR policy body all pass." }, { @@ -20841,7 +20883,7 @@ "ref": "PR #938 / `cursor/fix-differentials-results-top-d760`", "head": "e177b5e877aa2f834b3a601fa37679fa3e77b0e3", "scope": "merge main (#933) + post-merge revalidation", - "outcome": "Merged `origin/main` (Safari edge-to-edge #933) with ledger conflict resolved by keeping both review rows. No product conflicts; `contentAlign`, Chip density, and Best Answer fold asserts intact. No new P0\u2013P2. Still blocked only by required human approving review; squash auto-merge remains enabled.", + "outcome": "Merged `origin/main` (Safari edge-to-edge #933) with ledger conflict resolved by keeping both review rows. No product conflicts; `contentAlign`, Chip density, and Best Answer fold asserts intact. No new P0–P2. Still blocked only by required human approving review; squash auto-merge remains enabled.", "checks": "Local after merge: align+composer-reserve Vitest 9/9; focused Chromium dock-hide + fold + compare-dock 3/3. Hosted on merge head: Production UI, PR required, Unit, Static, Build, PR policy all SUCCESS." }, { @@ -20849,7 +20891,7 @@ "ref": "PR #938 / `cursor/fix-differentials-results-top-d760`", "head": "efe472fac3489473e2465da2d92980508c20fd81", "scope": "merge main (#934 favourites) + #941 sync", - "outcome": "Merged favourites guest-gate (#934) then Specifiers results UI (#941). Product conflicts none: kept `contentAlign=\"startOnPhone\"` on Specifiers home while taking #941 results chrome. `ui-overlap` gotoHome wait conflict resolved with settled single-header short-circuit. No new P0\u2013P2. Residual: human approving review required for squash auto-merge.", + "outcome": "Merged favourites guest-gate (#934) then Specifiers results UI (#941). Product conflicts none: kept `contentAlign=\"startOnPhone\"` on Specifiers home while taking #941 results chrome. `ui-overlap` gotoHome wait conflict resolved with settled single-header short-circuit. No new P0–P2. Residual: human approving review required for squash auto-merge.", "checks": "Local: align Vitest; favourites+app-modes+tools 42 tests; Chromium ui-overlap+ui-tools 95/95; verify:cheap unit stage green. Hosted CI green on pre-#941 tip; re-running after this merge." }, { @@ -20857,7 +20899,7 @@ "ref": "PR #938 / `cursor/fix-differentials-results-top-d760`", "head": "f6682cc08eb0fcc0b8dd170d5c9358b3fedc0c0d", "scope": "final meticulous review + safe-merge handoff", - "outcome": "No high-confidence P0\u2013P2. Forms/services now centre when unseeded/loading and use `startOnPhone` only when seeded (avoids sparse empty homes). CodeRabbit risk-line comment dispositioned as stale #932 body confusion. Residual: branch protection still requires a human approving review before squash auto-merge can land.", + "outcome": "No high-confidence P0–P2. Forms/services now centre when unseeded/loading and use `startOnPhone` only when seeded (avoids sparse empty homes). CodeRabbit risk-line comment dispositioned as stale #932 body confusion. Residual: branch protection still requires a human approving review before squash auto-merge can land.", "checks": "Local: align Vitest 5/5; focused Chromium overlap+fold 13/13; verify:cheap/pr-local unit stages 2953/2955 with only known container `pdf-extraction-budget` Python ENOENT failures; format/lint/typecheck/RAG fixtures pass; local `next build` blocked by running ensure server (hosted Build green). Hosted exact-head: Production UI, PR required, Unit, Static, Build, PR policy all SUCCESS. Enabled squash `--auto` merge." }, { @@ -20873,8 +20915,8 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (Phase 3, PR #872, final reviewed head ba46c1581a3c4e87d5d5989f3eb77483c9aa8aa5)", "head": "ba46c1581a3c4e87d5d5989f3eb77483c9aa8aa5", "scope": "PWA offline-page design upgrade (plan Phase 3)", - "outcome": "Rebuilt the `public/offline.html` visual shell on mirrored Clinical White / Aegean Graphite tokens (each value annotated with its source token): pure-white canvas, aligned text/border/hover values, system UI font stack, and the clinical-accent focus ring replacing the off-contract amber. Privacy copy, structure, forced-colors behavior, safe-area insets, and target sizes unchanged. `CACHE_VERSION` bumped to the new unique `2026-07-18-v1` with the offline.html sha256 pairing updated \u2014 the Phase 1 binding guard exercised for real and enforced the paired move. A transient typecheck failure from stale `.next/dev` route types (cross-branch dev-server state) self-resolved after server regeneration; nothing was deleted.", - "checks": "Focused Vitest 55/55 including the binding guard on the new pairing. `verify:cheap` 2778 passed/1 failed and `verify:pr-local` unit stage identical \u2014 the lone failure is the known container-only `pdf-extraction-budget` artifact (clean-main baselined; hosted CI green on #826/#835). `test:e2e:pwa`: the cold-offline journey rendered and asserted the redesigned page through the new-version worker; sole installability error remains the container `in-incognito` artifact. `verify:ui` 219 passed/2 failed \u2014 the same two clean-main-baselined container artifacts, no new failures. Build/bundle stages deferred to the blocking hosted CI Build job. No provider-backed checks run." + "outcome": "Rebuilt the `public/offline.html` visual shell on mirrored Clinical White / Aegean Graphite tokens (each value annotated with its source token): pure-white canvas, aligned text/border/hover values, system UI font stack, and the clinical-accent focus ring replacing the off-contract amber. Privacy copy, structure, forced-colors behavior, safe-area insets, and target sizes unchanged. `CACHE_VERSION` bumped to the new unique `2026-07-18-v1` with the offline.html sha256 pairing updated — the Phase 1 binding guard exercised for real and enforced the paired move. A transient typecheck failure from stale `.next/dev` route types (cross-branch dev-server state) self-resolved after server regeneration; nothing was deleted.", + "checks": "Focused Vitest 55/55 including the binding guard on the new pairing. `verify:cheap` 2778 passed/1 failed and `verify:pr-local` unit stage identical — the lone failure is the known container-only `pdf-extraction-budget` artifact (clean-main baselined; hosted CI green on #826/#835). `test:e2e:pwa`: the cold-offline journey rendered and asserted the redesigned page through the new-version worker; sole installability error remains the container `in-incognito` artifact. `verify:ui` 219 passed/2 failed — the same two clean-main-baselined container artifacts, no new failures. Build/bundle stages deferred to the blocking hosted CI Build job. No provider-backed checks run." }, { "date": "2026-07-18", @@ -20890,14 +20932,14 @@ "head": "d46f381ac27b53b1bd5ac0ef77962fbd48cf3aa7", "scope": "PWA manifest and install-UX polish (plan Phase 2)", "outcome": "Implemented Phase 2 of the PWA plan with cache semantics untouched: `launch_handler` navigate-existing/auto and `display_override` standalone/minimal-ui in `manifest.ts`; `monochrome-192/512` icon variants rendered as a white alpha-only silhouette from the shared brand mark via `BRAND_MONOCHROME`; a one-time iOS/iPadOS Add to Home Screen hint in `pwa-lifecycle.tsx` (30-day dismissal key, never in standalone, timer-deferred eligibility for the set-state-in-effect lint rule). Docs Installability section updated; manifest screenshots remain deferred per the production-capture precondition. Phase 2 re-scout confirmed zero upstream drift before implementation.", - "checks": "Focused Vitest 55/55. `verify:cheap` 2773 passed/1 failed and `verify:pr-local` unit stage identical \u2014 the lone failure is the known container-only `pdf-extraction-budget` artifact (clean-main baselined; hosted CI green on #826). `test:e2e:pwa`: privacy journey passed; icon probes validated both new monochrome PNGs; sole installability error remains the container `in-incognito` artifact. `verify:ui` 219 passed/2 failed \u2014 exactly the two clean-main-baselined container artifacts, no new failures. `format:check` clean. Build/bundle stages deferred to the blocking hosted CI Build job on PR #835. No provider-backed checks run." + "checks": "Focused Vitest 55/55. `verify:cheap` 2773 passed/1 failed and `verify:pr-local` unit stage identical — the lone failure is the known container-only `pdf-extraction-budget` artifact (clean-main baselined; hosted CI green on #826). `test:e2e:pwa`: privacy journey passed; icon probes validated both new monochrome PNGs; sole installability error remains the container `in-incognito` artifact. `verify:ui` 219 passed/2 failed — exactly the two clean-main-baselined container artifacts, no new failures. `format:check` clean. Build/bundle stages deferred to the blocking hosted CI Build job on PR #835. No provider-backed checks run." }, { "date": "2026-07-18", - "ref": "claude/clinical-kb-pwa-review-asi3wb (PR #890, plan Phase 4; single-batch implementation+ledger commit \u2014 Phase 3 landed as squash 44a4c511bc1381168474794d6f89273564659ead)", + "ref": "claude/clinical-kb-pwa-review-asi3wb (PR #890, plan Phase 4; single-batch implementation+ledger commit — Phase 3 landed as squash 44a4c511bc1381168474794d6f89273564659ead)", "head": "ceabc04d75fd0cea2a120d504418d44edd704bfb", "scope": "App-wide performance pass: audit-then-fix + budget ratchet (plan Phase 4)", - "outcome": "Audit on post-#872 main: enforced gzip budget +3.13% over the 1,363,382-byte baseline; analyzer treemap showed pdfjs-dist (123 KB) and cross-mode-differentials data (121 KB) already correctly lazy, and disproved the suspected forms-catalog dashboard leak (type-only import). Confirmed one real defect: the 143-line `/services` client home page value-imported `defaultServiceSlug` from `@/lib/services`, compiling the ~915 KB services snapshot (~100 KB gzip) into its route chunk. Fixed by computing the slug in the server page (`src/app/services/page.tsx`) and passing it as a prop; the client component builds its task cards from the prop. Measured result: budget swung from +3.13% to \u22123.97%; baseline ratcheted down 1,363,382 \u2192 1,309,286 bytes gzip so CI locks the win. pdfjs/differentials/#718 paths deliberately untouched per audit rules. Two transient `.next/dev` generated-type corruptions from the long-lived dev server were resolved by stopping the server and setting the generated dir aside (reversible); nothing hand-deleted.", + "outcome": "Audit on post-#872 main: enforced gzip budget +3.13% over the 1,363,382-byte baseline; analyzer treemap showed pdfjs-dist (123 KB) and cross-mode-differentials data (121 KB) already correctly lazy, and disproved the suspected forms-catalog dashboard leak (type-only import). Confirmed one real defect: the 143-line `/services` client home page value-imported `defaultServiceSlug` from `@/lib/services`, compiling the ~915 KB services snapshot (~100 KB gzip) into its route chunk. Fixed by computing the slug in the server page (`src/app/services/page.tsx`) and passing it as a prop; the client component builds its task cards from the prop. Measured result: budget swung from +3.13% to −3.97%; baseline ratcheted down 1,363,382 → 1,309,286 bytes gzip so CI locks the win. pdfjs/differentials/#718 paths deliberately untouched per audit rules. Two transient `.next/dev` generated-type corruptions from the long-lived dev server were resolved by stopping the server and setting the generated dir aside (reversible); nothing hand-deleted.", "checks": "Build + `check:bundle-budget --json` before/after (artifacts in session scratchpad); `check:bundle-budget -- --update` for the ratchet; `npm run test` 2789 passed/1 failed (known container-only `pdf-extraction-budget` artifact, hosted-CI-green through #826/#835/#872); `verify:cheap` green to the same artifact; `verify:ui` 219 passed/2 failed (the two long-established container artifacts; ui-tools spec covering the services surface passed); `verify:pr-local` unit stage identical; typecheck/lint/format clean. Lighthouse not run (dev-server churn; bundle evidence sufficed for this fix set). No provider-backed checks run." }, { @@ -20905,7 +20947,7 @@ "ref": "claude/clinical-kb-pwa-review-asi3wb (PR #896, plan Phase 5; content commit + this ledger follow-up)", "head": "a6c2b4e92374e9002fb00c547eb5677d01ce538c", "scope": "Design-polish sweep: audit-then-fix (plan Phase 5, final phase)", - "outcome": "Audit on post-#890 main: three strict design guards clean; full re-run of the 07-token-adoption-audit grep method shows all July 3 debt resolved (M1\u2013M3 done, L4 reduced to the deliberate theme-aware `ring-white/N dark:ring-white/10` glass idiom, L5/L7 gone; production hex all legitimate print/brand/console/comment classes); 43-capture live sweep across 15 routes \u00d7 desktop/phone + 320px spots + dark/reduced-motion/forced-colors spots found 0 overflow and 0 console errors. Three defects found and fixed: (1) forced-colors solid-button labels rendered as blank Canvas-on-Canvas backplate boxes (axe-invisible) \u2014 command controls flattened to the native HCM ButtonFace/ButtonText pairing and accent glyph tokens flipped to ButtonText inside the existing forced-colors block, regression-locked by a new ui-accessibility test; (2) tools desktop 6-up quick-action rail truncated card titles at 1440\u00d71000 \u2014 card metrics tightened, all six titles verified unclipped; (3) privacy page rendered \"systemand\" from a JSX newline-adjacent-to-tag drop \u2014 explicit space, locked by a privacy-ui assertion. Dated July 18 run appended to docs/redesign/07-token-adoption-audit.md (archived design-qa.md not resurrected).", + "outcome": "Audit on post-#890 main: three strict design guards clean; full re-run of the 07-token-adoption-audit grep method shows all July 3 debt resolved (M1–M3 done, L4 reduced to the deliberate theme-aware `ring-white/N dark:ring-white/10` glass idiom, L5/L7 gone; production hex all legitimate print/brand/console/comment classes); 43-capture live sweep across 15 routes × desktop/phone + 320px spots + dark/reduced-motion/forced-colors spots found 0 overflow and 0 console errors. Three defects found and fixed: (1) forced-colors solid-button labels rendered as blank Canvas-on-Canvas backplate boxes (axe-invisible) — command controls flattened to the native HCM ButtonFace/ButtonText pairing and accent glyph tokens flipped to ButtonText inside the existing forced-colors block, regression-locked by a new ui-accessibility test; (2) tools desktop 6-up quick-action rail truncated card titles at 1440×1000 — card metrics tightened, all six titles verified unclipped; (3) privacy page rendered \"systemand\" from a JSX newline-adjacent-to-tag drop — explicit space, locked by a privacy-ui assertion. Dated July 18 run appended to docs/redesign/07-token-adoption-audit.md (archived design-qa.md not resurrected).", "checks": "Guards + focused vitest 14/14; `verify:cheap` chain green to the known container-only pdf-extraction-budget artifact (2806/2809); `verify:ui` 220 passed/2 failed (the two long-baselined container artifacts, hosted-CI-green through #826/#835/#872/#890); `test:e2e:accessibility` 8/8 incl. the new forced-colors token test; production build + client-bundle secret scan passed; `check:bundle-budget` within tolerance vs the Phase 4 ratchet (1290.6 vs 1278.6 KiB baseline); `verify:pr-local` runtime/format/lint/typecheck/build/rag-fixtures green with the same sole unit-suite artifact. `verify:release` not run (provider-backed; awaits explicit confirmation). No provider-backed checks run." }, { @@ -20953,7 +20995,7 @@ "ref": "PR #861 / codex/design-audit-main-safe-20260720-final", "head": "d8c1916ac (functional head 593d5aa00 + current-main merge)", "scope": "design-audit/search cancellation merge review", - "outcome": "Fixed unsupported Forms pathway claims, propagated cancellation through every retrieval RPC, removed duplicate favourites \u201cAlso matches\u201d results, and resolved all four review threads. Merged as `3b2dd9ef76ff1c8c099fc1972065628d23b853b1`; exact `origin/main` commit and tree content were verified after merge.", + "outcome": "Fixed unsupported Forms pathway claims, propagated cancellation through every retrieval RPC, removed duplicate favourites “Also matches” results, and resolved all four review threads. Merged as `3b2dd9ef76ff1c8c099fc1972065628d23b853b1`; exact `origin/main` commit and tree content were verified after merge.", "checks": "Exact-head hosted Static PR checks, Unit coverage, Build, Safety and config checks, Production UI, Advisory UI, Migration replay, PR required, PR policy, Semgrep, Gitleaks, and GitGuardian checks passed. No Supabase, OpenAI, or other product-provider call ran." }, { @@ -20982,7 +21024,7 @@ }, { "date": "2026-07-18", - "ref": "PR batch screenshot queue \u2192 #808 / cursor/pr-queue-land-bfe7", + "ref": "PR batch screenshot queue → #808 / cursor/pr-queue-land-bfe7", "head": "3b54a785c7c6073024b6bae0182b6a9321154595", "scope": "open-PR review + merge babysit", "outcome": "Consolidated unique remaining work from screenshot PRs onto current main via #808 (Also matches placement, factsheets, audit metadata minimize with numeric storageRemoved, answer-progress UI gate, global-error role=alert). Superseded already-landed #800/#799/#801/#802 (via #798/#804). Closed conflicted/failing design-audit duplicates #789/#790/#803/#806/#807/#788 and older duplicates #748/#749/#751 without replaying Production UI regressions.", @@ -20990,23 +21032,23 @@ }, { "date": "2026-07-18", - "ref": "PR batch screenshot queue \u2192 #808/#812/#814", + "ref": "PR batch screenshot queue → #808/#812/#814", "head": "44555ab9e414f615981eb444f46a62333c28ec18", "scope": "open-PR review + merge babysit", - "outcome": "Screenshot PRs #784\u2013#789 closed as superseded. Unique residual work landed via #808 and #812. Design-audit/Playwright stack landed via #814 after Production UI fixes (Clinical Guide H1, service mocks, reduced-motion dock asserts), presentations empty-query fallback, and CodeRabbit thread resolution (RightRail remount, IS DISTINCT FROM, no-op dropped trigram migration). #783 already merged. Communication #17 inaccessible from this token.", + "outcome": "Screenshot PRs #784–#789 closed as superseded. Unique residual work landed via #808 and #812. Design-audit/Playwright stack landed via #814 after Production UI fixes (Clinical Guide H1, service mocks, reduced-motion dock asserts), presentations empty-query fallback, and CodeRabbit thread resolution (RightRail remount, IS DISTINCT FROM, no-op dropped trigram migration). #783 already merged. Communication #17 inaccessible from this token.", "checks": "Hosted #808/#812/#814 required checks green including Production UI; migration replay green on #814. No OpenAI/live Supabase writes." }, { "date": "2026-07-18", - "ref": "PR batch screenshot queue \u2192 #853 / cursor/pr-queue-land-3084", + "ref": "PR batch screenshot queue → #853 / cursor/pr-queue-land-3084", "head": "11ec0122f (tip of cursor/pr-queue-land-3084)", "scope": "open-PR review + merge babysit", - "outcome": "Reviewed screenshot PRs #833/#837/#845\u2013#852 + Communication #19. #852/#848 already merged. Closed superseded/unsafe: #833/#837 (empty vs main), #845 (clinical-search over-expand; fixed in #853), #846/#847/#849 (Production UI red design-audit dupes), #850 (CONFLICTING), #851 (schema-test regressions), #726 (CONFLICTING CodeRabbit UTG). Unique safe fix landed in #853: agitation chart expansion without bare table/management over-trigger. Communication #19 inaccessible (repo not resolvable).", + "outcome": "Reviewed screenshot PRs #833/#837/#845–#852 + Communication #19. #852/#848 already merged. Closed superseded/unsafe: #833/#837 (empty vs main), #845 (clinical-search over-expand; fixed in #853), #846/#847/#849 (Production UI red design-audit dupes), #850 (CONFLICTING), #851 (schema-test regressions), #726 (CONFLICTING CodeRabbit UTG). Unique safe fix landed in #853: agitation chart expansion without bare table/management over-trigger. Communication #19 inaccessible (repo not resolvable).", "checks": "Focused Vitest clinical-search 42/42. Local verify:cheap unit suite hit pre-existing pdf-extraction-budget failures also on main (2 tests). Hosted #853 required checks green (Static/Unit/Build/PR required/policy/Semgrep/Gitleaks/GitGuardian). Squash-merged to main. Also closed follow-on dupes #854 (same failing tip as #851) and #855 (Clinical KB H1 reverts #814 Clinical Guide contract; Static/PR policy red). Communication #19 inaccessible. No OpenAI/live Supabase writes." }, { "date": "2026-07-18", - "ref": "PR batch screenshot queue \u2192 #883\u2013#888 / #891", + "ref": "PR batch screenshot queue → #883–#888 / #891", "head": "8b0a600209 (main tip after #887)", "scope": "open-PR review + merge babysit", "outcome": "Reviewed and land-safe-merged screenshot PRs. Merged #888 (worker placement dedupe), #891 (PR policy `github.workflow_sha` checkout superseding incorrect #884 `base.sha`), #886 (mobile differentials FAB), #885 (Compare selected href; closed duplicate #883/#882), #887 (Therapy mode-home align + nested-main landmark fix). Closed superseded #884/#883/#882/#881/#877/#875. Fixed PR-policy bodies (Clinical KB governance checkbox), resolved Codex/CodeRabbit threads, Prettier on therapy landmark files, and re-synced branches through main between merges. No high-confidence residual P0-P1 on landed heads.", @@ -21297,8 +21339,8 @@ "ref": "HEAD detached 570e6ba56 + WIP tree", "head": "570e6ba56ae60bea56a32801b9cc96c5a8dfde4f", "scope": "thorough multi-lens review: WIP RAG/schema + clinical design/UI + architecture/bug-hunt", - "outcome": "Changes requested: no P0. Confirmed P1s in WIP \u2014 registryCorpusDetailHref typecheck break; ChunkLoadCache error/null poisoning across parallel hydrations; registry cleanup `::uuid` cast abort; corrector GIN unused by query path; new table-facts trgm index expression mismatch vs trgm_matches. Design: production clinical shell stays token/a11y-aligned; favourites nav multi-gradient bars and mockup hex drift fight clinical density. Residual: concurrent cache race, SECURITY DEFINER revoke gaps, schema/migration lifecycle drift, accidental pnpm-lock.yaml.", - "checks": "`npm run typecheck` (red: registry link callers + stale .next apps types); static SQL/expr/diff review; architecture + bug-hunt agents; design-system grep (tokens, reduced-motion, forced-colors). Not run: vitest, verify:*, ensure/browser screenshots, live Supabase/OpenAI. frontend-ui-reviewer subagent blocked by usage limit \u2014 design pass done inline." + "outcome": "Changes requested: no P0. Confirmed P1s in WIP — registryCorpusDetailHref typecheck break; ChunkLoadCache error/null poisoning across parallel hydrations; registry cleanup `::uuid` cast abort; corrector GIN unused by query path; new table-facts trgm index expression mismatch vs trgm_matches. Design: production clinical shell stays token/a11y-aligned; favourites nav multi-gradient bars and mockup hex drift fight clinical density. Residual: concurrent cache race, SECURITY DEFINER revoke gaps, schema/migration lifecycle drift, accidental pnpm-lock.yaml.", + "checks": "`npm run typecheck` (red: registry link callers + stale .next apps types); static SQL/expr/diff review; architecture + bug-hunt agents; design-system grep (tokens, reduced-motion, forced-colors). Not run: vitest, verify:*, ensure/browser screenshots, live Supabase/OpenAI. frontend-ui-reviewer subagent blocked by usage limit — design pass done inline." }, { "date": "2026-07-15", @@ -21401,7 +21443,7 @@ "ref": "claude/codebase-review-ade6ed", "head": "a96b8ffafb88da22f667b41edf01b215866dde32", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21441,7 +21483,7 @@ "ref": "claude/document-page-redesign-7dd487", "head": "c2cfd57b4e7ec602d96e7f042eb60ff0b10a9e8e", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21449,7 +21491,7 @@ "ref": "claude/document-viewer-redesign-55b68b", "head": "0dbd83c73d2783cbe8e8d00bf04c9947a33518fc", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21481,7 +21523,7 @@ "ref": "claude/medication-alerts-database-cb8o83", "head": "a0ca895015df8ebe6ae57fa8a811a1fbb240e623", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21505,7 +21547,7 @@ "ref": "claude/perf-r2-bundle-hygiene", "head": "95ce39f7715caeadc8197c35c2c41500183a715e", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion (user decision): redundant perf-r2 duplicate; unmerged batch-endpoint work preserved in retained claude/perf-r2-plan-cache-migration. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion (user decision): redundant perf-r2 duplicate; unmerged batch-endpoint work preserved in retained claude/perf-r2-plan-cache-migration. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21513,7 +21555,7 @@ "ref": "claude/perf-r2-hot-path", "head": "843dcf8d287950b2ddf86a121701dfbb95ac86c0", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion (user decision): redundant perf-r2 duplicate; unmerged batch-endpoint work preserved in retained claude/perf-r2-plan-cache-migration. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion (user decision): redundant perf-r2 duplicate; unmerged batch-endpoint work preserved in retained claude/perf-r2-plan-cache-migration. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21521,7 +21563,7 @@ "ref": "claude/perf-r2-network-caching", "head": "424ae6b045d9ec38443292a1569de4b04d6a295d", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion (user decision): redundant perf-r2 duplicate; unmerged batch-endpoint work preserved in retained claude/perf-r2-plan-cache-migration. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion (user decision): redundant perf-r2 duplicate; unmerged batch-endpoint work preserved in retained claude/perf-r2-plan-cache-migration. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21529,7 +21571,7 @@ "ref": "claude/perf-r2-payload-trim", "head": "5a6ce71153198c746fab96859d5895374ac05bb9", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion (user decision): redundant perf-r2 duplicate; unmerged batch-endpoint work preserved in retained claude/perf-r2-plan-cache-migration. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion (user decision): redundant perf-r2 duplicate; unmerged batch-endpoint work preserved in retained claude/perf-r2-plan-cache-migration. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21545,7 +21587,7 @@ "ref": "claude/pr-672-specifiers-formulation-3n123f", "head": "059398c962711f57e5f9ee7c6b4783066cd6718f", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21641,7 +21683,7 @@ "ref": "claude/site-performance-speed-61d154", "head": "cb0bcf35498385bca1180462c8ab79b6f8293708", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion (user decision): redundant perf-r2 duplicate; unmerged batch-endpoint work preserved in retained claude/perf-r2-plan-cache-migration. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion (user decision): redundant perf-r2 duplicate; unmerged batch-endpoint work preserved in retained claude/perf-r2-plan-cache-migration. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21657,7 +21699,7 @@ "ref": "claude/therapy-compass-pages-rz0m5l", "head": "5a89a521add5a02dc4f6dd640b393c5bdd690183", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21689,7 +21731,7 @@ "ref": "codex/dsm-diagnosis-mode", "head": "f6cda83ca6aed3a24d999ef4ccd38bff167d4788", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21705,7 +21747,7 @@ "ref": "codex/dsm-main-integration-20260714", "head": "9e013894b2e45d6be39af1ef4593a14604886476", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21753,7 +21795,7 @@ "ref": "codex/formulation-workspace", "head": "ce6baa31ffe9647d736a18e95f9d95a95bda313c", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21785,7 +21827,7 @@ "ref": "codex/live-migration-history-alignment", "head": "c9853c7acdc80e3c33354c3b1a32e5df2682f521", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21793,7 +21835,7 @@ "ref": "codex/offline-retrieval-signal-followup", "head": "ef448e212d12c1cadbeb3ea053ca6639e6f0ada4", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21825,7 +21867,7 @@ "ref": "codex/please-thoroughly-review-this-repo", "head": "47e850ee93dd5281c792eb60618f98ba2e972b8e", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21841,7 +21883,7 @@ "ref": "codex/rag-canary-recovery", "head": "d6bd7fa7c0b9b29e9b7eddfd28e0478e042a0455", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21897,7 +21939,7 @@ "ref": "codex/release-blocker-remediation", "head": "8a7ec72b22bff98b8d4b31d533ae9a0738dee071", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21913,7 +21955,7 @@ "ref": "codex/repository-review-remediation", "head": "29c598cd2db4fc9c00ed56f60e8ef2adb969cccf", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21937,7 +21979,7 @@ "ref": "codex/universal-search-domain-exclusions", "head": "6b2c4ffbc81b9a35746ee2fa8795c73a2f65d4fc", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21953,7 +21995,7 @@ "ref": "codex/universal-search-mode-ranking", "head": "6a0c37f8e3b4b23fa52c49fec28dcbc8d635b80f", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21961,7 +22003,7 @@ "ref": "copilot/29199485110", "head": "4e09b838bda6a774f067b8e13717af2103502857", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21969,7 +22011,7 @@ "ref": "copilot/29202241308-fix-database-issue", "head": "29db1aa1b29a812bf4c7eb7af5ea33371f086157", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21977,7 +22019,7 @@ "ref": "copilot/database-ci-setup", "head": "45fa392a24987e4b596d80fc81528912e62d95c9", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21985,7 +22027,7 @@ "ref": "copilot/fix", "head": "060b2cd9c0cb38fa0cb0521ce3f67ead13a9ab87", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -21993,7 +22035,7 @@ "ref": "copilot/fix-961c247e-5acb-45db-b4ed-62fcf97681cd", "head": "b6097f0fbf19f82527ea95a385efb2ca7b8ec794", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22001,7 +22043,7 @@ "ref": "copilot/fix-accessibility-test-timeouts", "head": "17e11e45835510d2a43b8ea6fdfeed10df11e0d7", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22009,7 +22051,7 @@ "ref": "copilot/fix-again", "head": "0b2d29a143926279b327ff302c2de3d5fe0edbc5", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22017,7 +22059,7 @@ "ref": "copilot/fix-another-one", "head": "f1864308e0b287bb83b2a13daca4c3aa2ab95a3e", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22025,7 +22067,7 @@ "ref": "copilot/fix-barriers", "head": "8711ee2b15c3b9a1a0e8444ba2ee799d6c5e6ab7", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22033,7 +22075,7 @@ "ref": "copilot/fix-ci-error", "head": "e6e735d2668f7383acc45bdb7cc7dc183e7a73a8", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22041,7 +22083,7 @@ "ref": "copilot/fix-ci-issue", "head": "a95b282433e6b01bdd6444eb9b2de9148daf2363", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22049,7 +22091,7 @@ "ref": "copilot/fix-ci-issues", "head": "5f1c6f64a544705df9df970e09da3b85f0d90efa", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22057,7 +22099,7 @@ "ref": "copilot/fix-ci-test-to-pass", "head": "660e5789f56a0a54f68616392fb456e1ad10e48c", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22065,7 +22107,7 @@ "ref": "copilot/fix-database-action-error", "head": "7ff6c547e55100d7dfff912530e006f0a5ee70a2", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22073,7 +22115,7 @@ "ref": "copilot/fix-database-action-issue", "head": "b367aeb084a60fc46d3e4e8d3b318491a1530ac6", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22081,7 +22123,7 @@ "ref": "copilot/fix-database-action-run-issues", "head": "de36fd3ef8aa101e75a22fab8ff15940bb241e00", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22089,7 +22131,7 @@ "ref": "copilot/fix-database-actions", "head": "50cf0744df83708405d0bd215e22f19dc1f27815", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22097,7 +22139,7 @@ "ref": "copilot/fix-failing-ci", "head": "d248707d09f62bb153d0eece69b4f7f4e8aeb7dc", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22105,7 +22147,7 @@ "ref": "copilot/fix-failing-ci-again", "head": "28dacd7f19320bcbf2b03e5e40c7e97fc46a80cd", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22113,7 +22155,7 @@ "ref": "copilot/fix-failing-ci-another-one", "head": "59207b23fe88a23b0e2f3a6d7f1a288e0cca5132", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22121,7 +22163,7 @@ "ref": "copilot/fix-failing-ci-one-more-time", "head": "00b61456b3f4fd528b24476865fde3b046b105ea", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22129,7 +22171,7 @@ "ref": "copilot/fix-failing-ci-test", "head": "1de23d35e534c33cf444bc5e81e60c7384e8d072", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22137,7 +22179,7 @@ "ref": "copilot/fix-failing-ci-yet-again", "head": "8f2928b9dc925ac9ccc31e413ab422d2ffa77118", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22145,7 +22187,7 @@ "ref": "copilot/fix-issue-in-database-action", "head": "82c0e87224880ccbeee39f4101e98cf29683f74f", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22153,7 +22195,7 @@ "ref": "copilot/fix-issue-with-database-connection", "head": "67f5bb2744939922ceb280fab8785ee0259b26f2", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22161,7 +22203,7 @@ "ref": "copilot/fix-one-more-time", "head": "2682cbade791fc07f09d23fa11908eead223d3c7", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22169,7 +22211,7 @@ "ref": "copilot/fix-please-work", "head": "2f55346e72555500d17a08be02e6b649daa1a7cc", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22177,7 +22219,7 @@ "ref": "copilot/fix-yet-again", "head": "c57bc8af5570a5fc69fa0f804f67cfa98df76b89", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22185,7 +22227,7 @@ "ref": "copilot/rerun-all-ci-again", "head": "4615e39557112515cc9e4938fb5dd397f19ff70d", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22201,7 +22243,7 @@ "ref": "cursor/fix-pr654-ci-53b4", "head": "9f880853ea7d268186d982f4623b71f46e77d3dc", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22217,7 +22259,7 @@ "ref": "fix/accessibility-remaining-findings", "head": "9f880853ea7d268186d982f4623b71f46e77d3dc", "scope": "branch-cleanup-deletion-pending", - "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD \u2014 operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", + "outcome": "Pending deletion: content already on origin/main or superseded old-lineage snapshot / throwaway CI-retry branch; branch-only-file sweep found no novel work. Remote deletion DENIED (HTTP 403, session lacks ref-delete permission); branch still exists at this HEAD — operator must complete deletion. Scope is deletion-pending so future cleanup passes re-evaluate rather than skip.", "checks": "Provider-backed GitHub PR inventory via MCP (400 PRs #264-#674, all merged=false); local read-only git: rewritten-main-aware cherry-pick + two-dot tree + branch-only-file novelty sweep vs origin/main e75fad90; adversarial re-check. Remote `git push --delete` attempted (provider-backed write) and DENIED with HTTP 403. No OpenAI/Supabase/live-eval checks." }, { @@ -22233,15 +22275,15 @@ "ref": "HEAD (detached) 570e6ba56ae60bea56a32801b9cc96c5a8dfde4f", "head": "570e6ba56ae60bea56a32801b9cc96c5a8dfde4f", "scope": "clinical governance + RAG full-repo audit (source governance/citations, answer verification/clinical safety, privacy/query-privacy/private-search-scope, generation failure modes/degradation, retrieval/ranking/selection, ingestion/OCR index quality)", - "outcome": "No high-confidence P0/P1. Fail-closed governance chokepoint (`buildGovernedAnswerClientResponse`) applies to both `/api/answer` and `/api/answer/stream`; numeric/quote/citation verification, prompt-injection neutralization, owner-scope tenancy, and query/answer redaction all conservative. Two P3 observations: (1) `secondStageScore` demotion penalties can be floored away by `Math.max(hybrid_score, boosted)` at the tail of the list (rag.ts:663); (2) `outdatedPenalty` default-ON uses governance metadata to weight ranking (eval-gated, demotion-only) \u2014 in tension with the \"no governance weighting\" principle but conservative. D4/D5 (#649) levers verified default-OFF with tests.", + "outcome": "No high-confidence P0/P1. Fail-closed governance chokepoint (`buildGovernedAnswerClientResponse`) applies to both `/api/answer` and `/api/answer/stream`; numeric/quote/citation verification, prompt-injection neutralization, owner-scope tenancy, and query/answer redaction all conservative. Two P3 observations: (1) `secondStageScore` demotion penalties can be floored away by `Math.max(hybrid_score, boosted)` at the tail of the list (rag.ts:663); (2) `outdatedPenalty` default-ON uses governance metadata to weight ranking (eval-gated, demotion-only) — in tension with the \"no governance weighting\" principle but conservative. D4/D5 (#649) levers verified default-OFF with tests.", "checks": "Pure review, no mutations except this ledger append. Offline: focused Vitest governance/verification/privacy/scope suites 79/79 + 98/98 passed. Provider-backed (Supabase/OpenAI), browser, release, and live retrieval-quality checks not run (confirmation boundary)." }, { "date": "2026-07-14", "ref": "HEAD (detached) 570e6ba56ae60bea56a32801b9cc96c5a8dfde4f", "head": "570e6ba56ae60bea56a32801b9cc96c5a8dfde4f", - "scope": "frontend/UI/accessibility audit \u2014 global-search-shell, master-search-header, composer, answer surfaces, document viewer, clinical dashboard modules; design-token usage, reduced-motion/forced-colors, icon aria, focus traps, composer/header placement", - "outcome": "No P0. P2: (1) `aria-describedby`+`aria-hidden=\"true\"` conflict in `mode-action-popup.tsx:622,651` makes menu descriptions invisible to AT; (2) ~25 dynamic `` render sites missing `aria-hidden` across dashboard modules \u2014 ESLint `require-lucide-icon-aria` rule gap for LucideIcon-typed variables; (3) Mode menu (`role=\"menu\"` in header) does not close on Tab \u2014 keyboard users can Tab away from an open menu without dismissing it; (4) No live region on streaming `NaturalLanguageAnswer` \u2014 screen reader users not notified of incremental answer content. P3: (5) `--surface-glass`/`--panel-gloss` not remapped in `@media (forced-colors: active)` block \u2014 image-lightbox and PDF toolbar control bars could become invisible in high-contrast; (6) `bg-black/45` on Sheet backdrop instead of `var(--overlay-backdrop)` token; (7) `active:scale-[0.99]` on action-popup buttons without `motion-safe:` \u2014 still fires as a visual jump under reduced-motion; (8) Microsoft/Google brand hex squares not `forced-color-adjust:none` \u2014 lose brand identity in high-contrast mode.", + "scope": "frontend/UI/accessibility audit — global-search-shell, master-search-header, composer, answer surfaces, document viewer, clinical dashboard modules; design-token usage, reduced-motion/forced-colors, icon aria, focus traps, composer/header placement", + "outcome": "No P0. P2: (1) `aria-describedby`+`aria-hidden=\"true\"` conflict in `mode-action-popup.tsx:622,651` makes menu descriptions invisible to AT; (2) ~25 dynamic `` render sites missing `aria-hidden` across dashboard modules — ESLint `require-lucide-icon-aria` rule gap for LucideIcon-typed variables; (3) Mode menu (`role=\"menu\"` in header) does not close on Tab — keyboard users can Tab away from an open menu without dismissing it; (4) No live region on streaming `NaturalLanguageAnswer` — screen reader users not notified of incremental answer content. P3: (5) `--surface-glass`/`--panel-gloss` not remapped in `@media (forced-colors: active)` block — image-lightbox and PDF toolbar control bars could become invisible in high-contrast; (6) `bg-black/45` on Sheet backdrop instead of `var(--overlay-backdrop)` token; (7) `active:scale-[0.99]` on action-popup buttons without `motion-safe:` — still fires as a visual jump under reduced-motion; (8) Microsoft/Google brand hex squares not `forced-color-adjust:none` — lose brand identity in high-contrast mode.", "checks": "Pure static review, no mutations. Files read: `master-search-header.tsx`, `global-search-shell.tsx`, `globals.css`, `sheet.tsx`, `mode-action-popup.tsx`, `image-lightbox.tsx`, `answer-content.tsx`, `ClinicalDashboard.tsx` (partial), `use-dismissable-layer.ts`, `layout.tsx`, `eslint-rules/require-lucide-icon-aria.mjs`, `ui-accessibility.spec.ts`, `process-hardening.md`. Browser/live checks not run (confirmation boundary)." }, { @@ -22249,7 +22291,7 @@ "ref": "HEAD (detached) 570e6ba56ae60bea56a32801b9cc96c5a8dfde4f", "head": "570e6ba56ae60bea56a32801b9cc96c5a8dfde4f", "scope": "full repo-structure audit (broken imports, dead files, redundant config, module dependency, structural debt)", - "outcome": "No P0/P1. P2: `RAG_TEXT_WEAK_OR_RELAXATION=true` in `.env.example` contradicts `default(\"false\")` in `env.ts` (process-hardening hardened this to off); `reindex-eval-gate.ts` (488 lines) has no production importer \u2014 test-only orphan; `bundle-budget.json` still has `enforce: false` + `totalGzipBytes: null` after first production build window passed. P3: `client-env.ts` duplicates `isLocalNoAuthMode`/`publicUploadsEnabled` from `env.ts` using raw `process.env` (intentional server-only split, but divergent implementations); `OPENAI_PRICE_*`, `SPEND_ALERT_DAILY_USD` env vars undocumented in `.env.example`; `rag.ts` \u2192 extracted-module architecture still has acknowledged runtime back-edges in `rag-extractive-answer` but no import cycles detected by `architecture-boundaries.test.ts`; several `mockup`-named component files not removed from `src/components/` (production use gated via `mockupsEnabled()`).", + "outcome": "No P0/P1. P2: `RAG_TEXT_WEAK_OR_RELAXATION=true` in `.env.example` contradicts `default(\"false\")` in `env.ts` (process-hardening hardened this to off); `reindex-eval-gate.ts` (488 lines) has no production importer — test-only orphan; `bundle-budget.json` still has `enforce: false` + `totalGzipBytes: null` after first production build window passed. P3: `client-env.ts` duplicates `isLocalNoAuthMode`/`publicUploadsEnabled` from `env.ts` using raw `process.env` (intentional server-only split, but divergent implementations); `OPENAI_PRICE_*`, `SPEND_ALERT_DAILY_USD` env vars undocumented in `.env.example`; `rag.ts` → extracted-module architecture still has acknowledged runtime back-edges in `rag-extractive-answer` but no import cycles detected by `architecture-boundaries.test.ts`; several `mockup`-named component files not removed from `src/components/` (production use gated via `mockupsEnabled()`).", "checks": "`npm run verify:cheap` green (2,290 passed/2 skipped, 0 lint errors, typecheck clean, sitemap aligned, type-scale 0 hits, runtime Node 24/npm 11). `npm run check:env-parity` clean. `npm run docs:check-scripts` passed 266 refs. Architecture-boundaries suite (no cycles, server modules isolated, scripts not imported). Provider-backed (Supabase/OpenAI), browser, release, and live-eval checks not run (confirmation boundary)." }, { @@ -22257,7 +22299,7 @@ "ref": "HEAD (detached) 570e6ba56ae60bea56a32801b9cc96c5a8dfde4f", "head": "570e6ba56ae60bea56a32801b9cc96c5a8dfde4f", "scope": "RAG retrieval/ranking/selection/answer-generation audit (fresh scoped pass; PR #649 D4/D5 governance levers safe-by-default focus, token/effort waste, provider routing)", - "outcome": "No P0/P1. Both #649 levers verified safe-by-default and fail-safe: D4 `unknownCurrentnessPenalty` default 0 (no-op, clamped non-negative, activated only via `RAG_RANKING_CONFIG`); D5 `NEXT_PUBLIC_RAG_TRUST_CAP_ALL_CLAIMS` unset=false (only tightens display trust high\u2192medium, never exposes more; `NEXT_PUBLIC` correct as `buildAnswerRenderModel` runs client-side in `ClinicalDashboard.tsx`). Reasoning-effort defaults correct (`OPENAI_STRONG_REASONING_EFFORT`=medium, fast=low; `strongReasoningEffortForQueryClass` never raises, caps routine at medium, keeps dose/threshold at configured). Provider mode default `auto`. P3 (reaffirmed): (1) `Math.max(hybrid_score, boosted)` floor at rag.ts:663 can nullify demotion penalties (outdated/unknown/poor/lowIndex) at the list tail, making D4 partly inert when activated; (2) `document_status` defaults to `\"unknown\"` (source-metadata.ts:34) for unenriched docs, so activating D4 penalizes the corpus-wide fallback status, not a curated signal \u2014 same mechanism that dropped selection doc-recall@5 1.0\u21920.76 (retrieval-selection.ts:340) \u2014 eval gate is the safeguard.", + "outcome": "No P0/P1. Both #649 levers verified safe-by-default and fail-safe: D4 `unknownCurrentnessPenalty` default 0 (no-op, clamped non-negative, activated only via `RAG_RANKING_CONFIG`); D5 `NEXT_PUBLIC_RAG_TRUST_CAP_ALL_CLAIMS` unset=false (only tightens display trust high→medium, never exposes more; `NEXT_PUBLIC` correct as `buildAnswerRenderModel` runs client-side in `ClinicalDashboard.tsx`). Reasoning-effort defaults correct (`OPENAI_STRONG_REASONING_EFFORT`=medium, fast=low; `strongReasoningEffortForQueryClass` never raises, caps routine at medium, keeps dose/threshold at configured). Provider mode default `auto`. P3 (reaffirmed): (1) `Math.max(hybrid_score, boosted)` floor at rag.ts:663 can nullify demotion penalties (outdated/unknown/poor/lowIndex) at the list tail, making D4 partly inert when activated; (2) `document_status` defaults to `\"unknown\"` (source-metadata.ts:34) for unenriched docs, so activating D4 penalizes the corpus-wide fallback status, not a curated signal — same mechanism that dropped selection doc-recall@5 1.0→0.76 (retrieval-selection.ts:340) — eval gate is the safeguard.", "checks": "Pure review, no mutations except this ledger append. Offline focused Vitest: answer-render-policy + ranking-config + answer-responsiveness-gate 54/54 passed. Provider-backed (Supabase/OpenAI), `eval:retrieval:quality`, browser, and release checks not run (confirmation boundary)." }, { @@ -22609,8 +22651,8 @@ "ref": "PR #655 / codex/release-blocker-remediation", "head": "3ed3a7a2df37d7d15143ab7606e5748ac7ecca09 + reviewed follow-up diff", "scope": "offline dose-route latency follow-up", - "outcome": "The next isolated timeout was a short IM/PO agitation question receiving the same blanket ten-term AND expansion. Agitation dose/route retrieval now keeps only the dose and route signals present in the question; the exact case retrieves its expected source and five citations in 1.54 seconds without a model. All remaining RAG cases 23\u201344 passed individually, so no further deadline crash remains.", - "checks": "Focused clinical-search/retrieval Vitest 111/111; scoped ESLint; Prettier; `git diff --check`; live provider-free case 22 passed; live provider-free cases 23\u201344 passed individually." + "outcome": "The next isolated timeout was a short IM/PO agitation question receiving the same blanket ten-term AND expansion. Agitation dose/route retrieval now keeps only the dose and route signals present in the question; the exact case retrieves its expected source and five citations in 1.54 seconds without a model. All remaining RAG cases 23–44 passed individually, so no further deadline crash remains.", + "checks": "Focused clinical-search/retrieval Vitest 111/111; scoped ESLint; Prettier; `git diff --check`; live provider-free case 22 passed; live provider-free cases 23–44 passed individually." }, { "date": "2026-07-14", @@ -24217,8 +24259,8 @@ "ref": "main (PR #570 squash, glass header)", "head": "cc6bfc1c80902ca3c91e5ba2ebe78a80f3fd9e14", "scope": "post-merge review: CSS/visual/a11y/perf + logic/regression", - "outcome": "No P0/P1. P2s confirmed and fixed in follow-up: build pipeline dropped ALL hand-authored backdrop-filter declarations (manual -webkit- duplicates confused Lightning CSS \u2014 header scrim, bottom dock, and composer pill were tint-only in every engine); scrim retuned to carry the bar's frost alone (header backdrop-root removed) with masks fading to true zero; private-scope alert made sticky inside main (was scroll-away in non-answer modes); scroll-hide reporter reset on breakpoint-gate change; non-forced fallback backgrounds layered to preserve the utility-wins contract.", - "checks": "Ran custom Playwright probe (`node scratchpad/probe-blur.mjs`, Chromium 390x844): baseline showed `getComputedStyle(.edge-glass-header-backdrop).backdropFilter === \"none\"` on all three passes, after fix `blur(14px)/blur(20px)/blur(26px)` \u2014 passed; Ran `node scripts/run-playwright.mjs tests/ui-smoke.spec.ts --project=chromium -g \"glass header|collapse hide|private-scope alert|phone (short|long) answer stays\"`: 6/6 passed; Ran `node scripts/run-playwright.mjs tests/ui-smoke.spec.ts --project=chromium` (full file): 71 passed, 4 failed (pre-existing `/privacy` heading test, fails identically on clean main); Ran `npm run verify:cheap`: exit 0 (1935 unit tests passed); Ran `npm run format:check`: passed; Not run: WebKit/Safari real-device check (no WebKit runner in this environment \u2014 served client chunk verified to pair `-webkit-backdrop-filter` with each declaration for Safari <= 17)" + "outcome": "No P0/P1. P2s confirmed and fixed in follow-up: build pipeline dropped ALL hand-authored backdrop-filter declarations (manual -webkit- duplicates confused Lightning CSS — header scrim, bottom dock, and composer pill were tint-only in every engine); scrim retuned to carry the bar's frost alone (header backdrop-root removed) with masks fading to true zero; private-scope alert made sticky inside main (was scroll-away in non-answer modes); scroll-hide reporter reset on breakpoint-gate change; non-forced fallback backgrounds layered to preserve the utility-wins contract.", + "checks": "Ran custom Playwright probe (`node scratchpad/probe-blur.mjs`, Chromium 390x844): baseline showed `getComputedStyle(.edge-glass-header-backdrop).backdropFilter === \"none\"` on all three passes, after fix `blur(14px)/blur(20px)/blur(26px)` — passed; Ran `node scripts/run-playwright.mjs tests/ui-smoke.spec.ts --project=chromium -g \"glass header|collapse hide|private-scope alert|phone (short|long) answer stays\"`: 6/6 passed; Ran `node scripts/run-playwright.mjs tests/ui-smoke.spec.ts --project=chromium` (full file): 71 passed, 4 failed (pre-existing `/privacy` heading test, fails identically on clean main); Ran `npm run verify:cheap`: exit 0 (1935 unit tests passed); Ran `npm run format:check`: passed; Not run: WebKit/Safari real-device check (no WebKit runner in this environment — served client chunk verified to pair `-webkit-backdrop-filter` with each declaration for Safari <= 17)" }, { "date": "2026-07-13", @@ -25401,7 +25443,7 @@ "ref": "claude/mobile-search-bar-fix (PR #456)", "head": "b73196c2e2e4a536804cdcdb50879c29e2c582c5", "scope": "PR required-testing review", - "outcome": "All 4 Advisory UI regression failures confirmed PR-caused via A/B against pre-merge main (01f2cee0d): the 640px mode-home query moved the phone composer out of the hero, contradicting the design tests; residual \u2265640px vanish remained when the slot never mounts. PR merged (b32c17b34) before the rework landed; follow-up fix shipped on `claude/mode-home-composer-hero-fix` (0px hero query restored, portal-outcome inline fallback, new `@critical` composer-presence test). Also found: main CI red on every push \u2014 missing `RAG_QUERY_HASH_SECRET` secret fails the deployment boot smoke and skips `release-browser-matrix`; owner adding the secret.", + "outcome": "All 4 Advisory UI regression failures confirmed PR-caused via A/B against pre-merge main (01f2cee0d): the 640px mode-home query moved the phone composer out of the hero, contradicting the design tests; residual ≥640px vanish remained when the slot never mounts. PR merged (b32c17b34) before the rework landed; follow-up fix shipped on `claude/mode-home-composer-hero-fix` (0px hero query restored, portal-outcome inline fallback, new `@critical` composer-presence test). Also found: main CI red on every push — missing `RAG_QUERY_HASH_SECRET` secret fails the deployment boot smoke and skips `release-browser-matrix`; owner adding the secret.", "checks": "Local chromium A/B (PR head 4/5 fail vs baseline product-pass); rework targeted run 6/6 pass incl. new `@critical`; `npm run typecheck`; `npm run lint`; focused Prettier check" }, { @@ -25630,8 +25672,8 @@ } ], "counts": { - "records": 2657, - "refs": 1623 + "records": 2661, + "refs": 1626 } } } From 69d121e3b35a16c44b4b251e3a199dadd59880e3 Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Wed, 2 Sep 2026 00:29:48 +0800 Subject: [PATCH 3/3] fix(sources): restore catalogue review and CI fixes --- data/repo-awareness-snapshot.json | 172 +++++++++--------- .../sources/sources-catalogue-client.tsx | 10 +- src/lib/source-authority-registry.ts | 9 + src/lib/sources/catalogue-core.ts | 65 +++++-- src/lib/sources/repository-providers.ts | 96 +++++++++- src/lib/sources/source-url-policy.ts | 1 + tests/source-authority-tooling.test.ts | 18 ++ tests/source-catalogue-core.test.ts | 55 ++++++ tests/source-catalogue-providers.test.ts | 50 ++++- 9 files changed, 360 insertions(+), 116 deletions(-) diff --git a/data/repo-awareness-snapshot.json b/data/repo-awareness-snapshot.json index cc42ee367e..b96ce9c4a4 100644 --- a/data/repo-awareness-snapshot.json +++ b/data/repo-awareness-snapshot.json @@ -1,8 +1,8 @@ { "version": "repo-awareness-snapshot-v1", "captured_revision": { - "sha": "a4d600782727ffbd4fc0e899a3c502c5a668bf5e", - "committed_at": "2026-09-01T23:34:27+08:00" + "sha": "f159844f1c5e8cf22871479a58f0deea00691a81", + "committed_at": "2026-09-02T00:24:19+08:00" }, "routes": { "modes": [ @@ -179,11 +179,6 @@ "file": "src/app/(search-app)/dictionary/search/page.tsx", "area": "product" }, - { - "path": "/dictionary/sources", - "file": "src/app/(search-app)/dictionary/sources/page.tsx", - "area": "product" - }, { "path": "/dictionary/topics", "file": "src/app/(search-app)/dictionary/topics/page.tsx", @@ -1151,6 +1146,11 @@ "file": "src/app/(search-app)/dictionary/browse/page.tsx", "target": "/dictionary/search" }, + { + "path": "/dictionary/sources", + "file": "src/app/(search-app)/dictionary/sources/page.tsx", + "target": "/sources?usedBy=dictionary" + }, { "path": "/differentials", "file": "src/app/(search-app)/differentials/page.tsx", @@ -1461,20 +1461,15 @@ ], "counts": { "modes": 16, - "pages": 205, - "product_pages": 68, + "pages": 204, + "product_pages": 67, "mockup_pages": 137, - "redirects": 17, + "redirects": 18, "api": 60 } }, "documentation": { "documents": [ - { - "path": "docs/README.md", - "section": "root", - "catalogued": false - }, { "path": "docs/adr/0001-use-a-shared-local-first-clinical-ask-orchestrator.md", "section": "adr", @@ -1540,16 +1535,6 @@ "section": "archive", "catalogued": false }, - { - "path": "docs/archive/COLOR_REDESIGN_PLAN.md", - "section": "archive", - "catalogued": false - }, - { - "path": "docs/archive/TOOLS_CONTEXT_FOR_NEW_CHAT.md", - "section": "archive", - "catalogued": false - }, { "path": "docs/archive/branch-cleanup-2026-06-28.md", "section": "archive", @@ -1585,6 +1570,11 @@ "section": "archive", "catalogued": false }, + { + "path": "docs/archive/COLOR_REDESIGN_PLAN.md", + "section": "archive", + "catalogued": false + }, { "path": "docs/archive/design-qa-2026-07-15.md", "section": "archive", @@ -1690,6 +1680,11 @@ "section": "archive", "catalogued": true }, + { + "path": "docs/archive/TOOLS_CONTEXT_FOR_NEW_CHAT.md", + "section": "archive", + "catalogued": false + }, { "path": "docs/audit/2026-07-20-repository-maturity.md", "section": "audit", @@ -1811,37 +1806,37 @@ "catalogued": false }, { - "path": "docs/care-plan/CLAUDE-START-HERE.md", + "path": "docs/care-plan/accessibility-acceptance.md", "section": "care-plan", "catalogued": false }, { - "path": "docs/care-plan/HANDOFF-START-HERE.md", + "path": "docs/care-plan/claude-build-handover-2026-08-21.md", "section": "care-plan", "catalogued": false }, { - "path": "docs/care-plan/accessibility-acceptance.md", + "path": "docs/care-plan/CLAUDE-START-HERE.md", "section": "care-plan", "catalogued": false }, { - "path": "docs/care-plan/claude-build-handover-2026-08-21.md", + "path": "docs/care-plan/clinical-language-trace.md", "section": "care-plan", "catalogued": false }, { - "path": "docs/care-plan/clinical-language-trace.md", + "path": "docs/care-plan/complete-work-ledger.md", "section": "care-plan", "catalogued": false }, { - "path": "docs/care-plan/complete-work-ledger.md", + "path": "docs/care-plan/conversation-transcript-2026-08-21.md", "section": "care-plan", "catalogued": false }, { - "path": "docs/care-plan/conversation-transcript-2026-08-21.md", + "path": "docs/care-plan/HANDOFF-START-HERE.md", "section": "care-plan", "catalogued": false }, @@ -1970,11 +1965,6 @@ "section": "care-plan", "catalogued": false }, - { - "path": "docs/caring-contacts/PROGRESS-LEDGER.md", - "section": "caring-contacts", - "catalogued": false - }, { "path": "docs/caring-contacts/accessibility-acceptance.md", "section": "caring-contacts", @@ -2236,17 +2226,17 @@ "catalogued": false }, { - "path": "docs/caring-contacts/phase-2b-CONTINUATION-PROMPT.md", + "path": "docs/caring-contacts/phase-2b-build-record.md", "section": "caring-contacts", "catalogued": false }, { - "path": "docs/caring-contacts/phase-2b-HANDOVER.md", + "path": "docs/caring-contacts/phase-2b-CONTINUATION-PROMPT.md", "section": "caring-contacts", "catalogued": false }, { - "path": "docs/caring-contacts/phase-2b-build-record.md", + "path": "docs/caring-contacts/phase-2b-HANDOVER.md", "section": "caring-contacts", "catalogued": false }, @@ -2255,11 +2245,6 @@ "section": "caring-contacts", "catalogued": false }, - { - "path": "docs/caring-contacts/phase-2b-sdd-archive/STANDING-DISCIPLINE.md", - "section": "caring-contacts", - "catalogued": false - }, { "path": "docs/caring-contacts/phase-2b-sdd-archive/group-4-review.md", "section": "caring-contacts", @@ -2285,6 +2270,11 @@ "section": "caring-contacts", "catalogued": false }, + { + "path": "docs/caring-contacts/phase-2b-sdd-archive/STANDING-DISCIPLINE.md", + "section": "caring-contacts", + "catalogued": false + }, { "path": "docs/caring-contacts/phase-2b-sdd-archive/task-1-brief.md", "section": "caring-contacts", @@ -2590,6 +2580,11 @@ "section": "caring-contacts", "catalogued": false }, + { + "path": "docs/caring-contacts/PROGRESS-LEDGER.md", + "section": "caring-contacts", + "catalogued": false + }, { "path": "docs/caring-contacts/task-seed-timeline-report.md", "section": "caring-contacts", @@ -2800,11 +2795,6 @@ "section": "design-system", "catalogued": true }, - { - "path": "docs/design-system/TOKENS.md", - "section": "design-system", - "catalogued": true - }, { "path": "docs/design-system/sweep-2026-08-29-structure.md", "section": "design-system", @@ -2845,6 +2835,11 @@ "section": "design-system", "catalogued": false }, + { + "path": "docs/design-system/TOKENS.md", + "section": "design-system", + "catalogued": true + }, { "path": "docs/development-speed-playbook.md", "section": "root", @@ -3161,12 +3156,12 @@ "catalogued": true }, { - "path": "docs/rag-behaviour/README.md", + "path": "docs/rag-behaviour/behaviour-map.md", "section": "rag-behaviour", "catalogued": false }, { - "path": "docs/rag-behaviour/behaviour-map.md", + "path": "docs/rag-behaviour/README.md", "section": "rag-behaviour", "catalogued": false }, @@ -3196,45 +3191,50 @@ "catalogued": true }, { - "path": "docs/rag-improvement/COORDINATION.md", + "path": "docs/rag-improvement/baseline-record.md", "section": "rag-improvement", "catalogued": true }, { - "path": "docs/rag-improvement/HANDOVER.md", + "path": "docs/rag-improvement/COORDINATION.md", "section": "rag-improvement", "catalogued": true }, { - "path": "docs/rag-improvement/README.md", + "path": "docs/rag-improvement/data-flow-register.md", "section": "rag-improvement", "catalogued": true }, { - "path": "docs/rag-improvement/baseline-record.md", + "path": "docs/rag-improvement/gate-b-decision-record-2026-08-18.md", "section": "rag-improvement", - "catalogued": true + "catalogued": false }, { - "path": "docs/rag-improvement/data-flow-register.md", + "path": "docs/rag-improvement/gate-b-decision-record.md", "section": "rag-improvement", - "catalogued": true + "catalogued": false }, { - "path": "docs/rag-improvement/gate-b-decision-record-2026-08-18.md", + "path": "docs/rag-improvement/HANDOVER.md", "section": "rag-improvement", - "catalogued": false + "catalogued": true }, { - "path": "docs/rag-improvement/gate-b-decision-record.md", + "path": "docs/rag-improvement/README.md", "section": "rag-improvement", - "catalogued": false + "catalogued": true }, { "path": "docs/rag-injection-threat-model.md", "section": "root", "catalogued": true }, + { + "path": "docs/README.md", + "section": "root", + "catalogued": false + }, { "path": "docs/reconciliation-playbook.md", "section": "root", @@ -3631,47 +3631,37 @@ "catalogued": false }, { - "path": "docs/superpowers/rag-upgrade/CLOUD-EXECUTION-PROMPT.md", - "section": "superpowers", - "catalogued": false - }, - { - "path": "docs/superpowers/rag-upgrade/LOCAL-CONNECTED-EXECUTION-PROMPT.md", - "section": "superpowers", - "catalogued": false - }, - { - "path": "docs/superpowers/rag-upgrade/canonical/START-HERE.cloud.md", + "path": "docs/superpowers/rag-upgrade/canonical/approval-matrix.md", "section": "superpowers", "catalogued": false }, { - "path": "docs/superpowers/rag-upgrade/canonical/START-HERE.local.md", + "path": "docs/superpowers/rag-upgrade/canonical/connected-execution.md", "section": "superpowers", "catalogued": false }, { - "path": "docs/superpowers/rag-upgrade/canonical/approval-matrix.md", + "path": "docs/superpowers/rag-upgrade/canonical/execution-order.md", "section": "superpowers", "catalogued": false }, { - "path": "docs/superpowers/rag-upgrade/canonical/connected-execution.md", + "path": "docs/superpowers/rag-upgrade/canonical/sdd-execution.md", "section": "superpowers", "catalogued": false }, { - "path": "docs/superpowers/rag-upgrade/canonical/execution-order.md", + "path": "docs/superpowers/rag-upgrade/canonical/START-HERE.cloud.md", "section": "superpowers", "catalogued": false }, { - "path": "docs/superpowers/rag-upgrade/canonical/sdd-execution.md", + "path": "docs/superpowers/rag-upgrade/canonical/START-HERE.local.md", "section": "superpowers", "catalogued": false }, { - "path": "docs/superpowers/rag-upgrade/cloud/START-HERE.md", + "path": "docs/superpowers/rag-upgrade/CLOUD-EXECUTION-PROMPT.md", "section": "superpowers", "catalogued": false }, @@ -3745,6 +3735,11 @@ "section": "superpowers", "catalogued": false }, + { + "path": "docs/superpowers/rag-upgrade/cloud/START-HERE.md", + "section": "superpowers", + "catalogued": false + }, { "path": "docs/superpowers/rag-upgrade/execution-artifacts/rag-answer-quality-and-repository-coverage-v1/README.md", "section": "superpowers", @@ -3756,7 +3751,7 @@ "catalogued": false }, { - "path": "docs/superpowers/rag-upgrade/local/START-HERE.md", + "path": "docs/superpowers/rag-upgrade/LOCAL-CONNECTED-EXECUTION-PROMPT.md", "section": "superpowers", "catalogued": false }, @@ -3830,6 +3825,11 @@ "section": "superpowers", "catalogued": false }, + { + "path": "docs/superpowers/rag-upgrade/local/START-HERE.md", + "section": "superpowers", + "catalogued": false + }, { "path": "docs/superpowers/specs/2026-07-02-triage-security-reliability-design.md", "section": "superpowers", @@ -3985,11 +3985,6 @@ "section": "root", "catalogued": false }, - { - "path": "docs/ward-flow-phase-3-workspace/README.md", - "section": "ward-flow-phase-3-workspace", - "catalogued": false - }, { "path": "docs/ward-flow-phase-3-workspace/clinical-changes-report.md", "section": "ward-flow-phase-3-workspace", @@ -4025,6 +4020,11 @@ "section": "ward-flow-phase-3-workspace", "catalogued": false }, + { + "path": "docs/ward-flow-phase-3-workspace/README.md", + "section": "ward-flow-phase-3-workspace", + "catalogued": false + }, { "path": "docs/ward-flow-phase-3-workspace/task-1-brief.md", "section": "ward-flow-phase-3-workspace", diff --git a/src/components/sources/sources-catalogue-client.tsx b/src/components/sources/sources-catalogue-client.tsx index 6709c97d71..f0bb56bf53 100644 --- a/src/components/sources/sources-catalogue-client.tsx +++ b/src/components/sources/sources-catalogue-client.tsx @@ -2,6 +2,7 @@ import Link from "next/link"; import { SearchResultsHeaderBand } from "@/components/clinical-dashboard/search-results-header-band"; +import { eyebrowText, fieldControlPlain } from "@/components/ui-primitives"; import { usePathname, useRouter, useSearchParams } from "next/navigation"; import { useMemo } from "react"; @@ -22,8 +23,7 @@ const bandLabels: Record = { excluded: "Excluded", }; -const filterClassName = - "min-h-12 w-full rounded-xl border border-[color:var(--border)] bg-[color:var(--surface)] px-3 text-sm text-[color:var(--text)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:var(--primary)]"; +const filterClassName = fieldControlPlain; function titleCase(value: string) { return value.replaceAll("_", " ").replace(/\b\w/g, (letter) => letter.toUpperCase()); @@ -217,7 +217,7 @@ export function SourcesCatalogueClient({ return (
-

Traceability

+

Traceability

Sources

Browse the clinical sources registered across the application. Ratings organise review work and do not measure @@ -374,10 +374,6 @@ export function SourcesCatalogueClient({

-

- {visibleEntries.length} {visibleEntries.length === 1 ? "source" : "sources"} -

- {visibleEntries.length === 0 ? (

No sources match these filters

diff --git a/src/lib/source-authority-registry.ts b/src/lib/source-authority-registry.ts index b849a5dd85..6a05a159b0 100644 --- a/src/lib/source-authority-registry.ts +++ b/src/lib/source-authority-registry.ts @@ -100,6 +100,15 @@ export const sourceAuthorityRegistry = [ scope: "wa", tier: "wa_validated", }), + authority({ + key: "office-of-the-chief-psychiatrist-wa", + codes: ["OCP WA", "OCPWA"], + publisher: "Office of the Chief Psychiatrist WA", + publisherAliases: ["Office of the Chief Psychiatrist", "Office of Chief Psychiatrist WA"], + jurisdictions: waJurisdictions, + scope: "wa", + tier: "wa_validated", + }), authority({ key: "armadale-kalamunda-group", codes: ["AKG"], diff --git a/src/lib/sources/catalogue-core.ts b/src/lib/sources/catalogue-core.ts index b53e5eebcb..316eb6b04a 100644 --- a/src/lib/sources/catalogue-core.ts +++ b/src/lib/sources/catalogue-core.ts @@ -44,6 +44,13 @@ const INCOMPLETE_METADATA_WARNINGS = new Set([ "verification_unknown", "invalid_date", ]); +const RESOLVED_METADATA_GAP_WARNINGS = new Set([ + "missing_publisher", + "missing_version", + "missing_dates", + "unknown_jurisdiction", +]); +const COMPATIBILITY_FIELDS = ["publisher", "publisherCode", "jurisdiction", "version"] as const; function opaqueSourceId(identity: string) { return `src_${createHash("sha256").update(identity).digest("hex").slice(0, 20)}`; @@ -57,7 +64,7 @@ function baseIdentity(input: ClinicalSourceReferenceInput) { if (input.documentId) return `document:${input.documentId}`; if (input.sourceId) return `source:${input.sourceId.trim().toLowerCase()}`; const url = safeHttpsUrl(input.canonicalUrl); - if (url) return `url:${url}|version:${input.version ?? "unknown"}`; + if (url) return `url:${url}`; if (input.publisher && input.title) { return `title:${normalizeSourceAuthorityText(input.publisher)}|${normalizeSourceAuthorityText(input.title)}|${input.version ?? "unknown"}`; } @@ -65,10 +72,37 @@ function baseIdentity(input: ClinicalSourceReferenceInput) { return provisionalIdentity ? `provisional:${provisionalIdentity}` : "provisional:unresolved"; } -function compatibilityKey(input: ClinicalSourceReferenceInput) { - return [input.publisher, input.publisherCode, input.jurisdiction, input.version] - .map((value) => normalizeSourceAuthorityText(value)) - .join("|"); +function metadataValue(value: string | null) { + return normalizeSourceAuthorityText(value); +} + +function compatibleMetadata(left: ClinicalSourceReferenceInput, right: ClinicalSourceReferenceInput) { + return COMPATIBILITY_FIELDS.every((field) => { + const leftValue = metadataValue(left[field]); + const rightValue = metadataValue(right[field]); + return !leftValue || !rightValue || leftValue === rightValue; + }); +} + +function partitionCompatibleReferences(inputs: readonly ClinicalSourceReferenceInput[]) { + const partitions: ClinicalSourceReferenceInput[][] = []; + for (const input of [...inputs].sort((left, right) => + compareText(canonicalReferenceKey(left), canonicalReferenceKey(right)), + )) { + const matches = partitions.filter((partition) => + partition.every((candidate) => compatibleMetadata(candidate, input)), + ); + if (matches.length === 1) matches[0].push(input); + else partitions.push([input]); + } + return partitions; +} + +function metadataPartitionKey(inputs: readonly ClinicalSourceReferenceInput[]) { + return COMPATIBILITY_FIELDS.map((field) => { + const values = [...new Set(inputs.map((input) => metadataValue(input[field])).filter(Boolean))].sort(compareText); + return values.join(",") || "unknown"; + }).join("|"); } function metadataFor(input: ClinicalSourceReferenceInput) { @@ -402,7 +436,8 @@ function catalogueEntry( ]), ); const warnings = sortedWarnings([ - ...inputs.flatMap(sourceWarnings), + ...sourceWarnings(merged), + ...inputs.flatMap(sourceWarnings).filter((warning) => !RESOLVED_METADATA_GAP_WARNINGS.has(warning)), ...(metadataConflict ? (["metadata_conflict"] satisfies SourceCatalogueWarning[]) : []), ]); const canonicalLocation = canonicalLocationFor(inputs); @@ -457,14 +492,16 @@ export function canonicalizeSourceReferences( ), ); for (const [identity, identityInputs] of identityGroups) { - const partitions = new Map(); - for (const input of identityInputs) { - const key = compatibilityKey(input); - partitions.set(key, [...(partitions.get(key) ?? []), input]); - } - const metadataConflict = partitions.size > 1; - for (const [key, partition] of partitions) { - entries.push(catalogueEntry(`${identity}|compatibility:${key}`, partition, metadataConflict)); + const partitions = partitionCompatibleReferences(identityInputs); + const metadataConflict = partitions.length > 1; + for (const partition of partitions) { + entries.push( + catalogueEntry( + metadataConflict ? `${identity}|compatibility:${metadataPartitionKey(partition)}` : identity, + partition, + metadataConflict, + ), + ); } } return entries.sort(compareClinicalSources); diff --git a/src/lib/sources/repository-providers.ts b/src/lib/sources/repository-providers.ts index 9f9d1800ee..9b0d1b6def 100644 --- a/src/lib/sources/repository-providers.ts +++ b/src/lib/sources/repository-providers.ts @@ -2,6 +2,7 @@ import "server-only"; import { createHash } from "node:crypto"; +import formsPdfManifest from "../../../data/forms-pdf-manifest.json"; import formsSnapshot from "../../../data/forms-page-snapshot.json"; import dsmClinicalContent from "../../data/dsm-clinical-content.json"; import therapiesSource from "../../data/therapies-source.json"; @@ -19,6 +20,8 @@ import { type FormulationMechanism, type FormulationSource, } from "@/lib/formulation"; +import { officialFormsRegisterUrl } from "@/lib/form-catalog"; +import { normalizeCode, officialForms } from "@/lib/form-register"; import { loadMedicationSnapshot } from "@/lib/medication-snapshot"; import { mhaActMetadata } from "@/lib/mha-act-sections"; import { loadServicesSnapshot } from "@/lib/service-catalog"; @@ -298,11 +301,72 @@ const specifierProvider: ClinicalSourceProvider = { references: () => [...specifierAuthoritativeSourceReferences(authoritativeSources()), ...specifierReviewReferences()], }; +const officialFormByCode = new Map(officialForms.map((form) => [normalizeCode(form.code), form] as const)); + +function formUsage(code: string, title: string, field: string): SourceUsage { + return { + modeId: "forms", + recordId: `official-form-${normalizeCode(code)}`, + recordLabel: `Form ${code}: ${title}`, + field, + }; +} + +function officialFormReferences() { + const references = formsPdfManifest.assets.flatMap((asset) => { + if (!asset.officialPdfUrl) return []; + const form = officialFormByCode.get(normalizeCode(asset.code)); + const title = form?.title ?? `Form ${asset.code}`; + return [ + reference(formUsage(asset.code, title, "officialPdfUrl"), { + sourceId: `official-mha-form-${normalizeCode(asset.code)}`, + title: `Form ${asset.code}: ${title}`, + publisher: "Office of the Chief Psychiatrist WA", + publisherCode: "OCP WA", + canonicalUrl: asset.officialPdfUrl, + version: formsPdfManifest.generatedAt, + reviewDate: formsPdfManifest.generatedAt, + jurisdiction: "Australia/WA", + evidenceType: "regulatory", + documentStatus: "current", + validationStatus: "locally_reviewed", + contentMode: "link_only", + topics: ["Mental Health Act", "official form"], + }), + ]; + }); + return [ + ...references, + ...officialForms.map((form) => + reference(formUsage(form.code, form.title, "officialRegisterUrl"), { + sourceId: "official-mha-2014-forms-register", + title: "Mental Health Act 2014 forms", + publisher: "Office of the Chief Psychiatrist WA", + publisherCode: "OCP WA", + canonicalUrl: officialFormsRegisterUrl, + version: formsPdfManifest.generatedAt, + reviewDate: formsPdfManifest.generatedAt, + jurisdiction: "Australia/WA", + evidenceType: "regulatory", + documentStatus: "current", + validationStatus: "locally_reviewed", + contentMode: "link_only", + topics: ["Mental Health Act", "official form"], + }), + ), + ]; +} + const formsProvider: ClinicalSourceProvider = { id: "forms", - sourcePaths: ["data/forms-page-snapshot.json"], - references: () => - formsSnapshot.sourceDocuments.flatMap((document) => { + sourcePaths: [ + "data/forms-page-snapshot.json", + "data/forms-pdf-manifest.json", + "src/lib/form-catalog.ts", + "src/lib/form-register.ts", + ], + references: () => [ + ...formsSnapshot.sourceDocuments.flatMap((document) => { const referencingForms = formsSnapshot.forms.filter((form) => form.sourceDocumentId === document.id); const usages: SourceUsage[] = referencingForms.length ? referencingForms.map((form) => ({ @@ -328,6 +392,8 @@ const formsProvider: ClinicalSourceProvider = { }), ); }), + ...officialFormReferences(), + ], }; const mhaProvider: ClinicalSourceProvider = { @@ -621,6 +687,30 @@ export function repositorySourceCoverageIssues(inputs: RepositorySourceCoverageI issues.push(`Forms record ${form.id} source document usage is not captured`); } } + for (const asset of formsPdfManifest.assets) { + if ( + !formReferences.some( + (item) => + item.canonicalUrl === asset.officialPdfUrl && + item.usage.recordId === `official-form-${normalizeCode(asset.code)}` && + item.usage.field === "officialPdfUrl", + ) + ) { + issues.push(`Forms official PDF ${asset.code} is not captured`); + } + } + for (const form of officialForms) { + if ( + !formReferences.some( + (item) => + item.canonicalUrl === officialFormsRegisterUrl && + item.usage.recordId === `official-form-${normalizeCode(form.code)}` && + item.usage.field === "officialRegisterUrl", + ) + ) { + issues.push(`Forms register usage ${form.code} is not captured`); + } + } const dsmReferences = providerReferences.get("dsm") ?? []; const dsmContent = dsmClinicalContent as DsmClinicalContent; diff --git a/src/lib/sources/source-url-policy.ts b/src/lib/sources/source-url-policy.ts index 7d37c3fcee..24ab90e567 100644 --- a/src/lib/sources/source-url-policy.ts +++ b/src/lib/sources/source-url-policy.ts @@ -18,6 +18,7 @@ export const GOVERNED_SOURCE_HOSTS = [ "www.aihw.gov.au", "www.beyondblue.org.au", "www.cci.health.wa.gov.au", + "www.chiefpsychiatrist.wa.gov.au", "www.entrypointperth.com.au", "www.gamblinghelponline.org.au", "www.health.gov.au", diff --git a/tests/source-authority-tooling.test.ts b/tests/source-authority-tooling.test.ts index 4a2026f9d1..890b37392a 100644 --- a/tests/source-authority-tooling.test.ts +++ b/tests/source-authority-tooling.test.ts @@ -40,6 +40,24 @@ describe("source authority metadata tooling", () => { }); }); + it("recognizes the Office of the Chief Psychiatrist as a WA authority", () => { + expect( + classifySourceAuthority({ + publisher_code: "OCP WA", + publisher: "Office of the Chief Psychiatrist WA", + jurisdiction: "Australia/WA", + document_status: "current", + clinical_validation_status: "locally_reviewed", + extraction_quality: "good", + }), + ).toMatchObject({ + authorityKey: "office-of-the-chief-psychiatrist-wa", + authority: { scope: "wa" }, + designation: "trusted", + conflict: false, + }); + }); + it("prefers the document identity over parent health-service path segments", () => { expect( inferSourceAuthorityFromIdentity( diff --git a/tests/source-catalogue-core.test.ts b/tests/source-catalogue-core.test.ts index 7fe952f62e..11dc4650b0 100644 --- a/tests/source-catalogue-core.test.ts +++ b/tests/source-catalogue-core.test.ts @@ -279,6 +279,61 @@ describe("clinical source catalogue", () => { expect(entries[0].usedBy).toHaveLength(2); }); + it("enriches incomplete metadata for the same canonical source without splitting its usages", () => { + const entries = canonicalizeSourceReferences([ + reference({ + sourceId: null, + canonicalUrl: "https://www.ranzcp.org/metadata-completion", + publisher: null, + publisherCode: null, + jurisdiction: null, + usage: { + modeId: "factsheets", + recordId: "depression", + recordLabel: "Depression", + field: "sources", + }, + }), + reference({ + sourceId: null, + canonicalUrl: "https://www.ranzcp.org/metadata-completion", + publisher: "Royal Australian and New Zealand College of Psychiatrists", + publisherCode: "RANZCP", + jurisdiction: "Australia", + }), + ]); + + expect(entries).toHaveLength(1); + expect(entries[0]).toMatchObject({ + publisher: "Royal Australian and New Zealand College of Psychiatrists", + publisherCode: "RANZCP", + }); + for (const warning of ["metadata_conflict", "missing_publisher", "unknown_jurisdiction"]) { + expect(entries[0].warnings).not.toContain(warning); + } + expect(entries[0].usedBy).toHaveLength(2); + }); + + it("keeps a canonical source detail ID stable when metadata is completed", () => { + const incomplete = reference({ + sourceId: null, + canonicalUrl: "https://www.ranzcp.org/stable-detail-source", + publisher: null, + publisherCode: null, + jurisdiction: null, + version: null, + }); + const completed = { + ...incomplete, + publisher: "Royal Australian and New Zealand College of Psychiatrists", + publisherCode: "RANZCP", + jurisdiction: "Australia", + version: "2025", + }; + + expect(canonicalizeSourceReferences([completed])[0].id).toBe(canonicalizeSourceReferences([incomplete])[0].id); + }); + it("does not merge conflicting versions or publishers", () => { const entries = canonicalizeSourceReferences([ reference(), diff --git a/tests/source-catalogue-providers.test.ts b/tests/source-catalogue-providers.test.ts index 164b9db224..082f47c391 100644 --- a/tests/source-catalogue-providers.test.ts +++ b/tests/source-catalogue-providers.test.ts @@ -2,6 +2,7 @@ import { describe, expect, it, vi } from "vitest"; vi.mock("server-only", () => ({})); +import formsPdfManifest from "../data/forms-pdf-manifest.json"; import formsSnapshot from "../data/forms-page-snapshot.json"; import dsmClinicalContent from "../src/data/dsm-clinical-content.json"; import therapies from "../src/data/therapies-source.json"; @@ -9,6 +10,8 @@ import { calculators } from "@/components/calculators/calculator-fixtures"; import { factsheets } from "@/components/factsheets/factsheets-data"; import { dictionarySources } from "@/lib/dictionary-data"; import { formulationMechanisms, formulationSourceLibrary } from "@/lib/formulation"; +import { officialFormsRegisterUrl } from "@/lib/form-catalog"; +import { normalizeCode, officialForms } from "@/lib/form-register"; import { loadMedicationSnapshot } from "@/lib/medication-snapshot"; import { loadServicesSnapshot } from "@/lib/service-catalog"; import { authoritativeSources, loadSpecifiersContent } from "@/lib/specifiers-content"; @@ -28,7 +31,12 @@ const expectedProviders = { formulation: ["src/data/formulation-content.json"], therapies: ["src/data/therapies-source.json"], specifiers: ["data/specifiers-content.json"], - forms: ["data/forms-page-snapshot.json"], + forms: [ + "data/forms-page-snapshot.json", + "data/forms-pdf-manifest.json", + "src/lib/form-catalog.ts", + "src/lib/form-register.ts", + ], mha: ["data/mha-2014-sections.source.json"], medications: ["data/medications-snapshot.json"], services: ["data/services-snapshot.json"], @@ -71,7 +79,7 @@ describe("repository source providers", () => { ); }); - it("pins the 49 currently governed structured source hosts without deriving trust at runtime", () => { + it("pins the 50 currently governed structured source hosts without deriving trust at runtime", () => { const emittedHosts = new Set( repositorySourceReferences() .map((reference) => reference.canonicalUrl) @@ -79,7 +87,7 @@ describe("repository source providers", () => { .map((value) => new URL(value).hostname), ); - expect(GOVERNED_SOURCE_HOSTS).toHaveLength(49); + expect(GOVERNED_SOURCE_HOSTS).toHaveLength(50); expect(new Set(GOVERNED_SOURCE_HOSTS)).toEqual(emittedHosts); }); @@ -142,9 +150,8 @@ describe("repository source providers", () => { ).toEqual(specifierSourceFamilies()); const formsReferences = provider("forms").references(); - expect(new Set(formsReferences.map((reference) => reference.sourceId))).toEqual( - new Set(formsSnapshot.sourceDocuments.map((document) => document.id)), - ); + const formSourceIds = new Set(formsReferences.map((reference) => reference.sourceId)); + expect(formsSnapshot.sourceDocuments.every((document) => formSourceIds.has(document.id))).toBe(true); for (const form of formsSnapshot.forms) { expect(formsReferences).toContainEqual( expect.objectContaining({ @@ -158,6 +165,37 @@ describe("repository source providers", () => { }), ); } + const officialPdfAssets = formsPdfManifest.assets.filter((asset) => asset.officialPdfUrl); + expect( + new Set( + formsReferences + .filter((reference) => reference.usage.field === "officialPdfUrl") + .map((reference) => reference.canonicalUrl), + ), + ).toEqual(new Set(officialPdfAssets.map((asset) => asset.officialPdfUrl))); + for (const asset of officialPdfAssets) { + expect(formsReferences).toContainEqual( + expect.objectContaining({ + canonicalUrl: asset.officialPdfUrl, + usage: expect.objectContaining({ + recordId: `official-form-${normalizeCode(asset.code)}`, + field: "officialPdfUrl", + }), + }), + ); + } + expect( + new Set( + formsReferences + .filter((reference) => reference.usage.field === "officialRegisterUrl") + .map((reference) => reference.usage.recordId), + ), + ).toEqual(new Set(officialForms.map((form) => `official-form-${normalizeCode(form.code)}`))); + expect( + formsReferences + .filter((reference) => reference.usage.field === "officialRegisterUrl") + .every((reference) => reference.canonicalUrl === officialFormsRegisterUrl), + ).toBe(true); const medicationReferences = provider("medications").references(); const medicationSourceRows = loadMedicationSnapshot().flatMap((medication) =>