diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md index 5e585d984e..80239137fb 100644 --- a/docs/branch-review-ledger.md +++ b/docs/branch-review-ledger.md @@ -253,10 +253,11 @@ Records before 2026-07-28 were written by hand and had drifted: 146 lines carrie | 2026-07-30 | PR #1477 | 20f795da2d9d0adafa6cb3117429ab3665129c0d | PR #1477 fork-safe Codex autofix routing | Refreshed onto current main after #1465; issue and ledger reconciliation remained clean and no new actionable defects were introduced. | check:outstanding-issues; check:branch-review-ledger; check:codex-autofix-workflow; focused Vitest 53 passed | | 2026-07-30 | PR #1480 | 6c1e76f53aee87be8408cebc295744fbdce05367 | PR #1480 bounded outstanding reliability fixes | Fixed both review findings: documented the dark accent role and added partial favourites retry without hiding valid counts; no other actionable defects found. | focused Vitest 119 passed; docs index; issue and ledger guards; Actions and Codex workflow guards; Prettier; diff check; typecheck coordinator-blocked | | 2026-07-30 | codex/close-pr1480-issues | bf8ac88b024642eb45d1fead86f4ee30fce3f98d | archive PR 1480 issue resolutions | approved: five resolved rows moved intact to archive | check:outstanding-issues; prettier check; diff check | -| 2026-07-30 | PR-1448 | 8ece7f345e93170c6bd242701eaff05f5504d98b | PR #1448 authenticated live workflow | PASS after review repair: protected-main-only checkout, explicit bounded mutations, scoped secrets, and static dispatch confirmation; no live provider workflow dispatched | GitHub Actions and PR-policy guards passed; focused Vitest 3 passed; docs links and scripts, issue and ledger guards, Prettier and diff checks passed | -| 2026-07-30 | PR-1458 | 8c1975b178c67e4c54acffc395d85e38c43d39f5 | PR #1458 superseded root-gate reconciliation | PASS: retained only unique documentation corrections after PR #1480 landed the stronger tracked-root gate; archived resolved shared-hook issue #143 | docs index and links passed; outstanding-issues and branch-review-ledger guards passed; diff check passed | | 2026-07-30 | codex/close-issue-127 | 9bbb8486d399ed31b9bf43364579f466a4e66c67 | archive issue 127 after post-fix runs | approved: close condition satisfied with no post-fix recurrence | check:outstanding-issues; prettier check; diff check | | 2026-07-30 | codex/close-issue-127 | d5fd28f75b404046f13507aa3705d55898d7669c | review finding wording correction | approved: causal wording now matches PR 1427 implementation | check:outstanding-issues; prettier check; diff check | | 2026-07-30 | PR-1469 | 02108d5424f8a3ab50f45808a6cc3cbd872e7555 | PR #1469 component state matrix coverage | PASS after current-main sync; tests execute enabled and disabled popup transitions plus document search loading, empty, and fault states | focused Vitest 2 files, 10 tests passed; outstanding-issues and branch-review-ledger guards passed; no unresolved review threads | | 2026-07-30 | claude/global-search-mockups-mrgmzl | e79e499839e56bff66aecc37d1c915ac3127e995 | prlanded | merged and verified by content | verify:cheap exit 0 (437 files, 4576 passed); verify:pr-local exit 0; CI pr-required green on a6f2281; squash e79e499 content diff vs branch tip empty; late aria-live/role=alert commit confirmed present on main | +| 2026-07-30 | codex/close-issue-105 | 09950abc8cf2d23455a6cbab3521bdec921ef272 | archive issue 105 after driven browser proof | approved: specific lazy fallback observed in driven desktop and phone Chromium | browser chunk-delay proof; check:outstanding-issues; prettier check; diff check | | 2026-07-30 | PR-1475 | 6de5c321beac55860cc4b6fc7d26ef5a7e088f38 | PR #1475 ingestion behavioral extraction | PASS after current-main reconciliation; extracted decisions preserve entrypoint behavior and replace the matching source-grep assertion with executable coverage | focused Vitest 3 files, 27 tests passed; typecheck passed; outstanding-issues and branch-review-ledger guards passed; provider-backed ingestion not run | +| 2026-07-30 | PR-1458 | 8c1975b178c67e4c54acffc395d85e38c43d39f5 | PR #1458 superseded root-gate reconciliation | PASS: retained only unique documentation corrections after PR #1480 landed the stronger tracked-root gate; archived resolved shared-hook issue #143 | docs index and links passed; outstanding-issues and branch-review-ledger guards passed; diff check passed | +| 2026-07-30 | PR-1448 | 8ece7f345e93170c6bd242701eaff05f5504d98b | PR #1448 authenticated live workflow | PASS after review repair: protected-main-only checkout, explicit bounded mutations, scoped secrets, and static dispatch confirmation; no live provider workflow dispatched | GitHub Actions and PR-policy guards passed; focused Vitest 3 passed; docs links and scripts, issue and ledger guards, Prettier and diff checks passed | diff --git a/docs/outstanding-issues.md b/docs/outstanding-issues.md index f60009838e..eae0f606d3 100644 --- a/docs/outstanding-issues.md +++ b/docs/outstanding-issues.md @@ -138,7 +138,6 @@ removed after current-main verification; it is not missing recommended work. | #101 | P3 | rec | Canary-gated retrieval parallelisation candidates | **Outcome:** independent retrieval stages stop running serially, proven by a live canary pair. Candidates: metadata/memory/visual hydration triples repeated on four branches (`rag.ts:2460,2493,2521` and three more) while `rag.ts:2751-2804` already parallelises three RPCs in one `Promise.all`, so the omission is inconsistency rather than intent; the nested `await`-in-loop scope enumeration (`search-scope.ts:202,328`); typeahead results never cached (`rag.ts:2698-2711`); universal-search coalescing (`/api/search` has it, `/api/search/universal` does not). Each changes candidate assembly, truncation, or what the next keystroke returns, so each needs 36/36 retrieval plus recall 1.0 and zero per-case rr regressions. Distinct from #001 (semantic rerank). Resolved #075 and #083 are the precedents for why these are gated rather than free. **Stop:** needs the #098 harness and explicit canary approval first. | `docs/audit/latency-audit-2026-07-28.md` L2-1/L2-2/L2-8/L1-5 | 2026-07-29 | | #102 | P3 | task | Apply the additive `documents` index debt (operator) | **Outcome:** bare-column `ILIKE` and the paged status scan on `documents` are index-served on hosted. `documents_title_trgm_idx` indexes a CONCATENATED expression, so the bare-column predicates in `api/documents/route.ts:193` and `rag-candidate-sources.ts:477` (RAG path) cannot use it and fall back to scanning; `search-scope.ts:271-277` sorts per page against the single-column `documents_status_idx`. **Runbook prepared 2026-07-29 — NOT applied, item stays open:** three `CREATE INDEX CONCURRENTLY` statements authored and reviewed in `docs/operator-apply-performance-latency-remediation.md` — additive, though **the "recall is byte-identical" claim was RETRACTED on 2026-07-29 review**: `fetchDocumentTitleAliasRows` (`rag-candidate-sources.ts:482`) applies `.limit(12)` with no `ORDER BY`, so a new index can change which title-alias documents feed candidate assembly. Only the documents-list use stays ordering-safe; `(status,id)` is canary-gated too — see runbook, and making that `.limit(12)` deterministic first does **not** lift the gate — an unordered `LIMIT` has no stable selection to preserve, so imposing an order can pick a different twelve and is itself an ordering behaviour change on a retrieval surface, which AGENTS.md requires a canary pair for. Sequencing the ordering fix first is worthwhile (unordered `LIMIT` on a retrieval input is latent nondeterminism regardless) but yields two canary-gated changes, not one (PR #1377 review). **Deliberately NO migration file:** an additive-index migration without a synchronized `schema.sql` mirror and regenerated drift manifest is exactly what closed PR #1312, and the mirror cannot come first because `required_indexes` in `search_schema_health()` (`schema.sql:3178`) runs against live. **Next (operator):** **author the migration first** — `supabase/migrations/` is the source of truth and `schema.sql` only a mirror, so hand-run operator SQL never reaches staging, disaster-recovery replay, or a local `supabase db reset`, and a `required_indexes` registration would fail there (PR #1377 review); follow the `20260717170000_registry_projection_cleanup.sql` idempotent pattern. **That migration must also carry the health-function change** — `required_indexes` lives inside `search_schema_health()`, which is redefined by `create or replace function` in eleven migrations (copy `20260705180000_reconcile_search_health_indexes.sql:62`); editing `schema.sql:3177` alone moves only the mirror and leaves the indexes unmonitored on hosted (PR #1377 review). Then apply concurrently, confirm `indisvalid`, mirror both the index statements and the identical function body into `schema.sql`, run `npm run drift:manifest` (Docker), and deploy the migration LAST — in that order, in one change. Expect `check:drift` to report them as unexpected between steps 1 and 2. **Rollback is three deployed phases, not the reverse of one:** retract `required_indexes` via its own `create or replace function` migration and deploy → drop concurrently live → only then deploy the `schema.sql` removal plus an idempotent forward `drop index if exists` migration, because Supabase wraps migrations in a transaction and a plain `DROP INDEX` there takes the lock the concurrent procedure exists to avoid (PR #1377 review). | `docs/audit/latency-audit-2026-07-28.md` L2-3/L2-5; `docs/operator-apply-performance-latency-remediation.md` | 2026-07-29 | | #103 | P2 | issue | Wide table-facts trigram index missing from `schema.sql` | **Outcome:** the migration chain and `schema.sql` agree on `document_table_facts` trigram indexes. `supabase/migrations/20260714190000_document_table_facts_trgm_idx.sql` creates a wide 5-column trigram index that is **absent from `supabase/schema.sql`**, so local replay and the live database can diverge. Distinct from #102: different owner and verification path. **Next:** confirm whether the wide index exists live, then take one of exactly two routes — **retained:** mirror `document_table_facts_text_trgm_idx` into `supabase/schema.sql` beside the narrow one and regenerate `drift-manifest.json`; **redundant:** drop it through a new forward migration, never by deleting `20260714190000`. **`drift-allowlist.json` is NOT a third option** (PR #1377 review): its own header scopes it to _"Known live-vs-`schema.sql` divergence"_, so it can silence a live drift finding but cannot reconcile the migration chain with the mirror — a fresh `supabase db reset` still runs `20260714190000` and creates the index while `schema.sql` still omits it, leaving this row's stated outcome unmet. **No offline gate catches this today:** the migration↔`schema.sql` parity test (`tests/drift-detection.test.ts:59-68`) only asserts one migration's `schema_drift_snapshot` function definition, not an index inventory — which is why this sits open rather than red in CI, and why a replay-to-schema inventory comparison is the check that would have caught it. Note the narrow `document_table_facts_title_row_param_trgm_idx` (`schema.sql:6425`) is the one the effective RPC expression (`:6726`) actually matches, so the wide index may be genuinely redundant — do not drop it without live scan evidence, per the monitored-not-auto-fixed index policy. | `docs/audit/latency-audit-2026-07-28.md` limitations; `npm run check:drift` | 2026-07-29 | -| #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 neither was held behind #017. **Preconnect half DONE 2026-07-30.** Verified against a dev server started with a placeholder `NEXT_PUBLIC_SUPABASE_URL` — locally the var is unset, `supabaseOrigin()` returns null and nothing renders, so the check fails silently without it. React 19 hoists both tags out of ``: SSR HTML and the live DOM both show `preconnect` and `dns-prefetch` in ``, zero stray `preconnect` in ``, and `crossOrigin="anonymous"` preserved — load-bearing, since without it supabase-js's CORS fetches open a second connection. **`LoadingPanel` half STILL PENDING, and a claimed verification of it was WITHDRAWN 2026-07-30 — read this before re-verifying.** It was briefly recorded as done on the strength of `role="status" aria-label="Loading"` appearing in the SSR HTML of `/`, `/dsm` and `/forms`. Those hits are real but they are **not `LoadingPanel`**: that exact string has exactly one renderer in `src/`, `ModeHomePageSkeleton` (`src/components/mode-home-page-skeleton.tsx:8`), and `LoadingPanel` never emits a bare `"Loading"` label — it renders `aria-label={label}`, always a specific string such as `"Loading differentials"`. Re-checked per route against a running server: `/`, `/dsm`, `/forms`, `/differentials` and `/favourites` return **zero** `aria-label="Loading "` matches. **Why, and what it means for the technique:** Codex's mechanism finding on PR #1459 is correct — the installed Next 16 loader sets `hasSuspenseBoundary` when a `loading` element is supplied, and `BailoutToCSR` throws on the server, so a mounted `ssr:false` surface DOES emit its fallback into the response HTML. But that only fires for a surface that mounts during the initial render, and none of the eleven in `clinical-dashboard-lazy.tsx` do: every one sits behind interaction state (`answer` present, a drawer open, results present — see the mount conditions in `ClinicalDashboard.tsx:3666-4070`). So neither a cold-load grep nor a throttled cold load can observe them. **Next:** verify with a driven browser session — navigate, perform the interaction that mounts the surface, and assert its specific `LoadingPanel` label — or accept that these fallbacks are unobservable on cold load and re-scope the row to say so. **Stop:** the two sidebar dialogs are intentionally excluded — they mount on open, so a fallback would render into a closed dialog. Do not re-close this row on a cold-load grep; that is the exact mistake being withdrawn here. | `docs/audit/latency-audit-2026-07-28.md` L3-4/L3-5; `src/components/clinical-dashboard/clinical-dashboard-lazy.tsx` | 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 | | #121 | P3 | issue | Container Playwright browser build lags the pinned client | **Outcome:** browser gates run in remote sessions without hand-patching. **Evidence 2026-07-30:** the repo's Playwright client resolves headless-shell build `1234`; the container image provides `1194` at `/opt/pw-browsers`, so every browser test fails at launch. Worked around in-session by symlinking `chromium_headless_shell-1234/chrome-headless-shell-linux64/chrome-headless-shell` to the `1194` `headless_shell` binary plus its sibling resources — container-local, nothing committed, and it disappears with the session. `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1` means the mismatch cannot self-heal. **Next:** decide whether the image pins the browser build or the repo pins a client matching the image; until then any remote session claiming browser proof must state which it used. **Added 2026-07-30 (session closing `#120`):** the mismatch reproduced unchanged on `main` at `c5c1a86` — `npx playwright install --dry-run chromium` reports `chromium v1234` while `/opt/pw-browsers` holds only `chromium-1194` and `chromium_headless_shell-1194`, and one `verify:phone-chrome` run lost all 13 browser tests at launch. It has now been misread twice: the 2026-07-30 handoff records 13 launch failures taken as "my change is wrong", and `#120` was filed as a gate defect from a reading taken under this condition (closed as not reproducible; the gate exits 1 correctly). **Detection, before trusting or filing anything from a browser gate:** compare `npx playwright install --dry-run chromium` against `ls /opt/pw-browsers`. **Stop:** do not file a gate defect from a run whose tests never launched — zero assertions executed, so the output describes the environment, not the diff. | `docs/testing.md`; container `/opt/pw-browsers` | 2026-07-30 | | #126 | P3 | task | Quarterly branch-review ledger rotation reminder | **Outcome:** live ledger stays navigable after #1418 L4 bootstrap. **Next:** each UTC calendar-quarter start (or when the live table feels unwieldy), run `npm run ledger:rotate -- --dry-run`, then `npm run ledger:rotate` and commit live+archive. Lookup/sweep/check already read archives. **Stop:** do not hand-move rows; do not delete unique review content. | session 2026-07-30; follow-up to #1418 / L4 | 2026-07-30 | @@ -162,9 +161,10 @@ 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 | -| ---- | ----- | --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | -| #127 | issue | Document-route phone header intermittently failed to hide | Resolved 2026-07-30 by PR #1427, which fixed the short/clamped drag mechanism. Its runway polling and delivered-travel assertions then passed across the four recorded post-fix runs and the later PR #1480 exact-head browser/PWA document-header journeys, with no recurrence. | 2026-07-30 | +| ID | Type | Summary | Outcome | Resolved | +| ---- | ----- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | +| #105 | task | Verify the #017-exempt client latency wins in a browser | Resolved 2026-07-30. The preconnect/dns-prefetch half was already proved in SSR and the live DOM. The remaining fallback was verified in driven Chromium by switching the dashboard from Answer to Documents while delaying the exact document-search-results chunk by 1.6 s: role=status with aria-label=Loading document results appeared after 315 ms at 1440x900 and 123 ms at 390x844, then disappeared when the chunk executed. The phone pass used keyboard activation, reduced motion, and forced colors, retained focus on Mode Documents, and had zero horizontal overflow. | 2026-07-30 | +| #127 | issue | Document-route phone header intermittently failed to hide | Resolved 2026-07-30 by PR #1427, which fixed the short/clamped drag mechanism. Its runway polling and delivered-travel assertions then passed across the four recorded post-fix runs and the later PR #1480 exact-head browser/PWA document-header journeys, with no recurrence. | 2026-07-30 | | ID | Type | Summary | Outcome | Resolved | | ---- | ----- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- |