diff --git a/.agents/skills/handover/SKILL.md b/.agents/skills/handover/SKILL.md index e8ee81cd72..d942664258 100644 --- a/.agents/skills/handover/SKILL.md +++ b/.agents/skills/handover/SKILL.md @@ -6,8 +6,8 @@ description: Prepare a concise evidence-backed Database handover without automat # Handover 1. Inspect branch, upstream, worktrees, status, relevant diffs, and recent commits. -2. Run `npm run workflow:lifecycle -- --phase handoff --write-evidence`. -3. Run the smallest proportionate offline verification; prefer `npm run verify:pr-local` for non-trivial ready work. +2. Run `npm run workflow:lifecycle -- --phase handoff --write-evidence` and use its verification routing. +3. Run one smallest proportionate offline gate; prefer `npm run verify:pr-local` for non-trivial ready work and do not stack broad gates without a distinct failure class. 4. Separate intended changes from unrelated dirty work and list generated artifacts. -5. Summarize files, checks, failures, skipped gates, risks, and the exact next action. +5. Summarize files, checks, failures, skipped gates, risks, the decisive proof line (not exit 0 alone), and the exact next action. 6. Do not commit, push, open a PR, merge, or call providers unless explicitly requested and authorized. diff --git a/.claude/agents/verification-router.md b/.claude/agents/verification-router.md index 2d0c6deaa9..636e9c105c 100644 --- a/.claude/agents/verification-router.md +++ b/.claude/agents/verification-router.md @@ -37,8 +37,11 @@ Default to running **only** offline-safe gates. For any provider-touching comman - **Retrieval / ranking / selection / chunking / scoring:** offline gate is `verify:cheap`; note that the merge gate `eval:retrieval:quality` (36/36) is provider-touching → report and ask. - **Ingestion / answer-gen / source-governance / privacy / production env:** smallest relevant domain check + `check:production-readiness` (runs fail-closed offline). -- **UI / frontend / a11y / routing / styling:** `npm run ensure` then `verify:ui`. +- **UI / frontend / a11y / routing / styling:** `npm run ensure`, then the affected journey; + add `verify:ui` only for shared UI foundations or a distinct unclosed failure class. - **Supabase env/config change:** `check:supabase-project` (provider — report and ask). -- **Default source/config/test change:** `verify:cheap` first, `verify:pr-local` before PR handoff. +- **Default source/config/test change:** `verify:pr-local` at PR handoff; do not pre-run + `verify:cheap` because the routed handoff gate already owns that coverage. -Report the chosen gate, why it fits the diff, and any provider command that the author must run manually with confirmation. +Report the chosen gate, why it fits the diff, its decisive proof line (not exit 0 alone), checks +deliberately not stacked, and any provider command that requires confirmation. diff --git a/.claude/skills/gates/SKILL.md b/.claude/skills/gates/SKILL.md index 64325def52..3c504321d3 100644 --- a/.claude/skills/gates/SKILL.md +++ b/.claude/skills/gates/SKILL.md @@ -9,7 +9,9 @@ A green exit code is not proof. Contended gates can wait a long time before fail leave later checks unrun, and a stale worktree makes healthy-looking runs meaningless. This skill exists because those failures have cost real time more than once. -**Rule: never report a gate as passing without quoting the line that proves it ran.** +**Rule: never report a gate as passing without quoting the decisive line that proves it ran. Pick +one smallest sufficient gate first; do not stack broad gates unless each covers a distinct plausible +failure path.** ## The false-green traps diff --git a/.claude/skills/handoff/SKILL.md b/.claude/skills/handoff/SKILL.md index 38472dc230..871025e97b 100644 --- a/.claude/skills/handoff/SKILL.md +++ b/.claude/skills/handoff/SKILL.md @@ -18,16 +18,29 @@ force-push, or discard work. ## Steps 1. **Inspect first (read-only):** `git status --short --branch`, `git diff`, `git diff --cached`, - and the ahead/behind from `node scripts/check-base-freshness.mjs`. If staged paths are found - that aren't part of the current session's own work (leftover from other sessions' WIP), - unstage them with `git restore --staged ` before proceeding. + and the ahead/behind from `node scripts/check-base-freshness.mjs`. Record the exact cached index + state with `git diff --cached --raw --no-renames` before staging. Also record the worktree and + untracked state for every intended path with `git status --porcelain=v1 -z --untracked-files=all -- `. + Immediately before staging, repeat and compare both snapshots; if any intended path changed, + appeared, or disappeared, stop or move the handoff to an isolated worktree. Do not accept a + concurrent change merely because its path is intended. If the cached index contains paths outside + this session, stop and move the handoff to an isolated worktree; never unstage or otherwise + mutate another session's index entries. + Record `git branch --show-current` and `git rev-parse HEAD`; repeat both immediately before and + after the commit. Immediately before committing, repeat `git diff --cached --raw --no-renames` + and verify that every pre-existing cached entry is unchanged and every new entry is in the + explicit intended-path allowlist. Stop if the branch moved, HEAD changed before your commit, or + the cached index differs outside those intended paths. A shared worktree/index is not safe + handoff state. 2. **Stage coherent, completed changes only.** Stage explicit paths — never `git add -A` blindly. Do not stage `.env*`, secrets, build output, logs, or unrelated WIP; if you see a possible secret, report the path (never the value) and stop. -3. **Verify** with the smallest sufficient gate: - - Default: `npm run verify:pr-local` (format + cheap gate, plus build/RAG when the - scope needs them). - - Touched UI/routing/styling: add `npm run verify:ui`. +3. **Verify** by invoking `verification-router` (or the `gates` skill when scope is already clear) + and run the one smallest sufficient gate it selects. Default PR-ready work uses + `npm run verify:pr-local`; inspect its selection with `--dry-run` when uncertain. For + UI/routing/styling, prove the affected journey first and add `verify:ui` only for shared UI + foundations or when the router says its distinct coverage is necessary. Never stack + `verify:cheap` + `verify:ui` + `verify:release` by default. - Touched `src/app/`, `src/components/`, or `tests/` (or design-system adoption inputs): run `npm run design-system:adoption:update` and stage any regenerated `docs/design-system/adoption-manifest.json` / marked COMPONENTS/ADOPTION sections @@ -35,10 +48,15 @@ force-push, or discard work. bypass hooks still need the explicit update or static-pr + coverage fail together (PR #1782). - Touched Supabase env/config: `npm run check:supabase-project` (provider — confirm first). - Do not claim a gate passed unless it actually ran. -4. **Commit** with a clear message. End the message with: + Do not claim a gate passed unless it actually ran. Paste the decisive proof line (for example, + the test count or named check success), not only exit code 0. +4. **Commit** with a clear message, then verify the new commit has your message, only your intended + paths (`git show --name-only --format=fuller HEAD`), and the same branch name recorded in step 1. + End the message with: `Co-Authored-By: Claude Fable 5 `. -5. **Push** the feature branch: `git push -u origin `. The pre-push guards run +5. **Push** the feature branch: `git push -u origin `. Never pipe the push through `tail`, + `head`, or another command that can mask its status. Confirm the remote tip equals local HEAD + with `git ls-remote` before reporting success. The pre-push guards run (auto-merge sentinel, format, drift) — heed a block rather than overriding blindly. 6. **Open a PR** with `gh pr create --base main`, body ending with the Claude Code attribution line. Write the body from `.github/pull_request_template.md` in full normal diff --git a/.claude/skills/issues/SKILL.md b/.claude/skills/issues/SKILL.md index e017c390ae..6738da0723 100644 --- a/.claude/skills/issues/SKILL.md +++ b/.claude/skills/issues/SKILL.md @@ -9,8 +9,13 @@ description: Track and recall all outstanding tasks, recommendations, and issues execution order, open **tasks**, **recommendations**, **issues**, provider/operator work, and archive history. Chat context resets; that file does not. This skill reads it back and keeps it current. -**The ledger is the source of truth, not chat memory.** Never answer `/issues` from conversation -recall — always read the file first, so the answer is correct even in a fresh session. +**The ledger on the remote `main` branch is the source of truth, not chat memory or a stale +worktree.** Never answer `/issues` from conversation recall or by reading the checkout file +directly. Run `npm run issues:report -- --json`; it reads the locally cached +`origin/main:docs/outstanding-issues.md`, reports the checkout's `behind`/`ahead` counts, and labels +that source `revalidated: false`. Repeat its warning instead of presenting cached state as current. +A current remote read requires an explicitly authorized `git fetch origin main` immediately before +the report; record that fetch separately because the report itself performs no provider access. ## Trigger @@ -21,7 +26,7 @@ recall — always read the file first, so the answer is correct even in a fresh ## Default: `/issues` (read-only) -1. Read `docs/outstanding-issues.md`. +1. Run `npm run issues:report -- --json` and use that payload, preserving its cached-state warning. 2. State the **Recommended execution queue** back in order, including acuity, timing, and gate. 3. Summarize any open items not represented in that queue, grouped by priority (P1 → P3), each as `#ID · type · summary — next action (source)`. @@ -32,6 +37,13 @@ If a filter is given, filter the open items before rendering steps 2–3, then s queued tasks and matching non-queued items: `/issues P1` (by priority), `/issues issues` / `/issues recs` / `/issues tasks` (by type), `/issues ` (summary/detail substring match). +`/issues wins` or `/issues agent-safe` runs +`npm run issues:report -- --agent-safe-wins --json`. The classifier includes only queued work +estimated at no more than four hours whose capability is not Operator and whose timing/outcome names +no provider, live environment, RAG/retrieval/clinical surface, approval, owner decision, or human +decision. Keep report order unchanged and always state A1 priority blockers before these convenience +wins; the filter never changes acuity. + **A row being open is not evidence that nobody is working on it.** Some rows carry a progress marker in their prose (`IN PROGRESS`, `IMPLEMENTED in PR #1766`), but there is no structured status field and no atomic claim — a marker is written by whoever did the work, usually after the fact, and nothing @@ -85,6 +97,13 @@ to prevent; treat it like `ledger:append` for the review ledger. It does **not** between concurrent branches (see `#156` / `#168`) — that needs a different id scheme, not a better writer. +Immediately before any mutation, explicitly refresh `origin/main` after provider authorization, +then run `npm run issues:report -- --json` again and rebuild the intended edit against that cached +ref rather than the worktree copy. Record the fetched SHA because the report deliberately does not +claim that a local remote-tracking ref is independently revalidated. After the writer returns, +inspect `git diff -- docs/outstanding-issues.md` and refuse any result that drops or duplicates +unrelated rows. Never use GitHub's Update branch button for a PR touching this file. + - Keep the table format and column order exactly as in `docs/outstanding-issues.md`. One row per item. - Add a retained task to the recommended queue with order, acuity, capability, timing, estimate, gate, success criteria, verification, and stop rule. Reorder rather than duplicate related work. @@ -96,8 +115,8 @@ writer. - This file deliberately has **no** merge driver, so an overlapping edit conflicts loudly. `merge=union` was tried and removed: it concatenated both sides silently, duplicating rows and the `next-id` marker (`#133`). Never resolve a conflict by taking one side wholesale — that - drops the other agent's rows. Rebuild from `origin/main` and re-apply only the rows you - changed. `npm run check:outstanding-issues` fails on duplicate IDs, a stale next-id marker, + drops the other agent's rows. Rebuild from `origin/main` and re-apply only the rows you changed; + never take either side wholesale. `npm run check:outstanding-issues` fails on duplicate IDs, a stale next-id marker, or a merge driver reappearing. - Respect the repo's RAG/clinical/privacy flagging rules if an item _itself_ touches a protected surface — recording it here is fine, but acting on it later still needs the usual gate. diff --git a/AGENTS.md b/AGENTS.md index 858ab53acd..514adac2c0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -883,8 +883,9 @@ status ledger. Update the universal ledger when work completes, is dropped, beco materially re-scoped. Never restore completed, duplicate, speculative, superseded, or rejected work to the recommended queue. -- When the user types `/issues`, invoke the `issues` skill (`.claude/skills/issues/SKILL.md`): read - `docs/outstanding-issues.md`, state the recommended queue in order, then summarize other open +- When the user types `/issues`, invoke the `issues` skill (`.claude/skills/issues/SKILL.md`): run + `npm run issues:report -- --json` to read the cached `origin/main` ledger with an explicit stale-state warning; + refresh that ref first only with provider authorization. State the recommended queue in order, then summarize other open items by priority. A plain `/issues` is read-only — it mutates and commits nothing. - `/issues add|done|update|capture …` mutate the ledger; each mutation commits **only** `docs/outstanding-issues.md` (no push unless the user asks or you are already handing off). diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md index db12429fe8..f7b079ffdc 100644 --- a/docs/branch-review-ledger.md +++ b/docs/branch-review-ledger.md @@ -883,7 +883,7 @@ Records before 2026-07-28 were written by hand and had drifted: 146 lines carrie | 2026-08-11 | codex/answer-loading-ui-20260811 | 6758f8156f9d1b3e893981dfd7a1f6563aa90da0 | answer creation loading UI | No high-confidence findings | UI 3 passed; unit 8 passed; lint, typecheck, build, design-system and offline RAG passed; full suite 6022 passed with 16 unchanged baseline failures | | 2026-08-11 | claude/codex-m4c-retire-shadow-nliak3 | 448a0d084c4cd2cda6153dd7f03dcb67c43a8df0 | DS Track A2 (#261): retire --shadow-focus; composer focus onto sanctioned outline; contract guard; baseline ratchet; design-system docs + ledger | Approved — PR #1807. Token deleted in both themes; .chat-composer-shell-delta:focus-within uses outline 2px var(--focus) at offset 2px and no longer overrides box-shadow. Reach premise corrected: 0 of 37 production routes render the class (only /mockups/calculators-search). legacyShadowAliases 127->125, globals.css pin 3->1. | check:design-system-contract PASS; design-token-contract.test.ts PASS + mutation-verified both ways; verify:pr-local PASS except pre-existing tests/pr-handoff-stop.test.ts failure baselined on untouched base e8b61d8; build PASS; check:rag:fixtures PASS (36 cases); Chromium look both themes on the mockup route (inspection only, rev 1194 vs pinned 1234 #255); verify:ui/verify:phone-chrome NOT run — delegated to CI | | 2026-08-11 | codex/answer-ecg-animation-20260811 | 12279a8309c225aa957ef1e65afc37545a0ce04c | answer ECG progress variants | No high-confidence findings; physical Safari/PWA remains residual acceptance | design contract, typecheck, focused unit 8/8, trace token 33/33, Chromium 4/4, offline RAG 574/574; full suite baseline/platform failures | -| 2026-08-11 | codex/chat-services-flow-redesign-20260812 | 6f44b92defb91bcd77509bf10337b428be37619c | Services home, results, shortlist, comparison, and referral detail redesign | No findings; changed-area UI, phone contracts, focused unit, build, and RAG fixtures passed; PR-local Windows baseline limitations documented. | 78 focused tests passed post-merge; 185 changed-browser tests; 129 phone contracts; 7 phone-scroll tests; build and RAG fixtures passed | +| 2026-08-11 | claude/filter-popup-design-mockups-x6sbjv | 7b64f2559741a9f353adcf939745831e0daff7db | services filter sheet redesign mockups (3 directions, desktop+phone) | PR #1828 opened; design-scratch route only, no production behaviour change | verify:pr-local (1 pre-existing root-uid test failure, reproduced on origin/main 046feb3), build, check:rag:fixtures, check:bundle-budget both baselines within tolerance, 320px 0px overflow | | 2026-08-11 | work | 6dcd695076d630d16aae594577763e8004361893 | Codex Cloud setup and local parity | P2 fixed: cache-friendly locked Cloud npm install; parity limitations documented | check:codex-cloud; codex-cloud-setup 24/24; full suite 6059 pass, 7 unrelated timeout/state failures | | 2026-08-11 | 1822 | 4fab267f52b72992745e1d2e6975fb4847af447a | review-and-fix | clean | Build pass; Static PR checks pass; Change scope pass; PR mergeability pass; PR policy pass; Safety and config checks pass; Semgrep pass; Semgrep ingestion gate pass; Gitleaks pass; GitGuardian pass; Unit coverage pending; Production UI (1) pass; Production UI (2) pass; Production UI critical pending; Production UI (3) pending; Lighthouse budget pass; PR required pending | | 2026-08-11 | 1822 | 4fab267f52b72992745e1d2e6975fb4847af447a | review-and-fix (supersedes 2026-08-11) | clean | Build pass; Static PR checks pass; Change scope pass; PR mergeability pass; PR policy pass; Safety and config checks pass; Semgrep pass; Semgrep ingestion gate pass; Gitleaks pass; GitGuardian pass; Unit coverage pass; Production UI (1) pass; Production UI (2) pass; Production UI (3) pass; Production UI critical pass; Lighthouse budget pass; PR required pass | @@ -891,29 +891,31 @@ Records before 2026-07-28 were written by hand and had drifted: 146 lines carrie | 2026-08-11 | 1821 | d76e90547dbdb104256b66a508c15c74302002fc | review-and-fix | dispositioned | PR policy:success; PR mergeability:success; Gitleaks:success; Semgrep:success; Semgrep ingestion gate:success; Safety and config checks:success; Build:success; Production UI critical:success; Production UI (1):success; Production UI (2):success; Production UI (3):failure test not reproduced outside this PR; PR required:failure | | 2026-08-11 | work | 45fd05c8c3947835c0368666ff576c7a38b33ee4 | mobile evidence sheet UX, accessibility, and feedback logic | fixed unexplained claim marker, excess panel reserve, unclear purpose and feedback copy; no remaining high-confidence defects | focused DOM 7/7; Chromium evidence journey 1/1; offline RAG 23 suites/574 tests | | 2026-08-11 | 1820 | 897ff11a4cdb13ae1c01f5eb149007847028f5aa | review-and-fix | fixed | Semgrep:IN_PROGRESS, Gitleaks:IN_PROGRESS, Semgrep ingestion gate:IN_PROGRESS, Static PR checks:QUEUED, Safety and config checks:QUEUED, Unit coverage:QUEUED, Build:QUEUED, Production UI critical:QUEUED, Lighthouse budget:QUEUED | +| 2026-08-12 | claude/filter-popup-design-mockups-x6sbjv | 5e41d164e30e8f5a74b255fbeafd34123385dbb9 | services filter: round-two options study (stop-the-bleed / recommended / presets-evicted) | Pushed to PR #1828; merged babysit fixes to round-one facet semantics; design-scratch only | verify:pr-local (1 pre-existing root-uid failure only), build, check:rag:fixtures, bundle-budget mockups 286.8 KiB within 25% tolerance, counts re-verified vs snapshot, 320px 0px overflow | +| 2026-08-11 | codex/chat-services-flow-redesign-20260812 | 6f44b92defb91bcd77509bf10337b428be37619c | Services home, results, shortlist, comparison, and referral detail redesign | No findings; changed-area UI, phone contracts, focused unit, build, and RAG fixtures passed; PR-local Windows baseline limitations documented. | 78 focused tests passed post-merge; 185 changed-browser tests; 129 phone contracts; 7 phone-scroll tests; build and RAG fixtures passed | | 2026-08-11 | claude/spacing-icon-design-review-rxwh28 | f8701a524f0eb22decc64ce1f626bdafe91751af | mode-home hero spacing rhythm + icon scale (PR #1815) | shipped: group copy reserve banded to measured wrap points, continuous hero medallion, phone composer glyph 1.1rem->icon-lg, surface glyphs onto size-icon-*, privacy link bottom-only negative margin (fixes 8px tap overhang on the APP-5 sentence), composer phone reserve 7.625->6.625rem | test 6043 passed/1 pre-existing root-perm failure; lint; typecheck; build; check:icon-scale; check:type-scale; check:design-system-contract; check:rag:fixtures; check:bundle-budget; prettier --check .; verify:ui NOT run (Playwright r1234 vs image r1194, #255 - delegate to CI Production UI) | | 2026-08-11 | 1815 | be7461ef1f66357999995acefbeecaf95268e481 | unblock | local-build-pass | MergeTreeClean,UnitCoverage,StaticPRChecks,ContainerImages | | 2026-08-11 | claude/spacing-icon-design-review-rxwh28 | 455bc198c077860fb1f830670a5fa9c1de08da52 | pr-1815 heavy review-and-fix | remote already merged main (shadow-tight Switch kept); cherry-picked privacy -mb-4 reclaim + calculators dock cancel; removed duplicate UniversalSearchAlsoMatches; rail-aware section-sheet focus restore; dispositioned CodeRabbit docs/ledger/gates nits and outdated Sentry skeleton gap | verify:cheap PASS prior tip; verify:pr-local PASS prior tip; vitest privacy+in-page-nav 28 passed on cherry-pick; merge-tree clean vs origin/main | | 2026-08-11 | claude/spacing-icon-design-review-rxwh28 | 5b96281ee7da817d5ce7f1102004ebe6f861b920 | pr-1815 heavy review-and-fix | remote already merged main (shadow-tight Switch kept); cherry-picked privacy -mb-4 reclaim + calculators dock cancel; removed duplicate UniversalSearchAlsoMatches; rail-aware section-sheet focus restore; dispositioned CodeRabbit docs/ledger/gates nits and outdated Sentry skeleton gap | verify:cheap PASS prior tip; verify:pr-local PASS prior tip; vitest privacy+in-page-nav 28 passed on cherry-pick; merge-tree clean vs origin/main | | 2026-08-12 | PR #1815 / claude/spacing-icon-design-review-rxwh28 | 9f266210f02081be54d407c70a85f52fed436128 | babysit | no remaining actionable findings; one pre-existing thread resolved as no-change (Dockerfile.worker follow-up needed) | required checks: Gitleaks PR policy PR required (all pass); targeted vitest passed: tests/document-frame-contract.test.ts + tests/in-page-nav-header.dom.test.tsx | | 2026-08-12 | 1815 | 27ce96e1755055ceee2eeae02d6efdf11259fcde | babysit | fixed | Unit coverage: targeted vitest passed: tests/shared-home-empty-state.dom.test.tsx (17 passed). PR required still blocked on pre-existing check failure at old remote head before sync. | +| 2026-08-12 | codex/implement-process-safety-for-multi-agent-workflows | 06144a7fcde8fea5dca63348bcc968fe796b152e | full PR diff and unresolved review feedback | Fixed cached-origin truthfulness, agent-safe approval gates, UI browser proof ordering, Added-date JSON, and foreign-index handoff safety; prior #240/#253 classifier feedback already fixed. | focused Vitest 31/31; outstanding-issues guard pass; gate-manifest pass; git diff --check | | 2026-08-12 | claude/design-issues-triage-wnr7k9 | a6bfc6f2707975d9b9c649843e083965c80afb9c | Tier 1 design-issue re-verification: archive #171/#172/#174/#181/#273/#274/#302, correct #293 | docs-only; six rows verified delivered on main, min-h-tap finding refuted as deliberate sm: step-down | verify:pr-local (10/10 green); check:outstanding-issues 138 open/163 archived | | 2026-08-12 | claude/design-issues-triage-wnr7k9 | 970d39bc7023823d3283c660df090659a2f07aec | Full outstanding-issues ledger sweep: 47 rows individually verified against merged main | 19 archived (delivered or duplicate), 10 re-scoped with re-measured evidence, 1 refuted (#293), 4 machine-local rows annotated do-not-close-from-cloud; 98 rows bucketed by blocker, not individually verified | verify:pr-local 10/10 green; check:outstanding-issues 126 open/175 archived, no ids deleted from base | -| 2026-08-11 | claude/filter-popup-design-mockups-x6sbjv | 7b64f2559741a9f353adcf939745831e0daff7db | services filter sheet redesign mockups (3 directions, desktop+phone) | PR #1828 opened; design-scratch route only, no production behaviour change | verify:pr-local (1 pre-existing root-uid test failure, reproduced on origin/main 046feb3), build, check:rag:fixtures, check:bundle-budget both baselines within tolerance, 320px 0px overflow | -| 2026-08-12 | claude/filter-popup-design-mockups-x6sbjv | 5e41d164e30e8f5a74b255fbeafd34123385dbb9 | services filter: round-two options study (stop-the-bleed / recommended / presets-evicted) | Pushed to PR #1828; merged babysit fixes to round-one facet semantics; design-scratch only | verify:pr-local (1 pre-existing root-uid failure only), build, check:rag:fixtures, bundle-budget mockups 286.8 KiB within 25% tolerance, counts re-verified vs snapshot, 320px 0px overflow | | 2026-08-12 | codex/pr-workflow-safety-230-296 | bc0a491fdf4146775629f9b2b03e2a2cc61bd7cb | pr-1830 unblock | unblocked: merged origin/main (outstanding-issues conflict), PR body RAG impact + governance, resolved Copilot thread; merge-tree clean; required CI in progress | check:outstanding-issues pass; evaluatePullRequestPolicy ok; merge-tree clean; PR policy/mergeability/Change scope in progress | | 2026-08-12 | claude/filter-contract-global | a0add717c2521c7fdeba4da5b094377014383c3e | global filter contract: lens/facet kinds + docs/filter-contract.md (no rendered change) | PR #1847 opened; additive only, zero call sites touched; fixed an accessible-name leak caught by the new DOM tests | verify:pr-local fully green (no failures), 4 new DOM tests, git diff over all 7 mode files empty | | 2026-08-12 | claude/design-issues-triage-wnr7k9 | 2553b64b2342b0ef2ebef0afde152e76c1252496 | Ledger sweep round 2: open-PR cross-check plus clinical/answer-surface verification | 24 rows flagged IN FLIGHT against 7 open PRs (none had said so); 3 answer-surface rows archived (#166 #208 #216); #250 wave plan re-scoped; main-merge conflict resolved preserving both sides, 23 branch changes re-applied via the writer | verify:pr-local 10/10 green; check:outstanding-issues 121 open/180 archived, no ids deleted from base | | 2026-08-12 | claude/rag-canary-test-review-seprbt | bcf357a96fde74d39fc4726ffabb5079a744ef28 | eval-canary review: workflow, compare tooling, snapshot builder, alias tiering, rag-behaviour docs | PR #1843 opened; no retrieval behaviour change; snapshot refresh handed off as /issues #304 | verify:pr-local (green except env-only #296), eval:rag:offline 574/574, focused suites 40/40 | | 2026-08-12 | claude/design-issues-triage-wnr7k9 | 586012639565e4d3306b44361ebc5a3bdb3024ad | Land PR #1838 ledger sweep; close #147 mobile CLS by measurement | Merge resolved as union (main renumbered #302/#303 to #306/#307 — not lost, correcting an earlier claim); #306/#307 archived as already-delivered. #147 archived on two identical offline Lighthouse runs: mobile CLS 0.035/0.000/0.013/0.081/0.000, all under 0.1, cause fixed by PR #1616 not this session. #118 updated (browser drift 141-vs-151, wider than recorded); new #308 for desktop /documents/search CLS 0.119 | verify:pr-local 10/10 green; check:outstanding-issues 121 open/185 archived; verify:lighthouse x2 (gate ungraded on browser drift, measurements valid) | -| 2026-08-12 | PR-1836 | eef2e275b7d5944206f1a27e23fdd78d95b383d8 | full PR diff and unresolved review feedback | No P0-P2 findings; prior review feedback already fixed and dispositioned | focused ledger/docs/workflow guards pass after current-main merge | -| 2026-08-12 | claude/segmented-control-count | d5ff3160242986d2fac80ed9a915390b5c69b6e1 | SegmentedControl option hint slot (filter rollout prerequisite) | PR #1848 opened; additive, no call site passes hint yet; fixed a concatenated accessible name (All62 -> All (62)) | lint/typecheck/test green, 80 in ui-v2-components, 56 design-sync with no regen needed, clean build, bundle-budget within tolerance | -| 2026-08-12 | 1848 | c65b9d91b760862c2ff9d5001974670219c5da02 | full PR diff and unresolved review feedback | P2 hint contrast and live-count width fixes applied | focused Vitest passed (81); focused ESLint passed; design-system contract passed | +| 2026-08-12 | codex/implement-process-safety-for-multi-agent-workflows | 6d054c1fa02a988829def3274b32d31c13570851 | full PR diff and unresolved review feedback | Fixed cached-origin truthfulness, agent-safe approval gates, UI browser proof ordering, index handoff safety, and synced main | focused Vitest 31/31; tsc --noEmit pass; git status clean | +| 2026-08-12 | codex/implement-verification-policy-changes-for-multiple-tasks | 8177129497eb95105cdd5bba80dbf72a9f88b066 | pr-review | resolved actionable Codex review findings; updated operational-risk patterns; removed outdated metadata from PR body and title | verify:cheap, pr-policy self-test | | 2026-08-12 | PR #1595 / claude/ds-v2-adopt | 590eb6cfb229c5ae0f7a5025352fa871d8321521 | Supersedes 2026-08-03 PR-J clinical-governance review at f9f73c707d9b6b6226fc04d172fef8e426513055; accepted delta through merged PR head | SUPERSEDES the earlier PR-J clinical-governance row for merge evidence. The final delta added the answer-state projection, the two scoped review fixes, and the clinically approved #228 attribution wording. The user accepted that delta without a second clinical-governance review; this record preserves that explicit limitation rather than implying the earlier review covered the final tree. | Final PR head 590eb6cfb229c5ae0f7a5025352fa871d8321521; squashed to main as f4448f8c1 (historical mapping recorded in #232); no new provider or clinical review performed | | 2026-08-12 | PR-1835 | fe46e5ade8018d21cf15d149711579b1b43c7fb8 | full PR diff and unresolved review feedback | P1/P2 findings fixed during fresh open-PR sweep; rename-only historical review comments dispositioned no-change | focused drift/docs/ledger/migration checks pass; verify:pr-local static+lint+typecheck pass, unrelated Windows unit baseline failures | -| 2026-08-12 | claude/filter-facet-formulation | 9262d89701808c58e3812a60b982596bb3f2b218 | filter contract PR B: formulation facet adoption (derive domains, union counts, evict query-replacing presets) | PR #1858 opened; domain converted from 12 radios to 9 derived facet chips (Biological/Social/Cultural carried by 0 of 12 mechanisms, removed per derive-dont-declare); union counts verified monotonic and non-additive (Affect 9 OR Risk 4 = 10); zero-yield options render as focusable dead ends, never on an already-selected option; Pattern group evicted from the sheet to AnswerSuggestionChips (all 5 presets, old slice(0,4) left one unreachable); ResultFilterFacetChips exported so desktop rail and sheet share one renderer; desktop select of 13 retired. Shares result-filter-control.tsx with PR #1857 - land #1857 first, its accessible-name fix then covers these chips | verify:pr-local failed:(none) not reached:(none), all 15 steps green including build with the server stopped; full unit suite 558/558 files, 6101 passed 4 skipped, zero failures; formulation.test.ts 11 passed with 3 new contract tests; bundle-budget production 1296.1 KiB and mockups 285.1 KiB within tolerance on a freshness-verified build; browser proof 1440/390/320px, 0px overflow, 9 chips not 12, 0 selects, 5 suggestion chips, live dead-end-to-selectable transition on union widening, phone sheet radiogroup count 0 | -| 2026-08-12 | codex/implement-verification-policy-changes-for-multiple-tasks | 8177129497eb95105cdd5bba80dbf72a9f88b066 | pr-review | resolved actionable Codex review findings; updated operational-risk patterns; removed outdated metadata from PR body and title | verify:cheap, pr-policy self-test | | 2026-08-12 | PR-1837 | 401aadc1d24a99067eb0472dc4419d85502e0caa | full PR diff and unresolved review feedback | No P0-P2 findings after current review fixes; existing dispositions verified | focused workflow policy and ledger guards pass after current-main merge | | 2026-08-12 | codex/implement-verification-policy-changes-for-multiple-tasks | 2fed97c601948b959120ff73e88be54af1dc84ba | pr-review | clean | check:pr-policy, verify:pr-local --dry-run | +| 2026-08-12 | PR-1836 | eef2e275b7d5944206f1a27e23fdd78d95b383d8 | full PR diff and unresolved review feedback | No P0-P2 findings; prior review feedback already fixed and dispositioned | focused ledger/docs/workflow guards pass after current-main merge | +| 2026-08-12 | claude/segmented-control-count | d5ff3160242986d2fac80ed9a915390b5c69b6e1 | SegmentedControl option hint slot (filter rollout prerequisite) | PR #1848 opened; additive, no call site passes hint yet; fixed a concatenated accessible name (All62 -> All (62)) | lint/typecheck/test green, 80 in ui-v2-components, 56 design-sync with no regen needed, clean build, bundle-budget within tolerance | +| 2026-08-12 | 1848 | c65b9d91b760862c2ff9d5001974670219c5da02 | full PR diff and unresolved review feedback | P2 hint contrast and live-count width fixes applied | focused Vitest passed (81); focused ESLint passed; design-system contract passed | | 2026-08-12 | claude/filter-lens-modes | 5cf8871ef122ec9e3d9b25ea65c4643d5a2cf2ba | filter contract PR A: lens adoption across differentials, medication, applications, specifiers | PR #1857 opened; 4 bespoke aria-pressed rails converged onto SegmentedControl with one shared option array per mode; specifiers footerNote fixed (counted results+catalogueMatches while filters govern only results); ResultFilterSheet counted-option accessible name fixed (All8 -> All (8)) on both group kinds; SegmentedControl gained group-level ariaControls so the launcher keeps #launcher-results-panel; dead SpecifierFamilyFilterChips removed; scope segment deliberately deferred to services per filter-contract.md s4 | verify:pr-local all steps green except build, which failed on the /issues #210 dev-types corruption and passed on a clean rebuild; unit suite 6100 passed/4 skipped with one 30s timeout (not an assertion failure) in design-sync-contract under parallel load, passing in isolation 7/7; bundle-budget production 1297.7 KiB and mockups 285.1 KiB both within tolerance on a verified-fresh build; browser proof at 1440/800/390/320px on all four modes, 0px overflow, 48px targets | | 2026-08-12 | 1849 | 34e5581c4418ef8a08909dff9ecf91d4a8f622de | full PR diff and unresolved review feedback | P1 setup-only PAT remained accessible through gh credential storage; removed agent-phase PAT persistence and retained safe base/shim changes | check:codex-cloud PASS; docs:check-inventory PASS; focused Vitest blocked by active repository lease | +| 2026-08-12 | claude/filter-facet-formulation | 9262d89701808c58e3812a60b982596bb3f2b218 | filter contract PR B: formulation facet adoption (derive domains, union counts, evict query-replacing presets) | PR #1858 opened; domain converted from 12 radios to 9 derived facet chips (Biological/Social/Cultural carried by 0 of 12 mechanisms, removed per derive-dont-declare); union counts verified monotonic and non-additive (Affect 9 OR Risk 4 = 10); zero-yield options render as focusable dead ends, never on an already-selected option; Pattern group evicted from the sheet to AnswerSuggestionChips (all 5 presets, old slice(0,4) left one unreachable); ResultFilterFacetChips exported so desktop rail and sheet share one renderer; desktop select of 13 retired. Shares result-filter-control.tsx with PR #1857 - land #1857 first, its accessible-name fix then covers these chips | verify:pr-local failed:(none) not reached:(none), all 15 steps green including build with the server stopped; full unit suite 558/558 files, 6101 passed 4 skipped, zero failures; formulation.test.ts 11 passed with 3 new contract tests; bundle-budget production 1296.1 KiB and mockups 285.1 KiB within tolerance on a freshness-verified build; browser proof 1440/390/320px, 0px overflow, 9 chips not 12, 0 selects, 5 suggestion chips, live dead-end-to-selectable transition on union widening, phone sheet radiogroup count 0 | diff --git a/docs/outstanding-issues.md b/docs/outstanding-issues.md index b8fb20422a..67556e148d 100644 --- a/docs/outstanding-issues.md +++ b/docs/outstanding-issues.md @@ -81,64 +81,60 @@ removed after current-main verification; it is not missing recommended work. | 26 | `#162` | A3 | High — frontend/UI | When starting the mode search redesign package | 0.5–1.5 days | Redesign `/tools?q=` as Compact Results Instrument (direction A): query-as-H1, one composer, dense tool rows, demote cross-mode cards, remove success-green filter banner and home hero on results. Comps in `public/mockups/mode-page-redesign-2026-07/tools-search/`. Verify phone+desktop chrome ownership and `verify:phone-chrome` / focused UI. Stop if scope expands into Tools home redesign without an explicit ask. | | 27 | `#163` | A3 | High — frontend/UI | After or with `#162` | 0.5–1.5 days | Redesign `/services?q=` as Progressive Referral Workflow (direction B): H1 = query (not match count), progressive shortlist/compare (no always-on decision panel or giant step rail). Comps in `public/mockups/mode-page-redesign-2026-07/services-search/`. Verify referral shortlist still works; stop before changing Services home ModeHome. | | 28 | `#164` | A3 | High — frontend/UI | Product confirmed Favourites is hybrid dashboard+search (no ModeHome) | 1–2 days | Redesign Favourites as one dashboard + search page: recommended Search-Led Workspace (direction B) — persistent search, sets as chips, Continue + recent + table on empty query, in-place filter on typed query. Comps in `public/mockups/mode-page-redesign-2026-07/favourites-hybrid/`. Do not reintroduce ModeHome for Favourites. Verify desktop+phone; stop before splitting into separate ModeHome routes. | -| 29 | `#202` | A3 | High — agent process | Next issues-skill touch | 30–60 min | Require recommendation/`/issues` answers to revalidate against `origin/main`'s ledger (or state checkout lag). Prevents re-proposing closed work from stale worktrees. | -| 30 | `#090` | A3 | High — eslint toolchain | When ESLint 10 plugin peers are compatible | blocked; revisit monthly | Upgrade the eslint ecosystem to clear remaining dev-scoped high advisories — full `npm audit` reports zero high advisories from the eslint toolchain. | -| 31 | `#100` | A3 | Specialist — answer streaming | After offline Phase 0/1 design proof | provider-gated rollout | Buffered answer generation has no incremental verified delivery — [`verified-answer-incremental-delivery-design.md`](verified-answer-incremental-delivery-design.md) records the clinical-governance decision and staged co… | -| 32 | `#150` | Optional | Operator — review tooling | Next CodeRabbit billing/policy decision | 30–60 min decision | CodeRabbit reviewed none of a full day's PRs; spending cap reached — the repo's second automated reviewer is either funded or acknowledged as absent, rather than appearing to review while skipping. | -| 33 | `#152` | A2 | High — worktree hygiene | Next cleanup batch with #079 | 1–2 hours | Uncommitted work sits in worktrees whose branches are already merged — work that exists in no branch and no PR is either committed or knowingly discarded, not lost to a disk reclaim. | -| 34 | `#155` | A2 | High — agent process | Standing rule; next multi-agent session | process change | Several agent sessions edit the same branch and ledger concurrently — concurrent sessions stop silently undoing each other on shared `claude/*` branches and on this file. | -| 35 | `#165` | A2 | High — clinical UI | Next answer-home UX pass | 0.5–1 day | Adopt a consolidated answer-home notice block — the studies exist, nothing adopts them — the answer hero states its safety obligation, its scope, and its verification requirement as one block in one voice. | -| 36 | `#168` | A3 | High — ledger architecture | With #156 / id-scheme redesign | design first | Sequential issue ids force every concurrent append to conflict — two sessions can append to this ledger at the same time without conflicting. | -| 37 | `#169` | A3 | High — git hygiene | Next branch cleanup batch | 1–2 hours | Local branches carry work that exists on no remote — committed work is not lost when a machine or worktree is reclaimed. | -| 38 | `#170` | A2 | High — phone UI | Next documents/filter phone pass | 0.5–1 day | Documents and therapy already have page-owned phone filter sheets; remaining modes still use inline controls — shared-band Filter+Sheet adoption without regressing those two or sheetless Sort. | -| 39 | `#175` | A2 | Operator — clinical data + Standard | Next therapy catalogue curation window | 2–4 hours | Therapy modality is now null on all 205 records and needs curation or removal — the Therapy detail and recommend screens either show a curated modality or stop carrying the field at all. | -| 40 | `#178` | A3 | High — PR policy | Next pr-policy change | 1–2 hours | pr-policy does not flag operational risk bundled with clinical or UI risk — a PR that mixes operational-risk paths with clinical or UI risk is called out before it merges, because squash-merging that mix destroys per-it… | -| 41 | `#189` | A2 | Specialist — search/RAG budgets | After #098 route residual; before collapsing RPCs | 2–4 hours + canary if behaviour | Pin /api/search route-level round trips and disposition the x3 text RPC probes — a counting-proxy budget drives `POST` `/api/search` (auth/ratelimit/scope/enrichment/telemetry), and the retrieval-core finding that `matc… | -| 42 | `#036` | Optional | Specialist — privacy/schema | When visibility model is redesigned | design + migration | No explicit `is_public` visibility flag on documents — Public-corpus visibility is implicit: `owner_id IS NULL` on an `indexed` document (`resolveSearchScope`). The `metadata.public_corpus` marker is written by the prom… | -| 43 | `#101` | A3 | Specialist — RAG/retrieval | After #098 harness + canary approval | canary-gated | Canary-gated retrieval parallelisation candidates — metadata and memory hydration shipped in PR #1474; visual hydration, scope enumeration, typeahead caching, and universal-search coalescing remain, each behind the RAG flag and live-canary criteria. | -| 44 | `#156` | A3 | High — ledger architecture | With #168 id-scheme work | design first | Outstanding-issues ids are still allocated read-modify-write, and Update-branch corrupts the merge — two branches cannot silently claim the same outstanding-issues id, and no merge path can commit a file where they have. | -| 45 | `#177` | A3 | High — therapy catalogue build | Next therapy-index build change | 1–2 hours | Therapy catalogue aliases duplicate 2.53 MB of bytes instead of pointing at the hashed file — the unversioned catalogue aliases stop costing a second copy of every payload in the repo and the image. | -| 46 | `#180` | A3 | High — therapy catalogue build | With #177/#179 | 1–2 hours | build-therapies-index now overwrites its own source input — the therapy catalogue generator has a source it does not also destroy. | -| 47 | `#188` | A3 | Operator — DR/SRE | After any schema restore drill, or next DR review | checklist-owned | Document and track disaster-recovery re-creation checklist as ledger work — the five DR items that do not survive a schema restore are tracked with owners and verify steps, not only in `docs/operator-backlog.md`. | -| 48 | `#190` | A3 | Specialist — RAG structure | On explicit X3 go-ahead | 1 PR per extraction unit | X3: Finish rag.ts monolith decomposition — `src/lib/rag/rag.ts` is decomposed into focused modules per `docs/maturity-backlog-workorders.md` X3, with existing offline RAG contracts green. | -| 49 | `#191` | A3 | Operator — DB + Specialist | Approved live-DB window only | provider-gated | X5: ACL-migration consolidation (provider-gated) — ACL-related migrations are consolidated per maturity work-order X5 without weakening owner-scope/RLS. | -| 50 | `#192` | A3 | High — test coverage | Next coverage-floor pass | 0.5–1 day | X6: Raise clinical/retrieval/answer coverage floors — coverage floors for clinical, retrieval, and answer domains meet the maturity X6 targets with CI enforcing them. | -| 51 | `#193` | A3 | High — src/lib structure | After/with X3 non-protected clusters | 1 PR per cluster | X7: Complete the remaining src/lib domain-directory reorg — remaining `src/lib` clusters sit in their domain directories per X7 follow-on to X2. | -| 52 | `#194` | A3 | High — scripts/docs hygiene | Next scripts archive pass | 1–2 hours | L1: Archive retired backfill one-shots and dead ci-change-scope token — retired `backfill:*` one-shots and the dead `ci-change-scope` token are archived/removed with docs/script index updated. | -| 53 | `#195` | A3 | Operator — GitHub maintainer | Maintainer UI window | 30–60 min | M1: Repo-host hardening (branch protection and required checks) — GitHub branch-protection rulesets and required checks match audit §8 / maturity M1. | -| 54 | `#196` | A3 | Operator — DR/SRE | After schema restore drill | 1–2 hours | DR: Re-create pg_cron schedules after schema restore — ingestion/retention and related pg_cron schedules exist on the target DB after any schema restore. | -| 55 | `#197` | A3 | Operator — DR/SRE | After schema restore drill | 30–60 min | DR: Re-add Vault secrets including cron_ingestion_jwt — required Vault secrets (at least `cron_ingestion_jwt`) are present after schema restore. | -| 56 | `#198` | A3 | Operator — DR/SRE | After schema restore drill | 30–60 min | DR: Re-set custom database GUCs after schema restore — custom `app.*` GUCs required by the app/worker are set on the restored database. | -| 57 | `#199` | A3 | Operator — DR/SRE | After schema restore; Deno v2 available | 1–2 hours | DR: Redeploy Supabase edge functions (Deno v2.x) — required edge functions are deployed to the target project with Deno v2.x. | -| 58 | `#200` | A3 | Operator — DR/SRE | After schema restore drill | 1–2 hours | DR: Re-enter dashboard config after schema restore — auth providers/SSO redirect URLs, connection-pool caps, per-project keys, and `E2E_USER_*` are re-entered in the Supabase/Railway dashboards after restore. | -| 59 | `#183` | A2 | Operator — Sentry + Specialist | Next approved observability window with SENTRY_AUTH_TOKEN | 1–2 hours | Create Sentry metric alert for production DB span p95 > 500ms (`span.op:db`, environment production). **Stop:** no secret printing; blocked until token/env available. | -| 60 | `#206` | A2 | Specialist — answer UI contract | With AnswerState producer work (`#207`) | 2–4 hours | `partial_retrieval` has no app-facing producer — decide RAG contract vs UI-only mapping before AnswerCard. **Stop:** no retrieval behaviour change without RAG flag. | -| 61 | `#209` | A3 | High — design tokens / contrast | Next Gate 1 / warning-token pass | 1–2 hours | Add contrast pair for `--warning` used as body text (VerificationNotice / DoseLine). **Gate:** design-system contrast checks. **Stop:** do not invent a new status token without TOKENS.md. | -| 62 | `#211` | A3 | High — TypeScript strictness | Dedicated migration branch | multi-PR | Plan and start `noUncheckedIndexedAccess` migration (1266 errors); highest-risk files first. **Stop:** do not flip the flag on main without a staged plan. | -| 63 | `#212` | A3 | High — runtime validation | After highest-risk cast inventory | multi-PR | Replace `as unknown as` and unvalidated `JSON.parse` with Zod/guards at trust boundaries. **Stop:** RAG/provider boundaries need clinical/privacy care. | -| 64 | `#213` | A3 | High — error handling | Next fetch/stream hardening pass | 0.5–1 day | Stop swallowing fetch/stream errors with empty catches; check `response.ok`. **Stop:** do not change telemetry contracts silently. | -| 65 | `#215` | Optional | High — image perf | Next image/PWA pass | 2–4 hours | Image-optimization basics for lightbox, PWA lifecycle, demo PNGs. **Stop:** optional until measured need. | -| 66 | `#221` | A3 | High — design-system convergence | After `#218` cn() decision | 0.5–1 day | Converge remaining local EmptyState/LoadingState/Chip duplicates. **Stop:** not piecemeal before cn()/Chip decisions. | -| 67 | `#222` | A3 | High — headers / search chrome | During headers redesign decision | 2–4 hours | Decide whether mode-home-template / search-results-header-band are in PageHeader scope or permanently out. **Stop:** do not flatten phone composer ownership. | -| 68 | `#233` | A3 | High — design-system docs | Next COMPONENTS.md docs PR | 1–2 hours | Refresh section 0 maturity matrix and document FormField optionality-marker contract. **Gate:** docs checks. **Stop:** docs-only; no product behaviour change. | -| 69 | `#234` | A3 | High — design-system docs | With answer-surface docs | 30–60 min | Document `answer-copy-payload.ts` as the clipboard contract for three surfaces. **Stop:** do not add a second copy builder. | -| 70 | `#235` | A3 | High — design-system evidence | Next warmed local proof-shot pass | 1–2 hours | Capture missing ADOPTION.md §7 proof shots for adopted surfaces. **Stop:** not visual-baseline PNGs (`#118`); no Playwright snapshot commit. | -| 71 | `#236` | Optional | High — branch hygiene | Next cleanup batch with `#079` | 30–60 min | Dispose orphan DS V2 builder branches and leftover wave-5 dev servers. **Stop:** content-verify before delete; no force-clean. | -| 72 | `#237` | A3 | High — design-system a11y | Before freezing Linux visual baselines (#242) | 30–60 min | Eyeball low-confidence AccessibleTable densities at 320px; MissingValue phrases must remain readable. **Gate:** visual spot-check only. **Stop:** do not abbreviate MissingValue to a dash. | -| 73 | `#238` | A3 | High — overlays/UI | After Sheet portal default change (#1616) | 30–60 min | Visual pass for Sheet portal default on settings, sidebar, and answer overlays under OverlayRoot. **Stop:** do not revert portal default without evidence. | -| 74 | `#239` | Optional | High — phone chrome | When phone orientation QA is available | 15–30 min | Manual phone rotation check for ResizeObserver-only phone chrome reserve. **Gate:** `verify:phone-chrome` still owns automated coverage. **Stop:** do not widen reserve heuristics without reproduction. | -| 75 | `#240` | Optional | High — design tokens | Next design-owner review | 15–30 min | Confirm tooltip visual hard-clip asymmetry with design owner (sr-only keeps full text). **Stop:** no product change without that confirmation. | -| 76 | `#241` | A3 | High — therapy catalogue | Standing; with any therapy-home change | 15–30 min | Therapy home summary count/slugs remain build-time; keep `build-therapies-index --check` load-bearing. **Stop:** do not bypass the check. | -| 77 | `#242` | A2 | High — design-system baselines | After human review of Linux baselines | 1–2 hours | Commit approved Linux visual baselines and promote adoption not-committed → committed. **Stop:** never commit baselines from an unreviewed machine run. | -| 78 | `#244` | A3 | High — design tokens / forced-colors | With any ckb-v2 forced-colours edit | 15–30 min | Keep grouped dark selectors in the forced-colours media block so specificity matches dark rules. **Stop:** do not trim to a single `.ckb-v2.ckb-v2` selector. | -| 79 | `#245` | A3 | High — cross-mode links | Next CrossModeLinks / analytics pass | 30–60 min | responsive-compact CrossModeLinks keeps duplicate rails in the DOM; prefer one mount or accept test double-counts. **Stop:** do not break phone-only rail contract. | -| 80 | `#248` | A2 | Operator — Supabase + Specialist | After PR #1614 symptom repair; approved live/history window | 1–2 hours | Investigate why 20260705180000 search-health indexes were missing on live despite applied history; decide if drift checks should catch this class. **Stop:** no hosted mutation without approval. | -| 81 | `#249` | A3 | High — agent process | Next issues-skill / plan touch | 1–2 hours | Extend issues/plan with an agent-safe wins classifier (optional filter; no new skill unless reused thrice). **Stop:** do not outrank A1 operator work. | -| 82 | `#250` | A2 | High — multi-agent execution | After Wave 0 queue repair on main (done in this capture); run remaining Wave 0/#202 process gates next on the engineering track | multi-wave | Execute the fastest-wins multi-wave plan (Waves 0–4 + operator track) with parallel agents and per-PR gates. Waves do not outrank A1 acuity. **Stop:** provider/RAG approvals still required where flagged. | -| 83 | `#251` | Optional | High — agent process | Next handoff/gates doc touch | 15–30 min | Handoff checklist pairs gates skill with verification-router; paste decisive proof line. **Stop:** do not stack broad gates by default. | -| 84 | `#253` | A2 | High — phone results UI | Next open-PR sweep | 15–30 min | Decide #1606's fate: the `MobileResultFilterControl` it rewrites was deleted by #247, so there is nothing left to hand-merge. Verify keyboard parity of the replacement sheet on a real device, then close #1606 as superseded. **Stop:** the decision is a human's; do not close #1606 automatically. | -| 85 | `#254` | A2 | Operator — Codex Cloud | Before #1617 leaves draft | 1–2 hours | Re-run Codex Cloud acceptance at the exact current head or mark head-independent evidence. **Stop:** do not treat stale pins as coverage. | -| 86 | `#257` | Optional | High — formulation/specifiers flake | Standing until second reproduction | 15–30 min | Single unreproduced ui-formulation flake when run with ui-specifiers — record a second sighting only; do not quarantine until three on the same SHA. **Stop:** do not weaken assertions. | +| 29 | `#090` | A3 | High — eslint toolchain | When ESLint 10 plugin peers are compatible | blocked; revisit monthly | Upgrade the eslint ecosystem to clear remaining dev-scoped high advisories — full `npm audit` reports zero high advisories from the eslint toolchain. | +| 30 | `#100` | A3 | Specialist — answer streaming | After offline Phase 0/1 design proof | provider-gated rollout | Buffered answer generation has no incremental verified delivery — [`verified-answer-incremental-delivery-design.md`](verified-answer-incremental-delivery-design.md) records the clinical-governance decision and staged co… | +| 31 | `#150` | Optional | Operator — review tooling | Next CodeRabbit billing/policy decision | 30–60 min decision | CodeRabbit reviewed none of a full day's PRs; spending cap reached — the repo's second automated reviewer is either funded or acknowledged as absent, rather than appearing to review while skipping. | +| 32 | `#152` | A2 | High — worktree hygiene | Next cleanup batch with #079 | 1–2 hours | Uncommitted work sits in worktrees whose branches are already merged — work that exists in no branch and no PR is either committed or knowingly discarded, not lost to a disk reclaim. | +| 33 | `#165` | A2 | High — clinical UI | Next answer-home UX pass | 0.5–1 day | Adopt a consolidated answer-home notice block — the studies exist, nothing adopts them — the answer hero states its safety obligation, its scope, and its verification requirement as one block in one voice. | +| 34 | `#168` | A3 | High — ledger architecture | With #156 / id-scheme redesign | design first | Sequential issue ids force every concurrent append to conflict — two sessions can append to this ledger at the same time without conflicting. | +| 35 | `#169` | A3 | High — git hygiene | Next branch cleanup batch | 1–2 hours | Local branches carry work that exists on no remote — committed work is not lost when a machine or worktree is reclaimed. | +| 36 | `#170` | A2 | High — phone UI | Next documents/filter phone pass | 0.5–1 day | Documents and therapy already have page-owned phone filter sheets; remaining modes still use inline controls — shared-band Filter+Sheet adoption without regressing those two or sheetless Sort. | +| 37 | `#175` | A2 | Operator — clinical data + Standard | Next therapy catalogue curation window | 2–4 hours | Therapy modality is now null on all 205 records and needs curation or removal — the Therapy detail and recommend screens either show a curated modality or stop carrying the field at all. | +| 38 | `#178` | A3 | High — PR policy | Next pr-policy change | 1–2 hours | pr-policy does not flag operational risk bundled with clinical or UI risk — a PR that mixes operational-risk paths with clinical or UI risk is called out before it merges, because squash-merging that mix destroys per-it… | +| 39 | `#189` | A2 | Specialist — search/RAG budgets | After #098 route residual; before collapsing RPCs | 2–4 hours + canary if behaviour | Pin /api/search route-level round trips and disposition the x3 text RPC probes — a counting-proxy budget drives `POST` `/api/search` (auth/ratelimit/scope/enrichment/telemetry), and the retrieval-core finding that `matc… | +| 40 | `#036` | Optional | Specialist — privacy/schema | When visibility model is redesigned | design + migration | No explicit `is_public` visibility flag on documents — Public-corpus visibility is implicit: `owner_id IS NULL` on an `indexed` document (`resolveSearchScope`). The `metadata.public_corpus` marker is written by the prom… | +| 41 | `#101` | A3 | Specialist — RAG/retrieval | After #098 harness + canary approval | canary-gated | Canary-gated retrieval parallelisation candidates — metadata and memory hydration shipped in PR #1474; visual hydration, scope enumeration, typeahead caching, and universal-search coalescing remain, each behind the RAG flag and live-canary criteria. | +| 42 | `#156` | A3 | High — ledger architecture | With #168 id-scheme work | design first | Outstanding-issues ids are still allocated read-modify-write, and Update-branch corrupts the merge — two branches cannot silently claim the same outstanding-issues id, and no merge path can commit a file where they have. | +| 43 | `#177` | A3 | High — therapy catalogue build | Next therapy-index build change | 1–2 hours | Therapy catalogue aliases duplicate 2.53 MB of bytes instead of pointing at the hashed file — the unversioned catalogue aliases stop costing a second copy of every payload in the repo and the image. | +| 44 | `#180` | A3 | High — therapy catalogue build | With #177/#179 | 1–2 hours | build-therapies-index now overwrites its own source input — the therapy catalogue generator has a source it does not also destroy. | +| 45 | `#188` | A3 | Operator — DR/SRE | After any schema restore drill, or next DR review | checklist-owned | Document and track disaster-recovery re-creation checklist as ledger work — the five DR items that do not survive a schema restore are tracked with owners and verify steps, not only in `docs/operator-backlog.md`. | +| 46 | `#190` | A3 | Specialist — RAG structure | On explicit X3 go-ahead | 1 PR per extraction unit | X3: Finish rag.ts monolith decomposition — `src/lib/rag/rag.ts` is decomposed into focused modules per `docs/maturity-backlog-workorders.md` X3, with existing offline RAG contracts green. | +| 47 | `#191` | A3 | Operator — DB + Specialist | Approved live-DB window only | provider-gated | X5: ACL-migration consolidation (provider-gated) — ACL-related migrations are consolidated per maturity work-order X5 without weakening owner-scope/RLS. | +| 48 | `#192` | A3 | High — test coverage | Next coverage-floor pass | 0.5–1 day | X6: Raise clinical/retrieval/answer coverage floors — coverage floors for clinical, retrieval, and answer domains meet the maturity X6 targets with CI enforcing them. | +| 49 | `#193` | A3 | High — src/lib structure | After/with X3 non-protected clusters | 1 PR per cluster | X7: Complete the remaining src/lib domain-directory reorg — remaining `src/lib` clusters sit in their domain directories per X7 follow-on to X2. | +| 50 | `#194` | A3 | High — scripts/docs hygiene | Next scripts archive pass | 1–2 hours | L1: Archive retired backfill one-shots and dead ci-change-scope token — retired `backfill:*` one-shots and the dead `ci-change-scope` token are archived/removed with docs/script index updated. | +| 51 | `#195` | A3 | Operator — GitHub maintainer | Maintainer UI window | 30–60 min | M1: Repo-host hardening (branch protection and required checks) — GitHub branch-protection rulesets and required checks match audit §8 / maturity M1. | +| 52 | `#196` | A3 | Operator — DR/SRE | After schema restore drill | 1–2 hours | DR: Re-create pg_cron schedules after schema restore — ingestion/retention and related pg_cron schedules exist on the target DB after any schema restore. | +| 53 | `#197` | A3 | Operator — DR/SRE | After schema restore drill | 30–60 min | DR: Re-add Vault secrets including cron_ingestion_jwt — required Vault secrets (at least `cron_ingestion_jwt`) are present after schema restore. | +| 54 | `#198` | A3 | Operator — DR/SRE | After schema restore drill | 30–60 min | DR: Re-set custom database GUCs after schema restore — custom `app.*` GUCs required by the app/worker are set on the restored database. | +| 55 | `#199` | A3 | Operator — DR/SRE | After schema restore; Deno v2 available | 1–2 hours | DR: Redeploy Supabase edge functions (Deno v2.x) — required edge functions are deployed to the target project with Deno v2.x. | +| 56 | `#200` | A3 | Operator — DR/SRE | After schema restore drill | 1–2 hours | DR: Re-enter dashboard config after schema restore — auth providers/SSO redirect URLs, connection-pool caps, per-project keys, and `E2E_USER_*` are re-entered in the Supabase/Railway dashboards after restore. | +| 57 | `#183` | A2 | Operator — Sentry + Specialist | Next approved observability window with SENTRY_AUTH_TOKEN | 1–2 hours | Create Sentry metric alert for production DB span p95 > 500ms (`span.op:db`, environment production). **Stop:** no secret printing; blocked until token/env available. | +| 58 | `#206` | A2 | Specialist — answer UI contract | With AnswerState producer work (`#207`) | 2–4 hours | `partial_retrieval` has no app-facing producer — decide RAG contract vs UI-only mapping before AnswerCard. **Stop:** no retrieval behaviour change without RAG flag. | +| 59 | `#209` | A3 | High — design tokens / contrast | Next Gate 1 / warning-token pass | 1–2 hours | Add contrast pair for `--warning` used as body text (VerificationNotice / DoseLine). **Gate:** design-system contrast checks. **Stop:** do not invent a new status token without TOKENS.md. | +| 60 | `#211` | A3 | High — TypeScript strictness | Dedicated migration branch | multi-PR | Plan and start `noUncheckedIndexedAccess` migration (1266 errors); highest-risk files first. **Stop:** do not flip the flag on main without a staged plan. | +| 61 | `#212` | A3 | High — runtime validation | After highest-risk cast inventory | multi-PR | Replace `as unknown as` and unvalidated `JSON.parse` with Zod/guards at trust boundaries. **Stop:** RAG/provider boundaries need clinical/privacy care. | +| 62 | `#213` | A3 | High — error handling | Next fetch/stream hardening pass | 0.5–1 day | Stop swallowing fetch/stream errors with empty catches; check `response.ok`. **Stop:** do not change telemetry contracts silently. | +| 63 | `#215` | Optional | High — image perf | Next image/PWA pass | 2–4 hours | Image-optimization basics for lightbox, PWA lifecycle, demo PNGs. **Stop:** optional until measured need. | +| 64 | `#221` | A3 | High — design-system convergence | After `#218` cn() decision | 0.5–1 day | Converge remaining local EmptyState/LoadingState/Chip duplicates. **Stop:** not piecemeal before cn()/Chip decisions. | +| 65 | `#222` | A3 | High — headers / search chrome | During headers redesign decision | 2–4 hours | Decide whether mode-home-template / search-results-header-band are in PageHeader scope or permanently out. **Stop:** do not flatten phone composer ownership. | +| 66 | `#233` | A3 | High — design-system docs | Next COMPONENTS.md docs PR | 1–2 hours | Refresh section 0 maturity matrix and document FormField optionality-marker contract. **Gate:** docs checks. **Stop:** docs-only; no product behaviour change. | +| 67 | `#234` | A3 | High — design-system docs | With answer-surface docs | 30–60 min | Document `answer-copy-payload.ts` as the clipboard contract for three surfaces. **Stop:** do not add a second copy builder. | +| 68 | `#235` | A3 | High — design-system evidence | Next warmed local proof-shot pass | 1–2 hours | Capture missing ADOPTION.md §7 proof shots for adopted surfaces. **Stop:** not visual-baseline PNGs (`#118`); no Playwright snapshot commit. | +| 69 | `#236` | Optional | High — branch hygiene | Next cleanup batch with `#079` | 30–60 min | Dispose orphan DS V2 builder branches and leftover wave-5 dev servers. **Stop:** content-verify before delete; no force-clean. | +| 70 | `#237` | A3 | High — design-system a11y | Before freezing Linux visual baselines (#242) | 30–60 min | Eyeball low-confidence AccessibleTable densities at 320px; MissingValue phrases must remain readable. **Gate:** visual spot-check only. **Stop:** do not abbreviate MissingValue to a dash. | +| 71 | `#238` | A3 | High — overlays/UI | After Sheet portal default change (#1616) | 30–60 min | Visual pass for Sheet portal default on settings, sidebar, and answer overlays under OverlayRoot. **Stop:** do not revert portal default without evidence. | +| 72 | `#239` | Optional | High — phone chrome | When phone orientation QA is available | 15–30 min | Manual phone rotation check for ResizeObserver-only phone chrome reserve. **Gate:** `verify:phone-chrome` still owns automated coverage. **Stop:** do not widen reserve heuristics without reproduction. | +| 73 | `#240` | Optional | High — design tokens | Next design-owner review | 15–30 min | Confirm tooltip visual hard-clip asymmetry with design owner (sr-only keeps full text). **Stop:** no product change without that confirmation. | +| 74 | `#241` | A3 | High — therapy catalogue | Standing; with any therapy-home change | 15–30 min | Therapy home summary count/slugs remain build-time; keep `build-therapies-index --check` load-bearing. **Stop:** do not bypass the check. | +| 75 | `#242` | A2 | High — design-system baselines | After human review of Linux baselines | 1–2 hours | Commit approved Linux visual baselines and promote adoption not-committed → committed. **Stop:** never commit baselines from an unreviewed machine run. | +| 76 | `#244` | A3 | High — design tokens / forced-colors | With any ckb-v2 forced-colours edit | 15–30 min | Keep grouped dark selectors in the forced-colours media block so specificity matches dark rules. **Stop:** do not trim to a single `.ckb-v2.ckb-v2` selector. | +| 77 | `#245` | A3 | High — cross-mode links | Next CrossModeLinks / analytics pass | 30–60 min | responsive-compact CrossModeLinks keeps duplicate rails in the DOM; prefer one mount or accept test double-counts. **Stop:** do not break phone-only rail contract. | +| 78 | `#248` | A2 | Operator — Supabase + Specialist | After PR #1614 symptom repair; approved live/history window | 1–2 hours | Investigate why 20260705180000 search-health indexes were missing on live despite applied history; decide if drift checks should catch this class. **Stop:** no hosted mutation without approval. | +| 79 | `#250` | A2 | High — multi-agent execution | After Wave 0 queue repair on main (done in this capture); run remaining Wave 0/#202 process gates next on the engineering track | multi-wave | Execute the fastest-wins multi-wave plan (Waves 0–4 + operator track) with parallel agents and per-PR gates. Waves do not outrank A1 acuity. **Stop:** provider/RAG approvals still required where flagged. | +| 80 | `#253` | A2 | High — phone results UI | Next open-PR sweep | 15–30 min | Decide #1606's fate: the `MobileResultFilterControl` it rewrites was deleted by #247, so there is nothing left to hand-merge. Verify keyboard parity of the replacement sheet on a real device, then close #1606 as superseded. **Stop:** the decision is a human's; do not close #1606 automatically. | +| 81 | `#254` | A2 | Operator — Codex Cloud | Before #1617 leaves draft | 1–2 hours | Re-run Codex Cloud acceptance at the exact current head or mark head-independent evidence. **Stop:** do not treat stale pins as coverage. | +| 82 | `#257` | Optional | High — formulation/specifiers flake | Standing until second reproduction | 15–30 min | Single unreproduced ui-formulation flake when run with ui-specifiers — record a second sighting only; do not quarantine until three on the same SHA. **Stop:** do not weaken assertions. | @@ -191,7 +187,6 @@ removed after current-main verification; it is not missing recommended work. | #150 | P2 | issue | CodeRabbit reviewed none of a full day's PRs; spending cap reached | IN FLIGHT 2026-08-12 in PR #1836 (finalize tooling follow-through notes). Checked against the open-PR list during the full ledger sweep. Do NOT start this row while that PR is open — duplicating a queued conversion is the exact failure #292 records, and it has happened twice. Re-verify this row against main after that PR merges, and close it there rather than here. **Outcome:** the repo's second automated reviewer is either funded or acknowledged as absent, rather than appearing to review while skipping. **Evidence 2026-07-30:** CodeRabbit posted "Review limit reached … Your organization has reached its usage spending cap" on **every** PR opened that day — #1404, #1430, #1444, #1445, #1479 — reviewing none of them. Each notice renders as an ordinary bot comment, so a skimming reader sees reviewer activity where there was no review. The Codex connector was the sole substantive reviewer across those PRs and found three real defects that had survived local gates and self-review: a proxy-variable inference in #1430, an `unset` vs `unspecified` git-attribute conflation in #1444, and an earlier P1 recursive-delete on an unvalidated `--dir`. **Next:** decide whether to raise the cap, switch to label-based opt-in so the budget lands on PRs that need it, or accept single-reviewer coverage explicitly. **ESCALATED 2026-07-30 — both reviewers are now capped, so this row's premise no longer holds.** The analysis above rests on the Codex connector being the surviving reviewer. On PR #1505 the Codex connector posted "You have reached your Codex usage limits for code reviews" while CodeRabbit posted its own spending-cap notice on the same PR. **That PR therefore received zero automated review**, and so will anything opened while both caps hold. This is not a second issue — it is the same one, with the fallback removed. **Why it is worth more than a status note:** on 2026-07-30 the single Codex finding on PR #1459 was correct and changed the outcome — it showed that a claimed `LoadingPanel` verification had matched `ModeHomePageSkeleton` instead, which caused `#105` to be closed on wrong evidence. Local gates did not catch it and neither did self-review; the review did. A window in which neither reviewer runs is a window in which that class of error lands. **Next:** the three options above now need deciding rather than deferring, because "accept single-reviewer coverage" is no longer one of them. Until then, treat any PR merged during a cap window as locally-gated only. **Stop:** do not read a CodeRabbit *or* Codex comment as a completed review without checking it is not a usage-limit notice — during this window both bots posted comments on every PR while reviewing none of them. | PRs #1404/#1430/#1444/#1445/#1479; `.coderabbit.yaml` | 2026-07-30 | | #152 | P2 | issue | Uncommitted work sits in worktrees whose branches are already merged | **Outcome:** work that exists in no branch and no PR is either committed or knowingly discarded, not lost to a disk reclaim. **Inventory 2026-07-30**, all from worktrees whose pre-snapshot branch tips were fully merged into `origin/main`, so the uncommitted changes existed nowhere else: `codex/reconcile-immediate-20260730` — 21 files, +395/-200 across 19 tracked, including `.github/workflows/ci.yml`, `package.json` and `docs/scripts-index.md`; `codex/document-results-mockup-20260730` — 8 files (+13/-3 tracked) plus an untracked `document-search-results/page.tsx` under `src/app/mockups/` (named without a full path here because it does not resolve in this repo); `codex/chat-ledger-triage-d344` — `docs/outstanding-issues.md` +59/-61; `claude/section-spy-browser-coverage` — `tests/ui-smoke.spec.ts` +51. A fifth (`claude/frosty-mayer-2c6167`) self-resolved to clean during the session. **Preserved 2026-07-30, not reviewed:** each was committed on its own branch as an unpushed `wip: preserve uncommitted work before worktree cleanup` snapshot, so the work now survives a worktree reclaim — `codex/reconcile-immediate-20260730` `748ef018f`, `codex/document-results-mockup-20260730` `5dbd9f965`, `codex/chat-ledger-triage-d344` `b7eae51a4`, `claude/section-spy-browser-coverage` `d949859c3`. All four worktrees are now clean. None is pushed and none is reviewed or verified; the snapshots exist to stop silent loss, not to endorse the content. First captured in PR #1490, which was closed unmerged; re-landed on `main` by PR #1508. **Next:** per snapshot, review and either promote it to a real branch/PR or `git reset --hard HEAD~1` to drop it. Do not bulk-delete worktrees without this check — it is why only one of the two "safe" candidates was removed in the 2026-07-30 cleanup. NOT VERIFIABLE FROM A CLOUD SESSION (checked 2026-08-12): this row describes machine-local git or process state. Claude Code on the web runs in a container cloned fresh at session start, so it reports 1 worktree, 0 upstream-less branches and no running dev servers no matter what is true on the machine that raised this. Do NOT close this row from a cloud session — that reading is an artifact of the container, not evidence. Verify from the originating machine. | session 2026-07-30 worktree cleanup; PR #1490 (closed); PR #1508 | 2026-07-30 | | #156 | P3 | issue | Outstanding-issues ids are still allocated read-modify-write, and Update-branch corrupts the merge | **Outcome:** two branches cannot silently claim the same outstanding-issues id, and no merge path can commit a file where they have. **Detail:** Residual of archived `#112` (gate landed; underlying read-modify-write race explicitly left open) plus post-`#133` evidence. `#133` fixed the two causes of *conflict frequency* — `#1444` removed `merge=union` and `#1479` excluded the ledger from Prettier so a maximum-width row stops re-padding the whole table. Neither touches **id allocation**, which is still read-modify-write against the `issues:next-id` marker, so two branches open at the same time still pick the same number. Measured on PR #1451 (2026-07-30): one P3 row was renumbered `#135` -> `#141` -> `#145` -> `#147` -> `#149` across four sync cycles, because `main` had taken each id in turn — every renumber was manual. This capture itself demonstrates the same hazard: first written as `#151` on PR #1506, then `#154` / `#155` after earlier main syncs, then `#156` here because `main` had already taken `#154` and `#155` for unrelated rows. Both renumbers happened *after* `#133` was closed, which is the point: the fixes in `#1444` and `#1479` were real, but they were fixes to conflict frequency, and allocation was never the same problem. The sharper finding is the resolution path: the GitHub **Update branch** button pushed a sync to that PR head (`df3f3aeed`) whose auto-merge produced **two rows numbered `#141` and two `next-id` markers**, leaving the marker at `142` — below `main`'s highest id, so the next allocation would have reused a live number. `git merge` reported success; only `npm run check:outstanding-issues` caught it. That guard runs in `verify:cheap` and `static-pr`, so such a head cannot merge — but the corruption is produced by a one-click path that runs no guard, and the cost lands on whoever notices. A second session on the same branch later dropped an entire appended evidence block while resolving this file, which the guard cannot detect at all: it validates ids and structure, not whether a merge kept both sides' prose. **Next:** cheapest first — document that Update branch must not be used on PRs touching this file (prefer `npm run sync:pr-branches:apply`, which the repo already prefers for other reasons), then consider allocating ids from a source that cannot collide (per-row files, or a date-plus-slug id) so concurrent branches never contend. **Stop:** do not reintroduce a merge driver here — `#133` settled that; this is about allocation and about merges that silently drop rows, not about the driver. Do not reopen archived `#112` — keep the gate outcome there and track the residual race here. | PR #1451 sync cycles; `df3f3aeed`; archived `#112`; session 2026-07-30; PR #1506 | 2026-07-31 | -| #155 | P2 | rec | Several agent sessions edit the same branch and ledger concurrently | IN FLIGHT 2026-08-12 in PR #1840 (harden agent handoff, ledger revalidation, wins classifier). Checked against the open-PR list during the full ledger sweep. Do NOT start this row while that PR is open — duplicating a queued conversion is the exact failure #292 records, and it has happened twice. Re-verify this row against main after that PR merges, and close it there rather than here. **Outcome:** concurrent sessions stop silently undoing each other on shared `claude/*` branches and on this file. **Observed across one task on 2026-07-30/31:** (a) PR #1490 was **closed unmerged by another actor while auto-merge was armed**, and because arming had been treated as "done", the only record of four preservation snapshots went with it and had to be reconstructed as #152. (b) Three branches (`claude/organize-local-worktree-d22bc3`, `claude/root-dir-coverage-gate-v2`, `claude/capture-session-followups`) received pushes from a Cursor Agent and a Codex session mid-task, producing repeated non-fast-forward rejections; one rejection was masked because the push was piped to `tail`, so the reported exit code was `tail`'s and the push looked successful. (c) `scripts/guard-push.mjs` correctly refused a push with `Pushing now races the squash-merge and can orphan this commit`, requiring disarm to push then re-arm. (d) Ledger ids were renumbered underneath in-flight work (#135 to #141 to #144), which is the mechanism behind #154. **New evidence 2026-08-07 (Track A1, PR #1678) — the sharpest form yet:** a concurrent session in the same worktree ran a commit BETWEEN this session's `git add -A` and its `git commit`, sweeping this session's staged index into a foreign commit `e422624f4` "Consolidate tailwind and UI fixes" mixed with unrelated mode-nav work, then created `claude/consolidated-ui-fixes`, pointed the in-use branch `claude/tailwind-merge-cn` at it too, and checked the new branch out — moving the worktree's HEAD off the branch being worked on. `git commit` reported "nothing to commit, working tree clean" and exit 1; only reading `git log -1` revealed the commit was not this session's. That foreign commit was built on the stale base `dfcbe2039`, so relative to `origin/main` it would revert PRs #1674 and #1675. Recovery was non-destructive: a fresh worktree off current `origin/main`, `git checkout e422624f4 -- `, re-verify, commit. **Next:** for a green ledger-only PR prefer merging it immediately over arming auto-merge; confirm a push landed with `git ls-remote` rather than the command's exit code; expect ids and row wording to move between reading and writing; after any `git commit`, verify `git log -1` is YOUR message and `git rev-parse --abbrev-ref HEAD` is still YOUR branch. **Stop:** do not treat auto-merge as completion, do not assume a branch you pushed an hour ago still has your commit at its tip, and never resolve a collision by resetting or re-pointing another session's branch. | session 2026-07-30/31; PRs #1490, #1508, #1511 | 2026-07-31 | | #162 | P2 | task | Redesign Tools search results state (Compact Results Instrument) | IN FLIGHT 2026-08-12 in PR #1839 (three runnable directions for the Tools search results state). Checked against the open-PR list during the full ledger sweep. Do NOT start this row while that PR is open — duplicating a queued conversion is the exact failure #292 records, and it has happened twice. Re-verify this row against main after that PR merges, and close it there rather than here. **Outcome:** `/tools?q=` is a committed results page: query-as-H1, one composer, dense tool rows; cross-mode demoted; no home hero / green filter banner / dual H1. **Product pick:** direction A from comps in `public/mockups/mode-page-redesign-2026-07/tools-search/`. **Next:** implement A on production Tools search; verify desktop+phone chrome ownership. **Stop:** do not redesign Tools home in the same PR unless asked. Renumbered after `main` took `#161` for mockup hover-token residue. | session 2026-07-31 mode-page design audit | 2026-07-31 | | #163 | P2 | task | Redesign Services search results (Progressive Referral Workflow) | **Outcome:** `/services?q=` uses query-as-H1 (not match-count), progressive shortlist/compare, no always-on decision panel or giant step rail. **Product pick:** direction B from comps in `public/mockups/mode-page-redesign-2026-07/services-search/`. **Next:** implement B; keep referral shortlist behaviour. **Stop:** do not change Services ModeHome in the same PR. | session 2026-07-31 mode-page design audit | 2026-07-31 | | #164 | P2 | task | Redesign Favourites as hybrid dashboard + search (no ModeHome) | **Outcome:** `/favourites` is one dashboard+search workspace; empty query shows Continue/recent/sets/table; typed query filters in place; no ModeHome hero. **Product pick:** Search-Led Workspace (direction B) from comps in `public/mockups/mode-page-redesign-2026-07/favourites-hybrid/`. User rejected ModeHome for Favourites. **Next:** implement B; retire command-library marketing H1 and redundant dual search. **Stop:** do not reintroduce ModeHome or a separate Favourites home route. | session 2026-07-31 mode-page design audit; user Favourites hybrid decision | 2026-07-31 | @@ -204,7 +199,6 @@ removed after current-main verification; it is not missing recommended work. | #178 | P2 | rec | pr-policy does not flag operational risk bundled with clinical or UI risk | IN FLIGHT 2026-08-12 in PR #1837 (harden verification & PR policy guards). Checked against the open-PR list during the full ledger sweep. Do NOT start this row while that PR is open — duplicating a queued conversion is the exact failure #292 records, and it has happened twice. Re-verify this row against main after that PR merges, and close it there rather than here. **Outcome:** a PR that mixes operational-risk paths with clinical or UI risk is called out before it merges, because squash-merging that mix destroys per-item revert. **Detail:** `classifyPullRequestFiles` already computes `operationalRisk`, `clinicalRisk`, `ragRanking` and `ui` independently, but nothing reacts to the combination. AGENTS.md's "PR bundling" section forbids bundling anything once `operationalRisk` is true; the classifier is where that could be enforced. PR #1489 is the worked example: 33 files spanning `.github/workflows/ci.yml`, both Dockerfiles, a rewrite of the bundle-budget gate, a phone-chrome scroll change and a therapy data restructure, merged as one squash (945148251). Reverting any single item now means hand-reverting hunks out of the squash commit, because the branch commits are unreachable. The remediation PR for that review repeats the pattern on a smaller scale (clinical data plus a one-line ci.yml timeout), which is why this is a recommendation rather than a hard gate — the right severity is probably a warning that names the mixed classes, not a merge block. **Next:** emit an advisory line from `evaluatePullRequestPolicy` when `operationalRisk` coincides with `clinicalRisk` or `ui`, listing which paths drove each; decide separately whether it ever blocks. Cover it in the `--self-test` block. **Stop:** do not make it a hard failure in the same change that introduces it — land the signal first and see how often it fires. Renumbered from this PR's original `#172`. | PR #1489 review remediation; PR #1532; session 2026-07-31 | 2026-07-31 | | #180 | P3 | issue | build-therapies-index now overwrites its own source input | RE-CONFIRMED STILL LIVE 2026-08-12 on merged main, with the exact lines. scripts/build-therapies-index.mjs takes public/therapy-compass-data/therapies.json as its SOURCE (:24-28, with the missing-source error naming it at :31) and also writes that same path as `legacyFullTarget` (:269). Source and target are one file, which is the defect this row names. Note the sibling that is now closed: the pretty-print regression (#179) is fixed and gated at :240-244, so do not conflate the two — the compactness guard does not address the read-write overlap. Next unchanged: give the generator a source that it never writes (or a target it never reads), so a re-run cannot consume its own output. | PR #1532; session 2026-07-31 | 2026-07-31 | | #183 | P2 | task | Create Sentry metric alert for production DB span p95 > 500ms | Still blocked 2026-08-01 closeout: SUPABASE_ACCESS_TOKEN and SENTRY_AUTH_TOKEN missing from session env; Sentry MCP OAuth can list/get alerts but has no create tool; browser hits login wall; no metric rules exist yet on clinibase-xz. Create Metric Alert: p95(span.duration), filter span.op:db, environment production, threshold >500ms, notify Active Members. Provide SENTRY_AUTH_TOKEN in session to finish via sentry alert metrics create. | session 2026-07-31 db-query-perf follow-up | 2026-07-31 | -| #202 | P3 | rec | Recommendation answers must revalidate the ledger against origin/main, not a stale checkout | IN FLIGHT 2026-08-12 in PR #1840 (harden agent handoff, ledger revalidation, wins classifier). Checked against the open-PR list during the full ledger sweep. Do NOT start this row while that PR is open — duplicating a queued conversion is the exact failure #292 records, and it has happened twice. Re-verify this row against main after that PR merges, and close it there rather than here. **Outcome:** agents stating next recommendations read `origin/main:docs/outstanding-issues.md` (or fast-forward first) and say how far the local checkout lags. **Evidence 2026-07-31:** a Cloud Agent answered `/issues`-style recommendations from a worktree 211 commits behind `origin/main`, so it re-proposed already-closed items (`#113`, `#114`, `#091`, `#105`, …) and missed newer opens (`#147`, `#117`, `#118`). Related to `#154` (ids/titles are unstable) and `#109` (shallow clones), but the failure mode here is stale full history, not missing history. **Next:** add a one-line check to the `issues` skill and AGENTS productivity defaults. **Stop:** do not treat a lagging worktree ledger as current memory. | session 2026-07-31 ledger hygiene review | 2026-07-31 | | #188 | P3 | task | Document and track disaster-recovery re-creation checklist as ledger work | **Outcome:** the five DR items that do not survive a schema restore are tracked with owners and verify steps. **Split into concrete tasks 2026-07-31:** `#196` pg_cron; `#197` Vault secrets; `#198` custom GUCs; `#199` edge functions; `#200` dashboard config. Keep this umbrella as the index; execute the child tasks. Distinct from `#056` (staging schema) and resolved `#054` (secrets reconciliation). **Stop:** do not treat a schema restore as complete until children are green. | docs/operator-backlog.md Disaster-recovery re-creation; session 2026-07-31 | 2026-07-31 | | #189 | P2 | task | Pin /api/search route-level round trips and disposition the x3 text RPC probes | **Outcome:** a counting-proxy budget drives `POST` `/api/search` (auth/ratelimit/scope/enrichment/telemetry), and the retrieval-core finding that `match_document_chunks_text_v2` and `match_document_table_facts_text_v2` each issue three times per search is either documented as intentional or collapsed under the RAG canary gate. **Source:** residual next actions on `#098` after answer-path and retrieval-core budgets landed. **Next:** (a) route-level budget following `tests/answer-route-preamble.test.ts`; (b) decide probe vs collapse — behaviour change needs RAG flag + canary. **Stop:** do not change retrieval assembly without approval. | session 2026-07-31; #098 residual; tests/search-round-trip-budget.test.ts | 2026-07-31 | | #190 | P3 | task | X3: Finish rag.ts monolith decomposition | VERIFIED CORRECT 2026-08-12 — re-checked against merged main during the full ledger sweep and left unchanged: src/lib/rag/rag.ts measures 4,362 lines — still the monolith this row describes; the decomposition has not started. This stamp exists so a later reader can tell "checked and still true" from "never looked at"; the two were indistinguishable before. **Outcome:** `src/lib/rag/rag.ts` is decomposed into focused modules per `docs/maturity-backlog-workorders.md` X3, with existing offline RAG contracts green. **Status:** IN PROGRESS (DocumentViewer/Dashboard extractions done; rag.ts remains). **Next:** continue safe extractions only with the RAG flag before editing protected surfaces; one verified draft PR per unit. **Stop:** no behaviour change without canary when retrieval/answer paths move. | docs/maturity-backlog-workorders.md X3; #086 | 2026-07-31 | @@ -241,9 +235,7 @@ removed after current-main verification; it is not missing recommended work. | #244 | P3 | rec | Forced-colours v2 mapping depends on grouped dark selectors staying in the media block | IN FLIGHT 2026-08-12 in PR #1841 (forced-colours selector specificity). Checked against the open-PR list during the full ledger sweep. Do NOT start this row while that PR is open — duplicating a queued conversion is the exact failure #292 records, and it has happened twice. Re-verify this row against main after that PR merges, and close it there rather than here. ckb-v2-tokens.css forced-colours block lists .ckb-v2.ckb-v2, .dark .ckb-v2.ckb-v2, and .ckb-v2.dark.ckb-v2 so specificity matches dark rules. Trimming to a single .ckb-v2.ckb-v2 silently drops dark HCM. Next: keep the contract test pin; never trim that selector group. | PR #1616 review findings; session 2026-08-05 | 2026-08-05 | | #245 | P3 | rec | responsive-compact CrossModeLinks keeps duplicate rails in the DOM | IN FLIGHT 2026-08-12 in PR #1842 (CrossModeLinks rail behaviour). Checked against the open-PR list during the full ledger sweep. Do NOT start this row while that PR is open — duplicating a queued conversion is the exact failure #292 records, and it has happened twice. Re-verify this row against main after that PR merges, and close it there rather than here. Phone chip rail and md+ card rail both mount; display:none removes the inactive from the a11y tree. Tests/analytics counting role=link see doubles; cross-mode-links-rail is phone-only. Next: prefer the variant test ids; do not collapse to one rail with JS breakpoints (hydration risk). | PR #1616 review findings; session 2026-08-05 | 2026-08-05 | | #248 | P2 | issue | Investigate why 20260705180000 search-health indexes were missing on live despite applied history | PR #1614 repairs the symptom with a mark-applied guard only. Confirm out-of-band whether the earlier reconcile migration partially applied, indexes were manually dropped, or schema_migrations was repaired — and whether check:drift should have caught this class before runtime search_schema_health. Renumbered from this PR's original #237 → #246 because main already used #237–#247 (PR #1616 findings plus the results-bar rows from PR #1615). | PR #1614 review / session 2026-08-05 (renumbered on main merge) | 2026-08-05 | -| #249 | P2 | rec | Extend issues/plan with an agent-safe wins classifier | IN FLIGHT 2026-08-12 in PR #1840 (wins classifier). Checked against the open-PR list during the full ledger sweep. Do NOT start this row while that PR is open — duplicating a queued conversion is the exact failure #292 records, and it has happened twice. Re-verify this row against main after that PR merges, and close it there rather than here. **Outcome:** /issues and recommendation answers can filter agent-safe short wins (estimate ≤4h, Capability not Operator-only, no RAG/provider, not blocked on a human decision) without inventing a 35th skill. **Next:** add an optional filter/section to the issues skill (and plan/flightplan when useful) that lists those wins from the open table + queue; keep it as procedure on the existing skills unless the classifier is reused thrice — only then mint a thin wins alias. **Stop:** do not weaken acuity ordering; operator A1s still outrank engineering wins. | session 2026-08-05 fastest-wins plan | 2026-08-05 | | #250 | P2 | task | Execute the fastest-wins multi-wave plan (Wave 0–4) | SUPERSEDED IN LARGE PART 2026-08-12 — this row is a wave plan whose contents have been overtaken, and as written it now misdirects. Rows it names as live A1 work are CLOSED: #207 and #226 were archived on main, and #166 (its sibling in that cluster) archived in the 2026-08-12 sweep. Of its engineering waves: 1B's gate-integrity set is done (#149, #210 re-scoped, #204/#167 covered by in-flight PR #1837); 1C's hygiene set is largely done or in flight (#232, #151, #154, #187, #142, #156, #186 all now carry IN FLIGHT notes against PR #1835/#1836); Wave 0/#202 is in flight in PR #1840. What genuinely remains of the plan is Wave 1A (#147 phone CLS, still open and still reproducible offline at zero provider cost), Wave 2 (#117 then #118), and Wave 3 (#098 then #189). The A1 track is now just #059, #053 and #231 — two operator rows and one live investigation. Next: either re-cut this row against that much smaller remainder, or close it and let #147/#117/#118/#098/#189 stand on their own, which is probably the honest move now that the multi-agent framing has served its purpose. Stop unchanged: no RAG behaviour change without flag plus canary, no provider gates without approval, and do not mix operationalRisk with clinical or UI in one squash. | session 2026-08-05 fastest-wins plan | 2026-08-05 | -| #251 | P3 | rec | Handoff checklist should pair gates skill with verification-router | IN FLIGHT 2026-08-12 in PR #1840 (handoff checklist). Checked against the open-PR list during the full ledger sweep. Do NOT start this row while that PR is open — duplicating a queued conversion is the exact failure #292 records, and it has happened twice. Re-verify this row against main after that PR merges, and close it there rather than here. **Outcome:** every PR handoff picks the smallest correct gate and pastes the decisive proof line, using verification-router when scope is unclear. **Next:** add one line to handoff/gates productivity defaults: after flightplan, run verification-router (or gates) before claiming green; never report exit 0 alone. **Stop:** do not stack verify:cheap + verify:ui + verify:release by default. | session 2026-08-05 fastest-wins plan | 2026-08-05 | | #253 | P3 | task | #1606 needs a hand-merge against merged PR #1615, not a rebase | SUPERSEDED IN PART 2026-08-07: the component both PRs rewrite no longer exists. `MobileResultFilterControl` — the native `