diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md index 0eebf7bd38..12cebf10a6 100644 --- a/docs/branch-review-ledger.md +++ b/docs/branch-review-ledger.md @@ -144,6 +144,16 @@ Records before 2026-07-28 were written by hand and had drifted: 146 lines carrie | 2026-07-30 | PR #1396 / claude/latency-findings-impl-s8g01v | 70e810b66881e17aa9f58126fdad970986bda911 | User ask: resolve comments + Production UI phone-scroll + main sync | FIXED: synced main (DIRTY was staleness); removed union ledger dup; adapted phone-scroll asserts for Answer strategy-overlay + overlay/reserve-only calculator budget + focus pre-scroll inside 8px reveal band. Codex P1s already on tip; 0 unresolved threads. Focused Chromium phone-scroll 9/9 green (system Chrome). | phone-scroll focused 9/9; check:branch-review-ledger PASS; merge-tree clean; prior Codex P1s retained | | 2026-07-30 | HEAD | 13c16cf07c854b50daa35a2ef2a2ea76d5e059e1 | ci-testing-approach | findings: UI-load flake #093 dominates PR reds; schedule full-sentinel blocks release-browser via audit; UI scope overfires on src/app/api; ~40% PR runs cancelled wasting ~12 UI-hrs; CI_TRIAGE inert; eval:rag:offline claimed-in-CI but only fixtures run | gh-ci-500-runs,ci.yml,ci-change-scope,testing.md,process-hardening,outstanding-issues-093-095-097-023,flake-ledger-empty | | 2026-07-30 | cursor/ci-testing-review-1bf5 | 13c16cf07c854b50daa35a2ef2a2ea76d5e059e1 | ci-testing-approach | Corrects the ref cell from the unresolved placeholder "HEAD" to the actual branch name, so ledger:lookup can match this review by branch (Codex P2 finding on PR #1406). | node scripts/branch-review-ledger.mjs lookup cursor/ci-testing-review-1bf5 --scope ci-testing-approach | +| 2026-07-30 | origin/circleci-project-setup | 9a55990053e26c02703b1ec9f2523a7c85e21e14 | branch-cleanup | REJECTED and deleted remote. Unique tip only changed trailing newline on obsolete .circleci hello-world config; CircleCI removed from main in PR #1412. No open PR. | fetch --prune; three-dot + tip inspect; gh pr list open=0; main has no .circleci; GitHub reads explicitly authorized; no non-GitHub provider checks. | +| 2026-07-30 | origin/execute-audit-code-remediation | 3470279fba23ad442d59d34552eb576e87f24141 | branch-cleanup | 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. | 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. | +| 2026-07-30 | origin/apply-audit-remediation-protocol | 046cb38ad45411c5f539636d4c976b25195f7bbd | branch-cleanup | RETAIN. Closed PR #1338; tip still has unique files main lacks (motion-tokens.ts, use-overlay-presence.ts) plus stale sheet/globals diffs. Not empty vs main; do not delete. | ledger lookup; cherry-pick+three-dot; blob existence on main; gh PR #1338 CLOSED; GitHub reads explicitly authorized; no non-GitHub provider checks. | +| 2026-07-30 | origin/audit-remediation | 5c6cef2fec5f4457dc46c0dc0e758d259e0c1dc8 | branch-cleanup | RETAIN. PR #1153 merged earlier but tip still differs from main on test-run-lock wait semantics, PDF extractor empty-stderr path, and related tests. Unique content not absorbed; keep until ported or rejected. | ledger lookup; cherry-pick+blob equality vs main; gh PR #1153 MERGED; open=0; GitHub reads explicitly authorized; no non-GitHub provider checks. | +| 2026-07-30 | origin/css-layout-audit-report | 5fa061a32b0c56c447d3bd7f444869eadbfc434e | branch-cleanup | RETAIN. Related CSS layout work merged via #1296, but tip blobs still differ from main on globals.css, AccessibleTable, source-preview-popover, settings-search mockup. Not empty; keep. | ledger lookup; cherry-pick; per-file blob equality vs main; gh related #1296 MERGED; GitHub reads explicitly authorized; no non-GitHub provider checks. | +| 2026-07-30 | origin/execute-audit-remediation-fixes | dcdcb5b2b0546eddbb5bfd6efdb68122be2eabaa | branch-cleanup | RETAIN. Closed PR #1352 (earlier #1305 merged from same name). Tip still has 33-file unique three-dot diff vs main; several added paths now exist on main via other merges but residual patch remains. Keep. | ledger lookup; cherry-pick+name-status; path existence on main; gh #1352 CLOSED #1305 MERGED; GitHub reads explicitly authorized; no non-GitHub provider checks. | +| 2026-07-30 | origin/execute-audit-remediation-plan | cc645928cefb18e4c08870ddc1c483bc051a92b9 | branch-cleanup | RETAIN at new HEAD (prior branch-cleanup deletion was a different tip). Closed PRs #1255/#1188; tip still has 30-file unique three-dot content vs main. Keep until ported or explicitly rejected. | ledger lookup (earlier DELETED at 8b863911); cherry-pick; gh CLOSED; GitHub reads explicitly authorized; no non-GitHub provider checks. | +| 2026-07-30 | origin/execute-audit-remediation-tasks | bdcf8d5c1f14c927bf5b71aaacd34d006856da4f | branch-cleanup | RETAIN. Closed PR #1347; tip adds check-answer-quality-thresholds.ts and check-cost-cap-preflight.ts that main lacks, plus other diffs. Keep. | ledger lookup; cherry-pick; MAIN_LACKS path check; gh #1347 CLOSED; GitHub reads explicitly authorized; no non-GitHub provider checks. | +| 2026-07-30 | origin/execute-typography-audit-fixes | dd641579f4cf54f82de89ef268ac8aa6acb439b5 | branch-cleanup | RETAIN. Closed PR #1185 (clean successor #1294 merged); tip blobs still differ from main on globals.css and mockup typography tweaks. Not empty; keep. | ledger lookup; cherry-pick; blob equality; gh #1185 CLOSED #1294 MERGED; GitHub reads explicitly authorized; no non-GitHub provider checks. | +| 2026-07-30 | origin/implement-audit-design-fixes | dda4a42baa34e28f12d1e676fcabdbdfaef820c8 | branch-cleanup | RETAIN. Closed PR #1263; tip still carries unique not-found/error route files and a large three-dot diff vs main. Keep. | ledger lookup; cherry-pick; path existence; gh #1263 CLOSED; GitHub reads explicitly authorized; no non-GitHub provider checks. | | 2026-07-30 | PR #1400 | e869cb9d7ab20939361b277d1c6fcc07bbb6ca45 | pr-1400-guard-push-band-adoption | 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. | 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 | | 2026-07-30 | cursor/ci-hygiene-gates-1bf5 | ad9da6a6f8ba3884b389fa78e678bb88ee72d9d1 | ci-hygiene-gates | implemented matrix unblock, scope narrow, cancelled≠failure, pinned gitleaks, critical-first UI, eval:rag:offline; skipped #093; verify:cheap 4471 pass | verify:cheap,check:ci-scope,check:gitleaks-pinned,check:gate-manifest,eval:rag:offline | | 2026-07-30 | cursor/ci-hygiene-gates-1bf5 | b660dbc5a10d7ca3da03541028017f0abc6b5bd3 | ci-hygiene-gates merge-readiness | findings | check:ci-scope;check:gitleaks-pinned;scope-classify PR files ui_changed=false;sim cancelled-as-neutral | @@ -155,3 +165,4 @@ Records before 2026-07-28 were written by hand and had drifted: 146 lines carrie | 2026-07-30 | origin/main | 3569e7888bba5d11f143f27c11eb9bfa58800e4f | dependency installation and CI reproducibility | no P0-P2 findings; corrected stale setup-ui-e2e cache description | manifest-lock parity; Actions pins; merge-marker scan; merged PR 1360 diff | | 2026-07-30 | codex/chat-dependency-pr-review-dependency-pr-review-20260730 | 2aee8c74e64bd09954fe1b474c73b25805063de0 | open PR changed-scope review | APPROVE: setup action description now matches clean npm install with npm-download caching; no behavior change. | check:github-actions PASS; diff review; no unresolved threads | | 2026-07-30 | claude/top-search-design-mockups-w53znc | 939d5799b9999f3f63928e1b2c95d097f07eff90 | open PR changed-scope review | APPROVE: PR 1400 closeout and issue IDs 131-134 are unique, internally consistent, and preserve the append-only ledgers. | check:branch-review-ledger PASS; check:outstanding-issues PASS; diff review; no unresolved threads | +| 2026-07-30 | cursor/safe-branch-cleanup-78a8 | c5190f38834ef2e928edc4876d971aa9d5d69fe7 | open PR changed-scope review | APPROVE after fixes: cleanup refs are discoverable, provider evidence is accurate, and issue 108 closure is preserved against current main. | check:branch-review-ledger PASS; check:outstanding-issues PASS; two review threads resolved | diff --git a/docs/outstanding-issues.md b/docs/outstanding-issues.md index d46826bb39..01bb0ec85b 100644 --- a/docs/outstanding-issues.md +++ b/docs/outstanding-issues.md @@ -145,7 +145,6 @@ removed after current-main verification; it is not missing recommended work. | #105 | P3 | task | Verify the `#017`-exempt client latency wins in a browser | **Outcome:** the two zero-payload client fixes are confirmed in a real browser. `#017` gates _payload_ decisions (#012/#013/#016 are all byte-count items); a `loading` fallback ships zero bytes and a resource hint ships ~60, so neither can be justified or refuted by a Lighthouse number — that is why these were not held behind #017. **Implementation shipped 2026-07-29; browser verification still PENDING:** 10 of 11 `ssr:false` dashboard surfaces had NO `loading` fallback and rendered nothing between HTML arrival and chunk execution — all now use the shared `LoadingPanel` (`role="status"` + accessible label); Supabase `preconnect`/`dns-prefetch` added, since `AuthProvider` awaits a cross-origin `getUser()` on mount that every auth-gated fetch queues behind and there were no resource hints anywhere in `src/`. Shipped with `verify:cheap` + `verify:pr-local` only. **Next:** run `npm run verify:ui` once the heavy-run lock is free, and confirm the preconnect appears in `` on a live page. **Stop:** the two sidebar dialogs are intentionally excluded — they mount on open, so a fallback would render into a closed dialog. | `docs/audit/latency-audit-2026-07-28.md` L3-4/L3-5; `src/components/clinical-dashboard/clinical-dashboard-lazy.tsx` | 2026-07-29 | | #106 | P2 | rec | Ingestion worker and indexing agent are verified by grepping their own source | **Outcome:** the ingestion worker and indexing agent are verified by executing code, not by asserting on their own source text. **Detail:** measured 2026-07-29 via `npm run test:coverage` — `worker/main.ts` (2,015 lines) and `supabase/functions/indexing-v3-agent/index.ts` (1,966 lines) each report **0% executed lines**; no test imports either module. Both are covered only by `readFileSync` + `toContain` assertions in `worker-safe-logging.test.ts`, `worker-visual-capture.test.ts` and `document-metadata-merge.test.ts`, which pass whenever a string is present and break on harmless refactors; `document-metadata-merge.test.ts` additionally reimplements the SQL deep-merge in TypeScript and tests the reimplementation rather than the worker. Area totals: `worker/` 18.6% lines, `supabase/functions/` 4.5%. **Next:** continue the extraction pattern that already works here — `indexing-v3-agent/behavior.ts` (167 lines, 96%) and `ingestion-worker/auth.ts` (30 lines, 90%) — pulling the highest-risk decision points out of `worker/main.ts` (job claim/retry, generation commit, failure classification) into importable modules with executing tests, retiring the matching source-text assertion as each lands. Roughly cost-neutral: each extracted test replaces a grep assertion. **Stop:** do not try to make the 2,000-line entrypoint importable in one pass; extract incrementally and keep each step green. | session 2026-07-29 test-coverage analysis | 2026-07-29 | | #107 | P2 | rec | Component state matrices are the largest untested surface | **Outcome:** loading / empty / error / disabled states on interactive components are covered by executing tests, not only by E2E happy paths. **Detail:** measured 2026-07-29 — production components (excluding mockups) sit at **38.2% lines / 22.8% branch** across 12,602 lines, with **83 of 208 files at zero executed lines**; there are 51 `.dom.test.tsx` files against 195 components. Playwright does visit these routes, so they are smoke-covered, but branch coverage is where the state matrix lives and smoke journeys rarely reach it. Worst by uncovered lines: `global-search-shell.tsx` (7%), `mode-action-popup.tsx` (21%), `answer-content.tsx` (27%), `document-search-results.tsx` (32%), `universal-search-command-surface.tsx` (39%), `master-search-header.tsx` (43%). A concrete first target with clinical meaning: `calculator-ui.tsx` now covers all exported scoring logic, but `seedCheckboxDefaults`, `toggleCheckboxAnswer` and `selectOptionAnswer` stay uncovered because they are module-private and only reachable through React event handlers — `seedCheckboxDefaults` is what makes an all-negative CAGE / SAD PERSONS screen read as a valid 0 rather than incomplete, so a regression there is a false-negative risk. **Next:** treat as a per-PR convention rather than a backfill push — `docs/testing.md` already prescribes the state matrix, so the gap is enforcement. Start with `global-search-shell.tsx`, which `docs/search-chrome-behaviour.md` treats as a contract surface. Keep additions in the jsdom tier (measured ~0.54s per file) instead of new Playwright journeys (~231 production journeys already run serially at `workers: 1` against a 45-minute CI budget). **Stop:** do not chase the coverage percentage by backfilling low-risk components; the re-ratcheted broad floor in `vitest.config.mts` holds the line. | session 2026-07-29 test-coverage analysis | 2026-07-29 | -| #108 | P3 | task | Five verified-landed remote branches await deletion (blocked in-session) | **Outcome:** the five branches whose content is fully on `main` are gone. **Detail:** a full-history branch-cleanup review on 2026-07-29 verified these introduce an empty diff against `main` and back no open PR: `claude/clinical-kb-pwa-review-asi3wb` @ `df29f311b60cadf8e43bf51283a9d6f496b295e3`, `claude/dazzling-blackwell-f348d0` @ `c9bec8f9dce38cb647de9aa64ebf08bf7823a524`, `codex/document-reader-condensed-view` @ `b5cdbf301d517239ffe9ed941b9ebe809aea0bfd`, `cursor/page-anchored-search-composer-30ee` @ `7ff134ca7f614db527b8d142676640305533669d`, `cursor/pr-1379-babysit-ledger-9365` @ `be2de03f855cb7fdfccea4bb74d05eb4c9bf6c61`. **The HEADs are recorded because they are unrecoverable once the refs are deleted:** `hasCompletedCleanupReview` (`scripts/sweep-branch-ledger.mjs:83-93`) matches a completed row on branch name AND HEAD together, so without them no later operator could ever append the required `branch-cleanup` rows. Each candidate now also has its own `branch-cleanup-deletion-pending` ledger row keyed to its own HEAD. Deletion could not be performed: the session git proxy rejects ref deletion with **HTTP 403**, and the GitHub MCP toolset exposes no delete-branch capability. The remaining 87 were deliberately NOT cleared — their touched files still differ from `main`, which is the conservative direction. **Next — ORDER MATTERS:** append the completed `branch-cleanup` row for each branch FIRST, from a checkout that still has the objects, and only then delete the refs. `resolveHead` (`scripts/branch-review-ledger.mjs:155-167`) runs `git rev-parse --verify ^{commit}` and refuses to append a HEAD that is not a commit in the repository, so the reverse order is unexecutable once the refs are gone and their objects are pruned. The `n/a - ` escape hatch does not help here: `hasCompletedCleanupReview` only matches a 7-40 char hex HEAD, so an `n/a` row would leave the branch resurfacing in every future sweep. **Progress 2026-07-30 — the prerequisite is DONE; only the deletion is left, and it needs a caller who can delete refs.** Re-verified against the live remote first, which mattered: `claude/clinical-kb-pwa-review-asi3wb` and `claude/dazzling-blackwell-f348d0` are **already gone** (surfaced by `git remote prune`, deleted by someone with the permission this session lacks), so the list is three, not five. The remaining three are still at exactly the recorded HEADs, and the proof was re-run and strengthened: for each, `tree(tip) == tree(merge-base)` byte-for-byte, so the branch nets zero content change from where it forked and nothing on it is absent from `main`. That is stronger than either check the guide names — `--cherry-pick` still reports 13/6/4 patch-unique commits on them, which is the squash-merge false positive, and none is an ancestor of `main`, so `--merged` would also miss them. A completed `branch-cleanup` row keyed to its own HEAD is now appended for each of the three (`npm run check:branch-review-ledger` passes at 1272 records), so the ORDER MATTERS constraint above is satisfied and the refs can now be deleted safely at any time. Deletion re-attempted and still blocked: `git push origin --delete` exits 1 with **HTTP 403** from the session git proxy (`recentRelayFailures` empty, so it is credential scope, not a relay fault), and a tool search confirms the GitHub MCP set exposes `create_branch` but no delete-branch capability. **Next:** delete these three refs from the GitHub UI or any session whose credentials permit ref deletion — `codex/document-reader-condensed-view`, `cursor/page-anchored-search-composer-30ee`, `cursor/pr-1379-babysit-ledger-9365`. Nothing else is required first. **Stop:** do not widen to the other 87 without per-branch content proof. | session 2026-07-29 branch cleanup; ledger `branch-cleanup-deletion-pending` @ 855aa291 | 2026-07-29 | | #109 | P2 | issue | Remote sessions clone shallow, silently invalidating all branch/merge analysis | **Outcome:** no session draws branch conclusions from a truncated history. **Detail:** on 2026-07-29 this repo's remote session had `git rev-parse --is-shallow-repository` = **true** with only **74** commits of `origin/main` (full history is 2829). Every merge-base, `--cherry-pick`, and ahead/behind number computed in that state was wrong: local `main` reported `ahead 52` and `refusing to merge unrelated histories` (it is actually 0 ahead with a shared base), and an all-branch sweep wrongly showed **90 of 91** branches as carrying unmerged work. Acting on that would have meant either deleting live branches or abandoning cleanup entirely. `git fetch --unshallow` corrected both. **FIXED 2026-07-29:** `scripts/sweep-branch-ledger.mjs` now refuses outright on a shallow clone via the exported `shallowCloneRefusal`, printing no inventory and exiting 1 in both text and `--json` mode, before the fetch and before any branch maths. `docs/branch-cleanup-guide.md` §Safety Rules gains the `is-shallow-repository` precondition ahead of its numbered steps, because the raw `git` commands it documents have no such guard. Proven in a real `--depth 1` clone: unguarded the sweep exited **0** and named the live checked-out branch a deletion candidate with "no unique patch content"; guarded it exits 1 with the `--unshallow` remedy. Five cases in `tests/repo-hygiene.test.ts` cover both directions, including that the string `"false"` (truthy) must NOT be read as shallow — the way this guard could fail dangerously in reverse. **Hardened in review:** an indeterminate `is-shallow-repository` result (empty output from a swallowed `git` failure) is now refused as its own failure rather than treated as complete, and the same refusal was extended to `scripts/reconciliation-preflight.mjs`, which reports its own merge-base-derived ahead/behind. That guard then had to move OUT of the preflight CLI and INTO the exported `collectReconciliationState`, because `buildReconciliationEvidencePack` calls the collector directly and stamps `status: "complete"`: in a `--depth 1` clone the guarded CLI exited 1 while the evidence-pack command exited 0 and persisted shallow ahead/behind as completed evidence. The collector now throws `UnverifiedHistoryError` (`code: "history-not-verified"`), so every current and future caller fails closed by default instead of by remembering to ask; the CLI catches it only to keep the `--json` envelope. Regression cases live with each entry point (`tests/reconciliation-preflight.test.ts`, `tests/reconciliation-evidence-pack.test.ts`) and build a real `--depth 1` clone, asserting `is-shallow-repository` is `true` first so a git behaviour change cannot make them pass vacuously. **Second failure mode, found in review after the first fix landed: complete history is not complete branch coverage.** `git clone --depth 1` implies `--single-branch`, pinning `remote.origin.fetch` to the one cloned branch; `git fetch --unshallow` converts the history so `--is-shallow-repository` reads `false` and the shallow guard passes, but it does not widen the refspec, and an ordinary `git fetch origin` respects the narrow one. Measured in a `main`+`feature` fixture: after unshallowing, `git ls-remote --heads origin` listed both while `refs/remotes/origin` held only `origin/main`, and the sweep exited **0** reporting `"branches": []` — and an empty inventory is not a safe failure, since it reads as "nothing to clean up" and a missing `origin/main` makes every `rev-list` fail into `0/0`, i.e. every branch a deletion candidate. Fixed both ways: the sweep's fetch now passes an explicit `+refs/heads/*:refs/remotes/origin/*` (repairing coverage without rewriting the operator's config), and `branchCoverageRefusal` refuses when neither the configured refspec nor a completed wildcard fetch establishes coverage — `--no-fetch`, offline, or a failed fetch. Its remedy is deliberately `git remote set-branches origin '*'`, not `--unshallow`, which fixes history and does nothing here. **Two further routes to the same empty-inventory answer, both found in review, both from checking only half of the refspec.** (1) The DESTINATION matters as much as the source, because the sweep enumerates `refs/remotes/origin` and nothing else: with `+refs/heads/*:refs/remotes/upstream/*`, `refs/remotes/upstream` held `upstream/main` and `upstream/feature` while `refs/remotes/origin` stayed empty and the sweep exited **0** with `"branches": []`. (2) Git substitutes the matched suffix into ``, so a `refs/*` source nests one level deeper: `+refs/*:refs/remotes/origin/*` writes `refs/remotes/origin/heads/main`, `origin/main` then does not resolve at all, every comparison fails into `0/0`, and the sweep exited **0** naming both `heads/feature` and **`heads/main`** as deletion candidates — a green run recommending the deletion of `main`. Coverage from config therefore requires exactly `refs/heads/*` to `refs/remotes/origin/*`; a completed wildcard fetch still establishes coverage by itself, since the sweep passes that destination explicitly. **Stop:** never delete a branch, or report a branch as unmerged, from a shallow clone, a single-branch refspec, or a refspec whose destination is not `refs/remotes/origin/*`. | session 2026-07-29; `docs/branch-cleanup-guide.md`; `scripts/sweep-branch-ledger.mjs` | 2026-07-29 | | #110 | P3 | task | Design-system project token manifest lags its stylesheet | **Outcome:** the claude.ai/design token panel matches the shipped stylesheet. **Detail:** PR #1375 pushed a recompiled `_ds_bundle.css` (Clinical Sky, `--e0`–`--e4`, 4px radius grid, `--tracking-eyebrow`/`--leading-display`/`--leading-prose`) plus the four changed guideline docs to project `08d6f126`, but `_ds_manifest.json` is converter-generated and still advertises `--text-4xs: 0.5rem`, the old `--radius-lg/xl/2xl` values, and `--tw-leading`/`--tw-tracking` entries scoped to the retired `.leading-[…]` / `.tracking-[0.08em]` utilities. Rendering is correct; only the token inventory lags. Hand-editing was rejected — `kind`/`scope`/`annotation` are converter heuristics and a wrong panel is worse than a stale one. **Next:** in a session with the `/design-sync` skill, `npm ci`, then `npm install --prefix .ds-sync --no-save --package-lock=false esbuild ts-morph @types/react @tailwindcss/cli geist`, read `.design-sync/NOTES.md`, and run `resync.mjs --remote` so bundle and manifest regenerate together. **Stop:** do not hand-author `_ds_manifest.json`; the converter is not a published npm package and ships with the skill. | PR #1375; `.design-sync/NOTES.md`; project `08d6f126` (`_ds_needs_recompile` marker present) | 2026-07-29 | | #115 | P3 | rec | Band adoption gate treats a discovered import as rendered | **Closed 2026-07-30.** `tests/search-results-band-adoption.test.ts` no longer asks "does this file mention the band?" but "does anything the route actually mounts reach it?". It parses each module with `@babel/parser` into a small graph — exported name to local declaration, local to the identifiers its body references, and which locals render the band — then walks from the route's default export, carrying at each hop the set of exports the importer mounts. So a static `import { X }` is followed only when `X` is reachable from a mounted declaration; `dynamic(() => import("…").then((m) => m.Named))` follows only that binding, which is how the code-split dashboard workspaces are written; a bare `import "…"` is not followed at all; `export { X } from "…"` is followed only when the importer wants `X`; and `export * from "…"` never supplies a default, so a page whose importer wants only the default gets no hop from it. **Why the redesign rather than more patches:** six false greens were reported in one day (unrendered import, `export { X }`, `export { X } from`, `export *`, bare side-effect import, JSX in an unmounted helper, and a lazy import reaching every sibling export), all one defect — presence is not reach. Two of the six were introduced by an earlier patch to the same walker. **Verified:** all five production search routes still reach the band; gutting `(search-app)/services/page.tsx` and `tools/page.tsx` to `
` each reports an orphan; fourteen temp-dir fixtures cover both directions, and the two guarding the new mechanisms were confirmed to fail against the prior behaviour by targeted mutation (presence-based band check, and following bare imports). Residual: reachability is per module, so a mounted declaration referencing an identifier anywhere in its body counts, and control flow inside it is not modelled. | PR #1400; session 2026-07-30 | 2026-07-30 | @@ -170,70 +169,71 @@ removed after current-main verification; it is not missing recommended work. Move resolved rows here with the resolution date and a one-line outcome. Keep them — do not delete. -| ID | Type | Summary | Outcome | Resolved | -| ---- | ----- | ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | -| #088 | task | Union-driver ledger duplication watch after repair | CLOSED 2026-07-30. Post-repair merges take main's repaired lines; residual exact-dupe babysit twins from stock `merge=union` are addressed by the custom `merge=ledger` driver (union + exact-row dedupe), `npm run ledger:dedupe`, and the Run PR anti-churn ledger policy. Success criterion (three consecutive post-repair guard passes) met on ordinary main syncs; ongoing exact-dupe class is now gated rather than watched. | 2026-07-30 | -| #087 | issue | `npm run check:knip` reported pre-existing dependency findings | NOT A DEFECT — false positive. The findings (unused `rimraf`/`tsx`/`@testing-library/dom`, unlisted `playwright-core`) only appeared because the worktree had no `node_modules` of its own and tooling resolved from the parent checkout. After `npm ci` in the same worktree, `npm run check:knip` exits 0 with no ignore-list change. Durable lesson: never act on a knip finding from a worktree that has not been installed. | 2026-07-28 | -| #089 | issue | Branch-review-ledger hygiene deferred from PR #1275 | Closed by the 2026-07-28 hygiene pass. The MD056 cell-count and duplicate-row findings dispositioned as "belongs in a dedicated main ledger hygiene pass" on PR #1275 are fixed: 140 mojibake lines restored byte-exact from git history, 6 residual separators repaired, 46 exact duplicates removed, 21 wrong-width rows normalised, and 4 heading+bullet records converted to table rows — 1067 records, all six cells. Root cause closed too: `npm run ledger:lookup` / `ledger:append` (`scripts/branch-review-ledger.mjs`) replace hand-written rows, and `check:branch-review-ledger` now fails on mojibake, cell width, heading records, impossible dates, table gaps, and (from 2026-07-29) unresolvable HEADs and near-duplicates. | 2026-07-28 | -| #097 | issue | Gitleaks reports a false red when the PR head moves mid-run | RESOLVED 2026-07-30: Secret Scan checks out the event head SHA and runs `scripts/run-gitleaks-pinned.mjs` against the immutable event base..head range (no mid-run PR commits API re-query). | 2026-07-30 | -| #111 | issue | `ui-overlap` phone-inset case still flakes under load | RESOLVED 2026-07-29 (PR #1391). The inset measurement now retries inside `expect(async () => …).toPass({ timeout: 15_000 })` (`ui-overlap.spec.ts:159`) — the same retry-the-measurement shape PR #1375 applied to the eight overlap cases. The 2px symmetry tolerance and the assertions themselves are byte-for-byte unchanged, so a genuinely asymmetric header still fails once the retry budget is spent; only a transient mid-remount sample settles. Full spec green across 4 consecutive runs (14 passed each). Do not relax the tolerance if this recurs — the assertion is the point; make the measurement robust instead. Source: PR #1375 flake triage; session 2026-07-29 | 2026-07-29 | -| #112 | issue | `issues:next-id` has no concurrency protection | RESOLVED 2026-07-30. `npm run check:outstanding-issues` now gates this file, in `verify:cheap` and in the `static-pr` CI job (the gate-manifest check refuses a local gate that CI does not run). It fails on a duplicate id, an id present in both tables, a marker at or below the highest id, a malformed row, and a missing heading or marker — so every shape the 2026-07-29 triple collision took is now a red gate rather than a silent row loss. Verified by replaying that collision against the real file: two rows claiming `#110` produced "#110 appears 2 times (lines 151, 164)", and a lost marker bump produced "issues:next-id=113 is not above the highest id #114". The checker honours `\|` escapes — its first run against the live file flagged row #042, which is correctly escaped, and a gate with false positives is a gate people switch off. NOT fixed: the underlying race. Ids are still allocated by read-modify-write with no lock, and this file still has no `merge=union` driver; what changed is that a collision can no longer land silently. Source: session 2026-07-29 PR sweep; PR #1391 conflict resolution; `.gitattributes` | 2026-07-30 | -| #113 | issue | `ModeNav` clips its labels at every phone width on `main` | RESOLVED 2026-07-30 (PR #1405, landed on `main` as `020c1260`). The two lower density bands used `grid-auto-columns: 1fr`, so the widest slot set every slot's width and the label's `truncate` hid the shortfall — nothing overflowed and nothing failed, the word was simply gone. `display: flex` at every band removes the mode rather than retuning it; thresholds went `16/26/34rem` -> `22/33/42rem` against remeasured intrinsic widths (471px for four labels, not the 394px originally budgeted). `tests/ui-mode-nav-density.spec.ts` asserts at both band boundaries and one pixel either side, registered in BOTH Playwright allowlists. **Carry-forward:** the ~8% threshold headroom is not padding — a measured-plus-one-pixel attempt (21/31rem) passed locally and failed CI by exactly 1px, because the variable face rasterises wider on `ubuntu-24.04`. A threshold calibrated to one machine's font metrics is calibrated to nothing. | 2026-07-30 | -| #114 | issue | The live Web-Vitals instrument cannot measure its own noise | RESOLVED 2026-07-30 (PR #1407, landed as `a73db460`). Each route/strategy cell is measured `SAMPLES` times (default 3), the MEDIAN is graded, and a cell whose samples straddle a threshold is reported as incomplete evidence rather than resolved either way — so #017's "evidence is too noisy" stop rule can finally fire. Mid-run Chrome drift disqualifies the verdict. **Second defect found in review and fixed in the same PR:** `samples` is a free-text `workflow_dispatch` input, so `samples=1` reached the grader as a valid integer and reproduced the exact single-run matrix this work removes — verified against the pre-fix logic, it reported 0 breaches, 0 incomplete and printed the bold "Every mobile route is within" verdict. Now refused in three places (`main()` before reading any report, `renderTable`'s disqualifier list, and the workflow before spending a live measurement pass). | 2026-07-30 | -| #012 | rec | Slim the lazy cross-mode differentials chunk | Precomputed a trimmed index (`src/data/cross-mode-differentials-index.json` via `scripts/build-cross-mode-differentials-index.mjs`) so the lazily-loaded cross-mode chunk imports a ~53 KB catalog instead of statically pulling the ~1.2 MB differentials snapshot (only that dynamic path reached it). A drift test plus `check:cross-mode-index` (in verify:cheap) lock the index to the live projection. | 2026-07-27 | -| #029 | issue | Residual answer-quality fallback stubs | Closed after fixing each causal cluster independently. Active-community ED, community-home-visit, clozapine blood-threshold/typo, discharge source-gap recovery, and Best Practice Prescription now use narrowly validated, source-bound answers or auditable recovery; cited provider refusal prose can no longer masquerade as grounded, and terminal gaps retain no claim citations. The final 44-case gate reported 30/30 substantive grounded supported answers, 14/14 unsupported correct, zero review fallbacks, zero citation/numeric failures, and zero route-ceiling failures. Measurement still reports review fallback separately and denies targeting credit for echoed boilerplate. | 2026-07-27 | -| #019 | issue | Preserve admission/discharge sources through comparison fallback | The actual fallback path now selects source-bound facts, preserves one admission and one discharge citation from distinct documents, and terminates at an evidence gap for qualified, negated, unrelated, title-only, single-sided, or same-document traps. Both exact live cases complete in about one second with zero provider calls; the final 44-case canary passed them with two citations each, while the 36-case retrieval canary held recall 1.0 and zero RR regressions. Retrieval scores, aliases, clamps, and comparator ordering were unchanged. | 2026-07-27 | -| #084 | task | Persist per-result irrelevant-at-10 grading evidence | `eval-retrieval` now persists each top result's `relevanceGrade` and `matchedDeclaredSignals`; focused fixtures cover ideal and zero-grade rows. The final golden artifact contains 338 graded top rows, including 33 grade-zero rows. This closes the reproducibility gap only: fixture labels, ranking, thresholds, and provider behavior were not changed, and human disposition remains #023. | 2026-07-27 | -| #080 | rec | Re-test the removed admission-to-discharge alias widening | Restored the two approved NMHS Admission-to-Discharge titles only on the eval-expectation surface. Canonical document-identity dedupe plus maximum bipartite matching prevents one dual-listed physical document from satisfying both comparison slots. Focused matching tests, both targeted admission cases, the final 36-case golden retrieval run, and the 44-case answer run passed; runtime retrieval/ranking behavior was not changed. | 2026-07-27 | -| #083 | issue | Documents-only universal search timed out on staging tenancy | A current staging nightly reproducer showed the documents-only search losing its synthetic fixture after the federated typeahead timeout was reduced to 750 ms. Current main retains 750 ms for multi-domain requests and uses the established 6,000 ms budget only when documents are the sole requested domain; fake-timer coverage proves both paths. RAG impact: no retrieval, ranking, ordering, alias, score, or result-selection change—only availability of the explicitly focused request. | 2026-07-27 | -| #082 | issue | Bot branch-sync heads leave required checks unapproved | Retired the automatic `GITHUB_TOKEN` PR branch-update workflow instead of weakening required-check approvals or introducing a privileged automation token. The existing helper remains dry-run by default, verifies its apply identity, and refuses missing or bot identities. The fast GitHub Actions policy check rejects both direct workflow `update-branch` calls and indirect apply-helper invocation. | 2026-07-27 | -| #058 | task | Verify production content before any seed write | Read-only production counts on project `sjrfecxgysukkwxsowpy` found 276 clinical registry, 328 medication, and 232 differential records. The required tables are non-empty, so no seed or production write was needed. | 2026-07-27 | -| #069 | task | Validate hosted table-facts RPC latency | Read-only profiling on the correct hosted project separated sample 1 (`first_unprimed`) from five `warm_repeat` samples; managed Supabase buffers were not flushed, so no true-cold claim is made. First-unprimed client/DB execution was 662.916/141.537 ms (clozapine), 277.661/96.229 ms (lithium), and 322.598/148.378 ms (metabolic). Warm client median/p90 was 187.029/198.907, 167.803/174.391, and 189.065/243.324 ms; warm DB execution median/p90 was 88.292/89.355, 64.342/65.566, and 107.448/148.417 ms. Earlier exact clinical probes were lower again. Plans are not the multi-second tail; no hosted migration, ranking, or provider configuration changed. | 2026-07-27 | -| #051 | task | Stabilise the live answer-quality canary before more RAG tuning | Closed after the scheduled structured report supplied a comparable second 36-retrieval/44-answer datapoint. Content gates stayed stable, the prior citation failure cleared, and #019 repeated with an identical diagnostic signature. Retrieval latency was investigated separately: #069 subsequently found acceptable table-facts database plans, so the broad scheduled tail was not treated as ranking debt. The report/trend tooling is now sufficient to compare future approved runs; no scheduled rerun or tuning was dispatched. | 2026-07-27 | -| #054 | task | Reconcile local and hosted secrets/config | Completed production names-only reconciliation on 2026-07-27. The correctly identified primary checkout received distinct gitignored local safety/query-hash/deep-probe values. A hardened checker now pins GitHub to `BigSimmo/Database` and Railway to the live production project/environment plus `Database`/`worker`, catches multiline schema and `.env.example` drift, and verifies GitHub secrets/variables and per-service Railway contracts without emitting provider values. All required names passed; the Ops Digest workflow is active with a successful scheduled run; both Railway services have later successful deployments; Supabase names-only proof found the expected cron/Vault configuration. Value equality remains deliberately unobservable, staging stays #056, webhook activation stays #025, and legal/ZDR work stays #053. | 2026-07-27 | -| #064 | task | Reconcile the preserved browser and contrast patch | Landed via PR #1250 squash `b91b4600171be08198e92bcf19b7d67e8207cb2f`. Opacity-free disabled Previous/Continue styling plus native-disabled/focus/axe Playwright coverage is on `main`. Historical `agent/formulation-disabled-contrast` remained unrecovered; conflicted PRs #1219/#1223/#1226/#1231/#1249 were closed without merge. | 2026-07-26 | -| #081 | issue | Open PR #1196 would undo the #030 alias tightening | Closed as no longer live: PR #1196 was closed 2026-07-25 as superseded by #913/current `main` (~680 commits behind, conflicting), and its successor #1198 does not touch `src/lib/eval-document-matching.ts`. The generalized alias-disjointness and single-document contracts landed in PR #1215 fail closed if any later branch re-adds the dual-listed admission aliases, so the regression route is guarded rather than watched. | 2026-07-25 | -| #077 | issue | Concurrent tasks can re-dirty the canonical primary checkout | Added cooperative primary-checkout write lease with dirty/operation fail-closed checks, stale-owner recovery, and lifecycle start/cleanup wiring; focused concurrency tests refuse a second primary writer while read-only/feature worktrees stay unblocked. | 2026-07-25 | -| #078 | task | Generate a deterministic reconciliation evidence pack | Added report-only atomic evidence pack with dispositions, markers, archive refs, bundle verify/hash, worktree counts, and local/base equality; fixture tests prove determinism/redaction and no false completion record on interrupt. | 2026-07-25 | -| #066 | task | Land and prove the streamlined six-item sidebar | Proven on `origin/main` via PR #1174 (`4dc76306 Land streamlined six-item sidebar`). Six-item rail shipped; open ledger row was stale post-merge. | 2026-07-25 | -| #067 | issue | Reconciliation preflight test times out under full-suite load | Fixed in PR #1191 (`e2488dbb`) by calling `collectReconciliationState()` in-process; PR #1203 further injects a fixture `repositoryRoot` so the contract no longer scales with the live worktree farm. No global timeout raise or heavy-test lock bypass. | 2026-07-25 | -| #007 | rec | `/tools` vs `/?mode=tools` parallel Tools entry points | Resolved as `/tools` canonical (PT-11 already documented on `/applications` redirect). Sidebar, appModeHomeHref, universal-search, prefetch, sitemap, and reachability now use `/tools`; `/?mode=tools` remains a dashboard-mode alias. Reachability allowlist entry removed. | 2026-07-24 | -| #030 | issue | Wide-tier alias lets one doc satisfy both comparison slots | Fixed on `cursor/search-correctness-030-075-6273`: removed dual-listed Admission-to-Discharge titles from AdmissionCommunityPts so one retrieved source cannot make allHit true for both comparison slots; fail-closed contracts in `tests/eval-document-matching.test.ts`. RAG impact: no retrieval behaviour change — eval matching only. Hardened after merge: coverage dedupes by document identity and assigns by maximum matching (#080). | 2026-07-24 | -| #075 | issue | Search-scope label enumeration can truncate after 1,000 rows | Fixed on `cursor/search-correctness-030-075-6273`: `loadScopeLabels` pages document_labels with deterministic order/batching past the Supabase 1k cap; multi-page >1000 contracts in `tests/search-scope.test.ts`. Isolated from mixed PR #1132. RAG impact: no retrieval behaviour change — label pagination only. | 2026-07-24 | -| #009 | rec | Confirm `/api/jobs` is intentionally server/ops-only | Kept as deliberate administrator/ops listing: no client `fetch("/api/jobs")` (UI uses `/api/ingestion/jobs`); documented in `docs/api-jobs-ops-surface.md` plus wiring/codebase-index/site-map notes. Not abandoned — do not remove without updating API contract tests. | 2026-07-24 | -| #010 | task | Un-built "Coming soon" controls across forms/favourites | Audited forms/favourites/presentation placeholders: all use honest `disabled` or `aria-disabled` + coming-soon copy (or presentational `ToggleSwitch` without `onToggle`). No fake-interactive controls; leave unwired until features land. Recorded in `docs/wiring-conventions.md`. | 2026-07-24 | -| #032 | rec | Governance ranking weighting: REFUTED, not debt | Reinforced as guardrail only in `docs/rag-behaviour/refuted-approaches.md` (Refutation 3), README, and safeguards — do **not** implement `review_due`/unknownCurrentness ranking penalties or boosts. No retrieval/ranking code changed. RC8 filter path remains the only revisit route behind canary gates. | 2026-07-24 | -| #041 | rec | Extend the existing Factsheets reading model | Brief recorded in `docs/factsheets-reading-model-brief.md`: extend Easy Read/Standard on existing Factsheets routes; reject a second patient-facing Factsheets mode unless concrete need + source-governance plan exist. | 2026-07-24 | -| #063 | rec | Define “Current Clinical Work” before implementation | Product/privacy/persistence brief recorded in `docs/current-clinical-work-brief.md`. Default v0 = no new storage (tab/URL resume); Class C free text needs privacy clearance. Stop without demand evidence. No UI/schema implemented. | 2026-07-24 | -| #076 | task | Reproduce malformed fallback PDF image/table crops | Reproduced truncated page-edge `table_crop`s on current-main with `worker/python/fixtures/malformed-table-crop-page-edge.pdf`. Root cause: `pymupdf_find_tables` stops at the last fully detected row; fix extends the candidate from contiguous cell drawings, recovers the on-page score-5 remnant, and emits `table_crop_edge_incomplete` / `crop_completeness=0.9` when content continues past the page. PR #1176. Broad PR #1129 retention/padding changes not merged. | 2026-07-24 | -| #070 | issue | Presentation mobile tabs misroute Overview/Map/Related | Fixed in PR #1135: Overview/Map/Related deep-link to diagnosis `?tab=` sections; Compare stays on the presentation page. Regression in `tests/mobile-interaction-regressions.test.ts`. (Provisional PR-branch IDs `#068`–`#072` were renumbered after `main` claimed `#068`/`#069`.) | 2026-07-24 | -| #071 | issue | Evidence/Clinical Notes Add fakes success without persistence | Fixed in PR #1135: sticky Add controls use the focusable coming-soon placeholder pattern instead of optimistic `setAdded(true)`. | 2026-07-24 | -| #072 | issue | Tools hub exposes false Sort/More affordances | Fixed in PR #1135: Sort is a status label, More filter targets coordination/saved without a fake menu chevron, and the favourites shortcut is labelled Saved/Favourites. | 2026-07-24 | -| #073 | issue | Presentation compare dock CTA is a self-link no-op | Fixed in PR #1135: dock shows non-link "Comparing (N)" status while already comparing. | 2026-07-24 | -| #074 | issue | Mode-action popup hard-reloads internal clinical routes | Fixed in PR #1135: `master-search-header` uses `router.push` for DSM/Specifiers/Formulation actions and mode href fallback. | 2026-07-24 | -| #068 | task | Regenerate full drift-manifest snapshot after schema hygiene | Full Docker `npm run drift:manifest` replay succeeded on a Docker-capable host; `supabase/drift-manifest.json` now carries live `def_hash` values for the plpgsql table-facts body (offline generator_note removed). | 2026-07-24 | -| #052 | issue | Reindex can overlap a fresh agent-enrichment pass | PR #1143 retained the friendly full/retry preflight and closed its check-then-enqueue race with an owner-scoped transactional RPC. Reindex enqueue and the agent claim path serialize on the document row; disposable PostgreSQL proved both interleavings, and exact-head migration replay/unit/build/Chromium/policy/security checks passed. | 2026-07-24 | -| #062 | issue | Upload crash can strand a queued document without a job | Aged owner-scoped `queued`-without-open-job rows are detected by `reindex:health`; the six-hour autopilot raises a durable alert, and guarded recovery uses PR #1143's transactional RPC so enqueue is owner-scoped, idempotent and atomic. `recover:ingestion --include-stranded-queued` remains dry-run/confirmation-first; scheduled production mutation is not enabled. | 2026-07-24 | -| #060 | issue | Safety Plan Generator contradicted the privacy contract | PR #1119 removed patient identifier entry, leaves the post-export name line blank, and aligned tool, privacy and PIA copy. DOM/privacy tests and Chromium copy/print/network coverage prove working content remains in React memory with no fetch/XHR; hosted Production UI, build, unit, policy, safety, static-analysis and secret checks passed. Support-contact details remain classified as sensitive local-only working content. | 2026-07-24 | -| #061 | issue | Missing answer relevance metadata was treated as source-backed | PR #1125 now requires explicit source-backed relevance for trusted/grounded presentation and prevents visual tables, clinical-note sections and quotes, and comparison metadata from bypassing the render model. Three actionable P2 review paths were fixed; focused policy/DOM tests, offline RAG, production-readiness, build, unit, static, security, and Production UI gates passed. No retrieval, ranking, generation, provider, or data behavior changed. | 2026-07-24 | -| #034 | issue | Answer cache can serve stale governance metadata | Current-source verification found direct route coverage already asserts RAG-cache invalidation on document PATCH, source review, label, bulk, and reindex mutation paths. The residual test recommendation is already met; changing the protected cache key is unnecessary. | 2026-07-24 | -| #014 | rec | Realize the `next/image` win on signed previews | Superseded: `SignedImage` uses `next/image` for layout and sizing but deliberately sets `unoptimized`, preventing bearer signed URLs from entering the unauthenticated optimizer cache where cached content could outlive the token. No optimization task remains unless private-image delivery changes. | 2026-07-24 | -| #026 | task | Wire the Supabase document-change trigger | PR #1100 merged after disposable PostgreSQL replay and hosted migration replay. Production migration history and read-only catalog proof confirm the enabled metadata trigger, security-definer function, pinned search path and denied anonymous/authenticated execution; `npm run check:drift` reports no unexpected live drift. Delivery remains intentionally inert until the operator inputs tracked in #025 are configured. | 2026-07-24 | -| #031 | issue | Populate canary Source Governance table | The answer-quality step now consumes the preceding `golden-retrieval.json` only for source-governance reporting. Offline replay of run `30018289898` populated 338 top results, including 202 review-required entries, while retaining zero retrieval cases and no additional threshold failures. Retrieval and ranking behavior are unchanged. | 2026-07-24 | -| #020 | task | Validate eval:quality cost readout post-fix | Confirmed on merged-main canary run `30018289898`: Answer Metrics reported 9 nonzero-cost cases and an estimated answer cost of `$0.234736`; the structured report retained the same value. The PR #1050 estimator fix is operationally proven. | 2026-07-23 | -| #003 | task | Staging tenancy release evidence outstanding | Ran GitHub Action and validated isolation | 2026-07-21 | -| #002 | task | Process-ownership fix not yet isolated on `main` | Fixed process isolation using child.pid termination | 2026-07-21 | -| #008 | rec | Dead href builders in `document-flow-routes.ts` | Not dead code (false positive): `documentReaderHref`/`documentEvidenceHref` are live via the mock wrappers in `src/components/document-search-mockups.tsx` + `src/components/master-document-flow-mockups.tsx` (rendered under `src/app/mockups/document-search/`) and covered by `tests/document-flow-routes.test.ts`; removing breaks the build. Only the production non-mock hrefs are unlinked from prod UI — a wiring gap, not dead code. | 2026-07-22 | -| #015 | task | Content-first fallback regression tests | Added `tests/registry-record-loader.dom.test.tsx` (8) + `tests/medication-record-page.dom.test.tsx` (6) covering content-first fallback paint, live swap-in, spinner/skeleton, error + not-found/unauthorized states, and the invariant that no authoritative verification badge shows before live governance reconciles (registry fixture-flag neutralization + medication governance-drop-on-error). | 2026-07-22 | -| #004 | rec | Rescope provider-gated RAG safety ideas | Closed obsolete — rescue source (754-line RAG-safety worktree) unrecoverable/pruned across all refs; answer-quality thresholds + deep-health already shipped on `main` (#585/#587); only cost-cap preflight was genuinely missing and, per session decision, dropped rather than re-filed. | 2026-07-22 | -| #006 | issue | Globe "Language & region" button had no handler | Resolved on main with the repository's disabled "Coming soon" placeholder convention and button-wiring coverage. Future language/region work remains a feature request, not an inert-control defect. | 2026-07-22 | -| #042 | issue | Invalid optional credentials fell into anonymous access | PRs #1078/#1079 introduced `absent \| valid \| invalid`, return 401 for presented invalid credentials, preserve authoritative header precedence and prefer the current-project session cookie. The archived anonymous-upload metadata patch was rejected as stale because uploads are already administrator-only before duplicate lookup. | 2026-07-22 | -| #043 | issue | Readiness could report healthy or throw on Supabase errors | PR #1080 now fails readiness closed for returned and thrown dependency failures, preserves recognized actionable messages, and prevents raw dependency-error disclosure. | 2026-07-22 | -| #044 | issue | Publication approval was not bound to immutable reviewed state | PR #1081 added a canonical reviewed-state digest, row locks, active-job rejection and a new forward migration with replay/schema/type/drift evidence. | 2026-07-22 | -| #045 | issue | Bulk reindex discarded partial-success results | PR #1084 reserves preflight conflicts for non-2xx responses; completed mixed batches return per-item success/failure/missing results, and the UI refreshes successful work. | 2026-07-22 | -| #046 | issue | DOCX extraction lacked explicit resource budgets | PR #1085 added pre-inflate declared-size checks and post-read fail-safes for artifact count, per-artifact bytes, aggregate media, Word XML and extracted UTF-8 text. | 2026-07-22 | -| #047 | issue | XLSX extraction could construct unbounded results | PR #1086 bounds worksheets, non-empty rows, rendered cells and UTF-8 output while preserving sparse-column rendering. | 2026-07-22 | -| #048 | issue | Account copy overstated sync/privacy and enabled unavailable SSO | PR #1087 now maps copy to actual favourites/preferences persistence, identifies browser-session recents, removes the contradictory "never shared" claim and clearly disables unavailable providers using the accessible placeholder contract. | 2026-07-22 | -| #049 | issue | Process diagnostic exposed a Cursor worker API key | The exact worker was stopped, the key was revoked server-side, both local encrypted worker-secret records were removed, and authorized repository/backup scans found no plaintext copy. Follow-up guardrails now prevent repository process inventory from serializing command lines and redact heavyweight-lock command text before persistence or errors. | 2026-07-23 | -| #050 | issue | Next.js 16.2.10 remained in a high-severity security range | Upgraded `next` and `@next/env` to 16.2.11, regenerated the npm lockfile, confirmed the production dependency audit is clean, and passed focused framework checks, `verify:cheap`, and the full Chromium UI gate. | 2026-07-23 | -| #116 | issue | Missing CI signal on conflicted PRs | RESOLVED 2026-07-30: `.github/workflows/pr-mergeability.yml` checks trusted `pull_request_target` events and refreshes unchanged heads after protected-base pushes. A conflicted PR gets a red `PR mergeability` check naming the conflict instead of an empty CI list. The base-push job alone has scoped `checks: write`; neither path checks out PR code or updates branches. Classifier: `scripts/pr-mergeability.mjs`; contract: `npm run check:pr-mergeability`. Behind-but-clean remains `sync:pr-branches`. | 2026-07-30 | +| ID | Type | Summary | Outcome | Resolved | +| ---- | ----- | ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | +| #108 | task | Five verified-landed remote branches await deletion (blocked in-session) | DONE 2026-07-30. Deleted the three remaining empty remote refs after re-verify (tree(tip)==tree(merge-base), 0 files vs main, no open PR): `codex/document-reader-condensed-view` @ `b5cdbf301d517239ffe9ed941b9ebe809aea0bfd`, `cursor/page-anchored-search-composer-30ee` @ `7ff134ca7f614db527b8d142676640305533669d`, `cursor/pr-1379-babysit-ledger-9365` @ `be2de03f855cb7fdfccea4bb74d05eb4c9bf6c61`. The other two candidates were already gone. Completed `branch-cleanup` ledger rows were already present; deletion succeeded from this session (prior 403 cleared). | 2026-07-30 | +| #088 | task | Union-driver ledger duplication watch after repair | CLOSED 2026-07-30. Post-repair merges take main's repaired lines; residual exact-dupe babysit twins from stock `merge=union` are addressed by the custom `merge=ledger` driver (union + exact-row dedupe), `npm run ledger:dedupe`, and the Run PR anti-churn ledger policy. Success criterion (three consecutive post-repair guard passes) met on ordinary main syncs; ongoing exact-dupe class is now gated rather than watched. | 2026-07-30 | +| #087 | issue | `npm run check:knip` reported pre-existing dependency findings | NOT A DEFECT — false positive. The findings (unused `rimraf`/`tsx`/`@testing-library/dom`, unlisted `playwright-core`) only appeared because the worktree had no `node_modules` of its own and tooling resolved from the parent checkout. After `npm ci` in the same worktree, `npm run check:knip` exits 0 with no ignore-list change. Durable lesson: never act on a knip finding from a worktree that has not been installed. | 2026-07-28 | +| #089 | issue | Branch-review-ledger hygiene deferred from PR #1275 | Closed by the 2026-07-28 hygiene pass. The MD056 cell-count and duplicate-row findings dispositioned as "belongs in a dedicated main ledger hygiene pass" on PR #1275 are fixed: 140 mojibake lines restored byte-exact from git history, 6 residual separators repaired, 46 exact duplicates removed, 21 wrong-width rows normalised, and 4 heading+bullet records converted to table rows — 1067 records, all six cells. Root cause closed too: `npm run ledger:lookup` / `ledger:append` (`scripts/branch-review-ledger.mjs`) replace hand-written rows, and `check:branch-review-ledger` now fails on mojibake, cell width, heading records, impossible dates, table gaps, and (from 2026-07-29) unresolvable HEADs and near-duplicates. | 2026-07-28 | +| #097 | issue | Gitleaks reports a false red when the PR head moves mid-run | RESOLVED 2026-07-30: Secret Scan checks out the event head SHA and runs `scripts/run-gitleaks-pinned.mjs` against the immutable event base..head range (no mid-run PR commits API re-query). | 2026-07-30 | +| #111 | issue | `ui-overlap` phone-inset case still flakes under load | RESOLVED 2026-07-29 (PR #1391). The inset measurement now retries inside `expect(async () => …).toPass({ timeout: 15_000 })` (`ui-overlap.spec.ts:159`) — the same retry-the-measurement shape PR #1375 applied to the eight overlap cases. The 2px symmetry tolerance and the assertions themselves are byte-for-byte unchanged, so a genuinely asymmetric header still fails once the retry budget is spent; only a transient mid-remount sample settles. Full spec green across 4 consecutive runs (14 passed each). Do not relax the tolerance if this recurs — the assertion is the point; make the measurement robust instead. Source: PR #1375 flake triage; session 2026-07-29 | 2026-07-29 | +| #112 | issue | `issues:next-id` has no concurrency protection | RESOLVED 2026-07-30. `npm run check:outstanding-issues` now gates this file, in `verify:cheap` and in the `static-pr` CI job (the gate-manifest check refuses a local gate that CI does not run). It fails on a duplicate id, an id present in both tables, a marker at or below the highest id, a malformed row, and a missing heading or marker — so every shape the 2026-07-29 triple collision took is now a red gate rather than a silent row loss. Verified by replaying that collision against the real file: two rows claiming `#110` produced "#110 appears 2 times (lines 151, 164)", and a lost marker bump produced "issues:next-id=113 is not above the highest id #114". The checker honours `\|` escapes — its first run against the live file flagged row #042, which is correctly escaped, and a gate with false positives is a gate people switch off. NOT fixed: the underlying race. Ids are still allocated by read-modify-write with no lock, and this file still has no `merge=union` driver; what changed is that a collision can no longer land silently. Source: session 2026-07-29 PR sweep; PR #1391 conflict resolution; `.gitattributes` | 2026-07-30 | +| #113 | issue | `ModeNav` clips its labels at every phone width on `main` | RESOLVED 2026-07-30 (PR #1405, landed on `main` as `020c1260`). The two lower density bands used `grid-auto-columns: 1fr`, so the widest slot set every slot's width and the label's `truncate` hid the shortfall — nothing overflowed and nothing failed, the word was simply gone. `display: flex` at every band removes the mode rather than retuning it; thresholds went `16/26/34rem` -> `22/33/42rem` against remeasured intrinsic widths (471px for four labels, not the 394px originally budgeted). `tests/ui-mode-nav-density.spec.ts` asserts at both band boundaries and one pixel either side, registered in BOTH Playwright allowlists. **Carry-forward:** the ~8% threshold headroom is not padding — a measured-plus-one-pixel attempt (21/31rem) passed locally and failed CI by exactly 1px, because the variable face rasterises wider on `ubuntu-24.04`. A threshold calibrated to one machine's font metrics is calibrated to nothing. | 2026-07-30 | +| #114 | issue | The live Web-Vitals instrument cannot measure its own noise | RESOLVED 2026-07-30 (PR #1407, landed as `a73db460`). Each route/strategy cell is measured `SAMPLES` times (default 3), the MEDIAN is graded, and a cell whose samples straddle a threshold is reported as incomplete evidence rather than resolved either way — so #017's "evidence is too noisy" stop rule can finally fire. Mid-run Chrome drift disqualifies the verdict. **Second defect found in review and fixed in the same PR:** `samples` is a free-text `workflow_dispatch` input, so `samples=1` reached the grader as a valid integer and reproduced the exact single-run matrix this work removes — verified against the pre-fix logic, it reported 0 breaches, 0 incomplete and printed the bold "Every mobile route is within" verdict. Now refused in three places (`main()` before reading any report, `renderTable`'s disqualifier list, and the workflow before spending a live measurement pass). | 2026-07-30 | +| #012 | rec | Slim the lazy cross-mode differentials chunk | Precomputed a trimmed index (`src/data/cross-mode-differentials-index.json` via `scripts/build-cross-mode-differentials-index.mjs`) so the lazily-loaded cross-mode chunk imports a ~53 KB catalog instead of statically pulling the ~1.2 MB differentials snapshot (only that dynamic path reached it). A drift test plus `check:cross-mode-index` (in verify:cheap) lock the index to the live projection. | 2026-07-27 | +| #029 | issue | Residual answer-quality fallback stubs | Closed after fixing each causal cluster independently. Active-community ED, community-home-visit, clozapine blood-threshold/typo, discharge source-gap recovery, and Best Practice Prescription now use narrowly validated, source-bound answers or auditable recovery; cited provider refusal prose can no longer masquerade as grounded, and terminal gaps retain no claim citations. The final 44-case gate reported 30/30 substantive grounded supported answers, 14/14 unsupported correct, zero review fallbacks, zero citation/numeric failures, and zero route-ceiling failures. Measurement still reports review fallback separately and denies targeting credit for echoed boilerplate. | 2026-07-27 | +| #019 | issue | Preserve admission/discharge sources through comparison fallback | The actual fallback path now selects source-bound facts, preserves one admission and one discharge citation from distinct documents, and terminates at an evidence gap for qualified, negated, unrelated, title-only, single-sided, or same-document traps. Both exact live cases complete in about one second with zero provider calls; the final 44-case canary passed them with two citations each, while the 36-case retrieval canary held recall 1.0 and zero RR regressions. Retrieval scores, aliases, clamps, and comparator ordering were unchanged. | 2026-07-27 | +| #084 | task | Persist per-result irrelevant-at-10 grading evidence | `eval-retrieval` now persists each top result's `relevanceGrade` and `matchedDeclaredSignals`; focused fixtures cover ideal and zero-grade rows. The final golden artifact contains 338 graded top rows, including 33 grade-zero rows. This closes the reproducibility gap only: fixture labels, ranking, thresholds, and provider behavior were not changed, and human disposition remains #023. | 2026-07-27 | +| #080 | rec | Re-test the removed admission-to-discharge alias widening | Restored the two approved NMHS Admission-to-Discharge titles only on the eval-expectation surface. Canonical document-identity dedupe plus maximum bipartite matching prevents one dual-listed physical document from satisfying both comparison slots. Focused matching tests, both targeted admission cases, the final 36-case golden retrieval run, and the 44-case answer run passed; runtime retrieval/ranking behavior was not changed. | 2026-07-27 | +| #083 | issue | Documents-only universal search timed out on staging tenancy | A current staging nightly reproducer showed the documents-only search losing its synthetic fixture after the federated typeahead timeout was reduced to 750 ms. Current main retains 750 ms for multi-domain requests and uses the established 6,000 ms budget only when documents are the sole requested domain; fake-timer coverage proves both paths. RAG impact: no retrieval, ranking, ordering, alias, score, or result-selection change—only availability of the explicitly focused request. | 2026-07-27 | +| #082 | issue | Bot branch-sync heads leave required checks unapproved | Retired the automatic `GITHUB_TOKEN` PR branch-update workflow instead of weakening required-check approvals or introducing a privileged automation token. The existing helper remains dry-run by default, verifies its apply identity, and refuses missing or bot identities. The fast GitHub Actions policy check rejects both direct workflow `update-branch` calls and indirect apply-helper invocation. | 2026-07-27 | +| #058 | task | Verify production content before any seed write | Read-only production counts on project `sjrfecxgysukkwxsowpy` found 276 clinical registry, 328 medication, and 232 differential records. The required tables are non-empty, so no seed or production write was needed. | 2026-07-27 | +| #069 | task | Validate hosted table-facts RPC latency | Read-only profiling on the correct hosted project separated sample 1 (`first_unprimed`) from five `warm_repeat` samples; managed Supabase buffers were not flushed, so no true-cold claim is made. First-unprimed client/DB execution was 662.916/141.537 ms (clozapine), 277.661/96.229 ms (lithium), and 322.598/148.378 ms (metabolic). Warm client median/p90 was 187.029/198.907, 167.803/174.391, and 189.065/243.324 ms; warm DB execution median/p90 was 88.292/89.355, 64.342/65.566, and 107.448/148.417 ms. Earlier exact clinical probes were lower again. Plans are not the multi-second tail; no hosted migration, ranking, or provider configuration changed. | 2026-07-27 | +| #051 | task | Stabilise the live answer-quality canary before more RAG tuning | Closed after the scheduled structured report supplied a comparable second 36-retrieval/44-answer datapoint. Content gates stayed stable, the prior citation failure cleared, and #019 repeated with an identical diagnostic signature. Retrieval latency was investigated separately: #069 subsequently found acceptable table-facts database plans, so the broad scheduled tail was not treated as ranking debt. The report/trend tooling is now sufficient to compare future approved runs; no scheduled rerun or tuning was dispatched. | 2026-07-27 | +| #054 | task | Reconcile local and hosted secrets/config | Completed production names-only reconciliation on 2026-07-27. The correctly identified primary checkout received distinct gitignored local safety/query-hash/deep-probe values. A hardened checker now pins GitHub to `BigSimmo/Database` and Railway to the live production project/environment plus `Database`/`worker`, catches multiline schema and `.env.example` drift, and verifies GitHub secrets/variables and per-service Railway contracts without emitting provider values. All required names passed; the Ops Digest workflow is active with a successful scheduled run; both Railway services have later successful deployments; Supabase names-only proof found the expected cron/Vault configuration. Value equality remains deliberately unobservable, staging stays #056, webhook activation stays #025, and legal/ZDR work stays #053. | 2026-07-27 | +| #064 | task | Reconcile the preserved browser and contrast patch | Landed via PR #1250 squash `b91b4600171be08198e92bcf19b7d67e8207cb2f`. Opacity-free disabled Previous/Continue styling plus native-disabled/focus/axe Playwright coverage is on `main`. Historical `agent/formulation-disabled-contrast` remained unrecovered; conflicted PRs #1219/#1223/#1226/#1231/#1249 were closed without merge. | 2026-07-26 | +| #081 | issue | Open PR #1196 would undo the #030 alias tightening | Closed as no longer live: PR #1196 was closed 2026-07-25 as superseded by #913/current `main` (~680 commits behind, conflicting), and its successor #1198 does not touch `src/lib/eval-document-matching.ts`. The generalized alias-disjointness and single-document contracts landed in PR #1215 fail closed if any later branch re-adds the dual-listed admission aliases, so the regression route is guarded rather than watched. | 2026-07-25 | +| #077 | issue | Concurrent tasks can re-dirty the canonical primary checkout | Added cooperative primary-checkout write lease with dirty/operation fail-closed checks, stale-owner recovery, and lifecycle start/cleanup wiring; focused concurrency tests refuse a second primary writer while read-only/feature worktrees stay unblocked. | 2026-07-25 | +| #078 | task | Generate a deterministic reconciliation evidence pack | Added report-only atomic evidence pack with dispositions, markers, archive refs, bundle verify/hash, worktree counts, and local/base equality; fixture tests prove determinism/redaction and no false completion record on interrupt. | 2026-07-25 | +| #066 | task | Land and prove the streamlined six-item sidebar | Proven on `origin/main` via PR #1174 (`4dc76306 Land streamlined six-item sidebar`). Six-item rail shipped; open ledger row was stale post-merge. | 2026-07-25 | +| #067 | issue | Reconciliation preflight test times out under full-suite load | Fixed in PR #1191 (`e2488dbb`) by calling `collectReconciliationState()` in-process; PR #1203 further injects a fixture `repositoryRoot` so the contract no longer scales with the live worktree farm. No global timeout raise or heavy-test lock bypass. | 2026-07-25 | +| #007 | rec | `/tools` vs `/?mode=tools` parallel Tools entry points | Resolved as `/tools` canonical (PT-11 already documented on `/applications` redirect). Sidebar, appModeHomeHref, universal-search, prefetch, sitemap, and reachability now use `/tools`; `/?mode=tools` remains a dashboard-mode alias. Reachability allowlist entry removed. | 2026-07-24 | +| #030 | issue | Wide-tier alias lets one doc satisfy both comparison slots | Fixed on `cursor/search-correctness-030-075-6273`: removed dual-listed Admission-to-Discharge titles from AdmissionCommunityPts so one retrieved source cannot make allHit true for both comparison slots; fail-closed contracts in `tests/eval-document-matching.test.ts`. RAG impact: no retrieval behaviour change — eval matching only. Hardened after merge: coverage dedupes by document identity and assigns by maximum matching (#080). | 2026-07-24 | +| #075 | issue | Search-scope label enumeration can truncate after 1,000 rows | Fixed on `cursor/search-correctness-030-075-6273`: `loadScopeLabels` pages document_labels with deterministic order/batching past the Supabase 1k cap; multi-page >1000 contracts in `tests/search-scope.test.ts`. Isolated from mixed PR #1132. RAG impact: no retrieval behaviour change — label pagination only. | 2026-07-24 | +| #009 | rec | Confirm `/api/jobs` is intentionally server/ops-only | Kept as deliberate administrator/ops listing: no client `fetch("/api/jobs")` (UI uses `/api/ingestion/jobs`); documented in `docs/api-jobs-ops-surface.md` plus wiring/codebase-index/site-map notes. Not abandoned — do not remove without updating API contract tests. | 2026-07-24 | +| #010 | task | Un-built "Coming soon" controls across forms/favourites | Audited forms/favourites/presentation placeholders: all use honest `disabled` or `aria-disabled` + coming-soon copy (or presentational `ToggleSwitch` without `onToggle`). No fake-interactive controls; leave unwired until features land. Recorded in `docs/wiring-conventions.md`. | 2026-07-24 | +| #032 | rec | Governance ranking weighting: REFUTED, not debt | Reinforced as guardrail only in `docs/rag-behaviour/refuted-approaches.md` (Refutation 3), README, and safeguards — do **not** implement `review_due`/unknownCurrentness ranking penalties or boosts. No retrieval/ranking code changed. RC8 filter path remains the only revisit route behind canary gates. | 2026-07-24 | +| #041 | rec | Extend the existing Factsheets reading model | Brief recorded in `docs/factsheets-reading-model-brief.md`: extend Easy Read/Standard on existing Factsheets routes; reject a second patient-facing Factsheets mode unless concrete need + source-governance plan exist. | 2026-07-24 | +| #063 | rec | Define “Current Clinical Work” before implementation | Product/privacy/persistence brief recorded in `docs/current-clinical-work-brief.md`. Default v0 = no new storage (tab/URL resume); Class C free text needs privacy clearance. Stop without demand evidence. No UI/schema implemented. | 2026-07-24 | +| #076 | task | Reproduce malformed fallback PDF image/table crops | Reproduced truncated page-edge `table_crop`s on current-main with `worker/python/fixtures/malformed-table-crop-page-edge.pdf`. Root cause: `pymupdf_find_tables` stops at the last fully detected row; fix extends the candidate from contiguous cell drawings, recovers the on-page score-5 remnant, and emits `table_crop_edge_incomplete` / `crop_completeness=0.9` when content continues past the page. PR #1176. Broad PR #1129 retention/padding changes not merged. | 2026-07-24 | +| #070 | issue | Presentation mobile tabs misroute Overview/Map/Related | Fixed in PR #1135: Overview/Map/Related deep-link to diagnosis `?tab=` sections; Compare stays on the presentation page. Regression in `tests/mobile-interaction-regressions.test.ts`. (Provisional PR-branch IDs `#068`–`#072` were renumbered after `main` claimed `#068`/`#069`.) | 2026-07-24 | +| #071 | issue | Evidence/Clinical Notes Add fakes success without persistence | Fixed in PR #1135: sticky Add controls use the focusable coming-soon placeholder pattern instead of optimistic `setAdded(true)`. | 2026-07-24 | +| #072 | issue | Tools hub exposes false Sort/More affordances | Fixed in PR #1135: Sort is a status label, More filter targets coordination/saved without a fake menu chevron, and the favourites shortcut is labelled Saved/Favourites. | 2026-07-24 | +| #073 | issue | Presentation compare dock CTA is a self-link no-op | Fixed in PR #1135: dock shows non-link "Comparing (N)" status while already comparing. | 2026-07-24 | +| #074 | issue | Mode-action popup hard-reloads internal clinical routes | Fixed in PR #1135: `master-search-header` uses `router.push` for DSM/Specifiers/Formulation actions and mode href fallback. | 2026-07-24 | +| #068 | task | Regenerate full drift-manifest snapshot after schema hygiene | Full Docker `npm run drift:manifest` replay succeeded on a Docker-capable host; `supabase/drift-manifest.json` now carries live `def_hash` values for the plpgsql table-facts body (offline generator_note removed). | 2026-07-24 | +| #052 | issue | Reindex can overlap a fresh agent-enrichment pass | PR #1143 retained the friendly full/retry preflight and closed its check-then-enqueue race with an owner-scoped transactional RPC. Reindex enqueue and the agent claim path serialize on the document row; disposable PostgreSQL proved both interleavings, and exact-head migration replay/unit/build/Chromium/policy/security checks passed. | 2026-07-24 | +| #062 | issue | Upload crash can strand a queued document without a job | Aged owner-scoped `queued`-without-open-job rows are detected by `reindex:health`; the six-hour autopilot raises a durable alert, and guarded recovery uses PR #1143's transactional RPC so enqueue is owner-scoped, idempotent and atomic. `recover:ingestion --include-stranded-queued` remains dry-run/confirmation-first; scheduled production mutation is not enabled. | 2026-07-24 | +| #060 | issue | Safety Plan Generator contradicted the privacy contract | PR #1119 removed patient identifier entry, leaves the post-export name line blank, and aligned tool, privacy and PIA copy. DOM/privacy tests and Chromium copy/print/network coverage prove working content remains in React memory with no fetch/XHR; hosted Production UI, build, unit, policy, safety, static-analysis and secret checks passed. Support-contact details remain classified as sensitive local-only working content. | 2026-07-24 | +| #061 | issue | Missing answer relevance metadata was treated as source-backed | PR #1125 now requires explicit source-backed relevance for trusted/grounded presentation and prevents visual tables, clinical-note sections and quotes, and comparison metadata from bypassing the render model. Three actionable P2 review paths were fixed; focused policy/DOM tests, offline RAG, production-readiness, build, unit, static, security, and Production UI gates passed. No retrieval, ranking, generation, provider, or data behavior changed. | 2026-07-24 | +| #034 | issue | Answer cache can serve stale governance metadata | Current-source verification found direct route coverage already asserts RAG-cache invalidation on document PATCH, source review, label, bulk, and reindex mutation paths. The residual test recommendation is already met; changing the protected cache key is unnecessary. | 2026-07-24 | +| #014 | rec | Realize the `next/image` win on signed previews | Superseded: `SignedImage` uses `next/image` for layout and sizing but deliberately sets `unoptimized`, preventing bearer signed URLs from entering the unauthenticated optimizer cache where cached content could outlive the token. No optimization task remains unless private-image delivery changes. | 2026-07-24 | +| #026 | task | Wire the Supabase document-change trigger | PR #1100 merged after disposable PostgreSQL replay and hosted migration replay. Production migration history and read-only catalog proof confirm the enabled metadata trigger, security-definer function, pinned search path and denied anonymous/authenticated execution; `npm run check:drift` reports no unexpected live drift. Delivery remains intentionally inert until the operator inputs tracked in #025 are configured. | 2026-07-24 | +| #031 | issue | Populate canary Source Governance table | The answer-quality step now consumes the preceding `golden-retrieval.json` only for source-governance reporting. Offline replay of run `30018289898` populated 338 top results, including 202 review-required entries, while retaining zero retrieval cases and no additional threshold failures. Retrieval and ranking behavior are unchanged. | 2026-07-24 | +| #020 | task | Validate eval:quality cost readout post-fix | Confirmed on merged-main canary run `30018289898`: Answer Metrics reported 9 nonzero-cost cases and an estimated answer cost of `$0.234736`; the structured report retained the same value. The PR #1050 estimator fix is operationally proven. | 2026-07-23 | +| #003 | task | Staging tenancy release evidence outstanding | Ran GitHub Action and validated isolation | 2026-07-21 | +| #002 | task | Process-ownership fix not yet isolated on `main` | Fixed process isolation using child.pid termination | 2026-07-21 | +| #008 | rec | Dead href builders in `document-flow-routes.ts` | Not dead code (false positive): `documentReaderHref`/`documentEvidenceHref` are live via the mock wrappers in `src/components/document-search-mockups.tsx` + `src/components/master-document-flow-mockups.tsx` (rendered under `src/app/mockups/document-search/`) and covered by `tests/document-flow-routes.test.ts`; removing breaks the build. Only the production non-mock hrefs are unlinked from prod UI — a wiring gap, not dead code. | 2026-07-22 | +| #015 | task | Content-first fallback regression tests | Added `tests/registry-record-loader.dom.test.tsx` (8) + `tests/medication-record-page.dom.test.tsx` (6) covering content-first fallback paint, live swap-in, spinner/skeleton, error + not-found/unauthorized states, and the invariant that no authoritative verification badge shows before live governance reconciles (registry fixture-flag neutralization + medication governance-drop-on-error). | 2026-07-22 | +| #004 | rec | Rescope provider-gated RAG safety ideas | Closed obsolete — rescue source (754-line RAG-safety worktree) unrecoverable/pruned across all refs; answer-quality thresholds + deep-health already shipped on `main` (#585/#587); only cost-cap preflight was genuinely missing and, per session decision, dropped rather than re-filed. | 2026-07-22 | +| #006 | issue | Globe "Language & region" button had no handler | Resolved on main with the repository's disabled "Coming soon" placeholder convention and button-wiring coverage. Future language/region work remains a feature request, not an inert-control defect. | 2026-07-22 | +| #042 | issue | Invalid optional credentials fell into anonymous access | PRs #1078/#1079 introduced `absent \| valid \| invalid`, return 401 for presented invalid credentials, preserve authoritative header precedence and prefer the current-project session cookie. The archived anonymous-upload metadata patch was rejected as stale because uploads are already administrator-only before duplicate lookup. | 2026-07-22 | +| #043 | issue | Readiness could report healthy or throw on Supabase errors | PR #1080 now fails readiness closed for returned and thrown dependency failures, preserves recognized actionable messages, and prevents raw dependency-error disclosure. | 2026-07-22 | +| #044 | issue | Publication approval was not bound to immutable reviewed state | PR #1081 added a canonical reviewed-state digest, row locks, active-job rejection and a new forward migration with replay/schema/type/drift evidence. | 2026-07-22 | +| #045 | issue | Bulk reindex discarded partial-success results | PR #1084 reserves preflight conflicts for non-2xx responses; completed mixed batches return per-item success/failure/missing results, and the UI refreshes successful work. | 2026-07-22 | +| #046 | issue | DOCX extraction lacked explicit resource budgets | PR #1085 added pre-inflate declared-size checks and post-read fail-safes for artifact count, per-artifact bytes, aggregate media, Word XML and extracted UTF-8 text. | 2026-07-22 | +| #047 | issue | XLSX extraction could construct unbounded results | PR #1086 bounds worksheets, non-empty rows, rendered cells and UTF-8 output while preserving sparse-column rendering. | 2026-07-22 | +| #048 | issue | Account copy overstated sync/privacy and enabled unavailable SSO | PR #1087 now maps copy to actual favourites/preferences persistence, identifies browser-session recents, removes the contradictory "never shared" claim and clearly disables unavailable providers using the accessible placeholder contract. | 2026-07-22 | +| #049 | issue | Process diagnostic exposed a Cursor worker API key | The exact worker was stopped, the key was revoked server-side, both local encrypted worker-secret records were removed, and authorized repository/backup scans found no plaintext copy. Follow-up guardrails now prevent repository process inventory from serializing command lines and redact heavyweight-lock command text before persistence or errors. | 2026-07-23 | +| #050 | issue | Next.js 16.2.10 remained in a high-severity security range | Upgraded `next` and `@next/env` to 16.2.11, regenerated the npm lockfile, confirmed the production dependency audit is clean, and passed focused framework checks, `verify:cheap`, and the full Chromium UI gate. | 2026-07-23 | +| #116 | issue | Missing CI signal on conflicted PRs | RESOLVED 2026-07-30: `.github/workflows/pr-mergeability.yml` checks trusted `pull_request_target` events and refreshes unchanged heads after protected-base pushes. A conflicted PR gets a red `PR mergeability` check naming the conflict instead of an empty CI list. The base-push job alone has scoped `checks: write`; neither path checks out PR code or updates branches. Classifier: `scripts/pr-mergeability.mjs`; contract: `npm run check:pr-mergeability`. Behind-but-clean remains `sync:pr-branches`. | 2026-07-30 |