From 95d68c6b272d8ad78204fafca07e9e751c4255dd Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 24 Jul 2026 17:30:20 +0000 Subject: [PATCH 1/7] docs: close ledger #009 #010 #032 #041 #063 Record ops-only /api/jobs decision, coming-soon audit, governance ranking REFUTED guardrail, Factsheets reading-model brief, and Current Clinical Work privacy/persistence brief. Archive the five open items; no RAG or application behavior changes. Co-authored-by: BigSimmo --- docs/api-jobs-ops-surface.md | 23 +++++++ docs/codebase-index.md | 2 +- docs/current-clinical-work-brief.md | 87 ++++++++++++++++++++++++ docs/factsheets-reading-model-brief.md | 40 +++++++++++ docs/outstanding-issues.md | 19 +++--- docs/rag-behaviour/README.md | 2 +- docs/rag-behaviour/refuted-approaches.md | 15 ++++ docs/rag-behaviour/safeguards.md | 4 +- docs/site-map.md | 2 +- docs/wiring-conventions.md | 14 +++- scripts/generate-site-map.ts | 2 +- 11 files changed, 193 insertions(+), 17 deletions(-) create mode 100644 docs/api-jobs-ops-surface.md create mode 100644 docs/current-clinical-work-brief.md create mode 100644 docs/factsheets-reading-model-brief.md diff --git a/docs/api-jobs-ops-surface.md b/docs/api-jobs-ops-surface.md new file mode 100644 index 000000000..af33ab9bf --- /dev/null +++ b/docs/api-jobs-ops-surface.md @@ -0,0 +1,23 @@ +# `/api/jobs` — intentional ops/admin surface + +**Decision (2026-07-24):** Keep `GET /api/jobs`. It is a deliberate server/ops surface, not an abandoned client API and not a product UI dependency. + +## Evidence + +- Route: `src/app/api/jobs/route.ts`. +- Auth: live mode requires an authenticated **administrator** via `requireAuthenticatedUser(..., { administrator: true })`, then scopes rows with `documents.owner_id = user.id`. +- Demo mode returns paginated `demoJobs` only when `isDemoMode()` is true; a partially configured production path fails closed (no unauthenticated demo bleed — S11/H6). +- Product UI polls **`/api/ingestion/jobs`**, not `/api/jobs` (`ClinicalDashboard.tsx`). +- Repo search finds **no client `fetch("/api/jobs")`**. Callers are tests (`tests/api-route-coverage.test.ts`, `tests/api-validation-contract.test.ts`, `tests/public-access-deep.test.ts`) plus ops/docs inventory. + +## Why keep it + +- Distinct from the ingestion collection used by the dashboard (`/api/ingestion/jobs`). +- Covered by tenancy and API validation contracts; removing it would churn CI/docs without a product win. +- Useful for manual/admin job inspection with administrator credentials. + +## Contract for future work + +- Do **not** wire a client product surface to `/api/jobs` without an explicit product decision. +- Prefer `/api/ingestion/jobs` for in-app indexing status. +- If this route is ever deleted, update `docs/site-map.md` (via `scripts/generate-site-map.ts`), `docs/codebase-index.md`, `docs/wiring-conventions.md`, tenancy review references, and the API contract tests in the same change. diff --git a/docs/codebase-index.md b/docs/codebase-index.md index d2b9b597f..cda78cbd3 100644 --- a/docs/codebase-index.md +++ b/docs/codebase-index.md @@ -89,7 +89,7 @@ Structured map for AI agents and onboarding. For live routes, see `docs/site-map | Registry | `/api/registry/records`, `/api/registry/records/[slug]` | `registry/records/` | | Images | `/api/images/[id]/signed-url` | `images/[id]/signed-url/route.ts` | | Ops | `/api/health`, `/api/health/ready`, `/api/setup-status`, `/api/local-project-id` | `health/`, `setup-status/`, `local-project-id/` | -| Eval / jobs | `/api/eval-cases`, `/api/jobs` | `eval-cases/`, `jobs/` | +| Eval / jobs | `/api/eval-cases`; `/api/jobs` (admin/ops listing — see `docs/api-jobs-ops-surface.md`; UI uses `/api/ingestion/jobs`) | `eval-cases/`, `jobs/` | | Webhooks | `/api/webhooks/railway`, `/api/webhooks/supabase/document-change` (inbound; secret-gated — see docs/webhooks.md) | `webhooks/` | --- diff --git a/docs/current-clinical-work-brief.md b/docs/current-clinical-work-brief.md new file mode 100644 index 000000000..4dbc36fbf --- /dev/null +++ b/docs/current-clinical-work-brief.md @@ -0,0 +1,87 @@ +# “Current Clinical Work” — product / privacy / persistence brief (#063) + +**Status:** Brief only (2026-07-24). **No storage schema, API, or UI implementation** in this pass. + +## Outcome sought by the ledger + +Decide whether a workspace combining saved comparisons, partial formulation work, recent tools, and pinned source sets is worth building. Success = define users, data classes, lifecycle, cross-device expectations, deletion, failure states, demand evidence, and the smallest testable slice. Stop if demand or safe persistence cannot be established. + +## Working definition + +**Current Clinical Work** would be an authenticated clinician workspace that resumes in-progress clinical reference tasks — not a patient chart and not an EHR. + +Candidate contents (product hypothesis only): + +- Saved / recent comparisons (e.g. differentials presentation compare sets) +- Partial formulation drafts +- Recent Tools launcher destinations +- Pinned source sets / favourites-adjacent collections + +Adjacent shipping surfaces today: Favourites / Saved workflows (`/favourites`, Tools catalog `favourites` tile), browser-session recents, and mode-local UI state. None of these yet form a unified “current work” document. + +## Users + +| Actor | Need | +| ----- | ---- | +| Authenticated clinician | Resume interrupted multi-step reference work across sessions/devices | +| Guest / anonymous | **Out of scope** for durable Current Clinical Work (align with Favourites gating) | +| Administrator / ops | Not a consumer; may need retention/deletion tooling if server persistence exists | + +## Data classes (privacy) + +Classify before any persistence design. Prefer the Safety Plan / PIA posture: **no patient identifiers**, identifier-free working content only. + +| Class | Examples | Sensitivity | Allowed persistence (draft policy) | +| ----- | -------- | ----------- | ---------------------------------- | +| A — Navigation husks | Tool ids, mode hrefs, last-opened route | Low | Server or device OK if owner-scoped | +| B — Clinical working selections | Compare slugs, pinned document ids, formulation section ids | Medium (workflow, not PHI by itself) | Owner-scoped server OK with retention | +| C — Free-text working notes | Formulation prose, comparison notes, untitled drafts | **High incidental PHI risk** | Prefer tab-local or explicit “save draft” with retention + deletion; never default-sync raw text to logs/providers | +| D — Source pins | Document ids / titles already in corpus | Medium | Owner-scoped; titles may be corpus public | + +**Hard stop:** do not implement cross-device sync of Class C until privacy/#053 counsel path accepts retention, residency, and deletion semantics. Do not send Class C to OpenAI as a “workspace restore” side channel. + +## Lifecycle + +1. **Create** — explicit user action (“Save to Current Work”) or narrow auto-save of Class A/B only. +2. **Update** — last-touched timestamp; replace-in-place per item type. +3. **Resume** — open the owning mode route with restored selection ids (URL-serializable where possible). +4. **Complete / archive** — user marks done; item leaves the “current” list. +5. **Delete** — user delete + account deletion cascade; TTL for abandoned drafts (recommend ≤ 30–90 days for Class C if ever stored). + +## Cross-device expectations + +| Option | Pros | Cons | Recommendation | +| ------ | ---- | ---- | -------------- | +| Tab-local only | Matches Safety Plan; lowest privacy risk | No multi-device resume | Default until demand proven | +| Device localStorage | Survives refresh | No cross-device; XSS/shared-device risk | Acceptable for Class A only | +| Owner-scoped Supabase rows | Real resume | Retention, RLS, deletion, PHI incident surface | Only after demand + Class C policy | + +**Product default for v0:** tab-local / URL state; no new tables. + +## Failure states + +- Signed-out user: hide or disable Current Clinical Work; do not leak previous owner items. +- Missing pinned document: show “source unavailable” and keep the shell item deletable. +- Partial formulation schema drift: fail closed to empty section rather than corrupting clinical text. +- Quota / storage failure: keep in-memory work; surface non-blocking “not saved.” + +## Demand evidence (gate) + +Before any storage/UI project, record at least one of: + +- Repeated clinician requests for resume-across-device of a named workflow, or +- Measured drop-off (e.g. formulation / compare sessions abandoned mid-flow) with owner acknowledgment. + +Without that evidence, **close the idea** rather than building speculative persistence. + +## Smallest testable slice (only if demand clears) + +1. **No backend.** Authenticated-only “Resume last comparison” using existing URL/query state + sessionStorage of compare ids (Class B). +2. Entry from Favourites or Tools “Saved workflows” only — no new mode. +3. Proof: focused DOM test that signed-out users see nothing durable; signed-in restore opens the existing differentials/presentation URL; no `/api/*` writes. + +**Out of scope for the first slice:** formulation prose sync, pinned source sets schema, mobile offline, sharing, export. + +## Stop rule + +If product cannot name (a) a single workflow to resume, (b) a data class that is safe without new legal review, and (c) an owner for deletion/retention — **do not build**. Keep Favourites + URL state as the resume story. diff --git a/docs/factsheets-reading-model-brief.md b/docs/factsheets-reading-model-brief.md new file mode 100644 index 000000000..3b8fd6e14 --- /dev/null +++ b/docs/factsheets-reading-model-brief.md @@ -0,0 +1,40 @@ +# Factsheets reading model — product brief (#041) + +**Status:** Decision recorded 2026-07-24. No second Factsheets mode. No implementation in this pass. + +## Decision + +Future patient-content work **extends the existing Factsheets reading model** (Easy Read / Standard on the current Factsheets routes). Do **not** add a parallel patient-facing Factsheets mode, launcher tile, or app-mode entry. + +## Current model (keep) + +| Piece | Location / behaviour | +| ----- | -------------------- | +| Mode home / search / detail | `/factsheets`, `/factsheets/search`, `/factsheets/[slug]` | +| Reading levels | `easy` \| `standard` toggle on med-rich detail (`factsheet-detail-page.tsx`) | +| Content fields | `whatEasy` / `whatStandard` (and related section bodies) in `factsheets-data.ts` | +| Presentation contracts | Existing accessibility, print/PDF, and theme tokens on the Factsheets surface | + +The Easy Read / Standard control is already a first-class reading-level switch, not a separate product mode. + +## Why not a second mode + +- A second mode would duplicate search chrome, nav, sitemap, reachability, and source-governance obligations. +- Patient-facing copy still needs the same clinical-governance and source-review path as clinician Factsheets; splitting modes does not reduce that risk. +- Mode sprawl conflicts with the “one job per mode home” navigation model in `docs/codebase-index.md` / `src/lib/app-modes.ts`. + +## When to revisit + +Only with **all** of: + +1. A concrete user need (who, what missing reading level or audience, measured gap). +2. A source-governance plan for patient-facing claims (review owner, attestation, refresh). +3. An extension plan that reuses Easy Read / Standard (or adds one more level **inside** the same detail presentation), not a new `app-modes` entry. + +## Smallest future slice (if demand lands) + +1. Add or revise content fields on existing Factsheet records. +2. Extend the existing reading-level group (new `aria-pressed` option + content selector). +3. Add focused Factsheets DOM/a11y coverage; keep reachability on current routes only. + +**Stop:** if the request is “new mode / new sidebar item / separate patient app,” reject and point here. diff --git a/docs/outstanding-issues.md b/docs/outstanding-issues.md index 5c7002f7b..d22b3dee0 100644 --- a/docs/outstanding-issues.md +++ b/docs/outstanding-issues.md @@ -81,11 +81,10 @@ removed after current-main verification; it is not missing recommended work. | 29 | `#038` | Optional | High — product/design architecture | When a new comparison surface is approved | 0.5–1 day | Define a shared interaction contract without flattening mode-specific content. Stop when no concrete new surface exists. | | 30 | `#040` | Optional | High — visual QA/accessibility | When baseline owner/update workflow exists | 1–2 days | Establish a small stable desktop/mobile/accessibility baseline set. Do not make it blocking if flake or maintenance cost outweighs detection value. | | 31 | `#039` | Optional | High — frontend architecture | During a concrete catalogue-toolbar project | 0.5–1 day inventory; 1–3 days code | Converge only repeated toolbar behavior without flattening search semantics. Stop when there is no bounded implementation target. | -| 32 | `#063` | A3 | High — product architecture + privacy | Only when the product owner wants to evaluate the feature | 0.5–1 day | Write a product/privacy/persistence brief for “Current Clinical Work” before storage or UI implementation. Stop if demand or safe persistence cannot be established. | -| 33 | `#065` | A2 | High — document-viewer UI | Only when the user explicitly resumes the paused task | 0.5–1.5 days | Finish the compact source-text accordion, citation/search auto-open, print restoration, and 320/390/1280 px coverage. Keep the preserved branch untouched until explicit resume; no provider calls. | -| 34 | `#077` | A3 | High — workflow safety | Next workflow-hardening window | 1–2 hours | Add a cooperative primary-checkout write lease/check that prevents a second task from writing, switching, or synchronizing the canonical checkout while another owner or dirty state exists. Keep read-only work and independent feature worktrees unblocked. | -| 35 | `#078` | A3 | Standard — reconciliation tooling | After `#067`; before another broad reconciliation | 2–4 hours | Generate one deterministic, secret-safe evidence pack from the reconciliation lifecycle: disposition rows, operation markers, archive refs, bundle verification, hashes, worktree counts, and local/base equality. Never fetch, call providers, or delete implicitly. | -| 36 | `#079` | Optional | High — repository hygiene | In explicitly scheduled batches | 30–60 minutes per batch | Disposition at most ten retained worktrees per pass using owner, PR, review-ledger, ancestry, and patch evidence. Preserve every dirty, active, secret-bearing, post-freeze, or ambiguous worktree and stop rather than broad-cleaning. | +| 32 | `#065` | A2 | High — document-viewer UI | Only when the user explicitly resumes the paused task | 0.5–1.5 days | Finish the compact source-text accordion, citation/search auto-open, print restoration, and 320/390/1280 px coverage. Keep the preserved branch untouched until explicit resume; no provider calls. | +| 33 | `#077` | A3 | High — workflow safety | Next workflow-hardening window | 1–2 hours | Add a cooperative primary-checkout write lease/check that prevents a second task from writing, switching, or synchronizing the canonical checkout while another owner or dirty state exists. Keep read-only work and independent feature worktrees unblocked. | +| 34 | `#078` | A3 | Standard — reconciliation tooling | After `#067`; before another broad reconciliation | 2–4 hours | Generate one deterministic, secret-safe evidence pack from the reconciliation lifecycle: disposition rows, operation markers, archive refs, bundle verification, hashes, worktree counts, and local/base equality. Never fetch, call providers, or delete implicitly. | +| 35 | `#079` | Optional | High — repository hygiene | In explicitly scheduled batches | 30–60 minutes per batch | Disposition at most ten retained worktrees per pass using owner, PR, review-ledger, ancestry, and patch evidence. Preserve every dirty, active, secret-bearing, post-freeze, or ambiguous worktree and stop rather than broad-cleaning. | @@ -98,7 +97,6 @@ removed after current-main verification; it is not missing recommended work. | ID | Pri | Type | Summary | Detail / next action | Source | Added | | ---- | --- | ----- | --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | | #059 | P1 | task | Verify containment of every credential reported exposed in chat | **Outcome:** every reported exposed credential is rejected or retired. **Next:** in approved security windows, verify and revoke or rotate the GitHub token, OpenAI key, Supabase service-role JWT, database password, and E2E credential; create replacements only when required and update only intended secret stores. **Success:** provider evidence confirms the old credentials cannot authenticate, replacements are distinct and minimally scoped, presence/readiness checks pass, and secret scans remain clean. **Stop:** no provider or secret-store action without approval; never print or paste values into Git, logs, issues, or chat. | session 2026-07-24 security reconciliation; AI Agent Target Manifest | 2026-07-24 | -| #063 | P3 | rec | Define “Current Clinical Work” before implementation | **Outcome:** decide whether a workspace combining saved comparisons, partial formulation work, recent tools, and pinned source sets is worth building. **Next:** write a product/privacy/persistence brief only; do not build storage or UI. **Success:** define users, data classes, lifecycle, cross-device expectations, deletion, failure states, demand evidence, and the smallest testable slice. **Stop:** close the idea if demand or safe persistence cannot be established. | session 2026-07-24; `src/lib/tools-catalog.ts` | 2026-07-24 | | #064 | P2 | task | Reconcile the preserved browser and contrast patch | **Outcome:** the isolated dirty formulation/contrast patch is safely landed or explicitly dispositioned. **Next:** rebase its intent against current `main` without overwriting the worktree, then run focused Playwright coverage and `verify:ui`. **Success:** intended disabled/contrast behavior is accessible, browser assertions remain meaningful, and unrelated work is preserved. **Stop:** do not discard or auto-merge the dirty worktree; pause on ambiguous ownership or scope. | `agent/formulation-disabled-contrast`; session 2026-07-24 | 2026-07-24 | | #065 | P2 | task | Complete the paused compact document source-text accordion | **Outcome:** the document viewer uses compact nested disclosures while retaining complete text, citation/search navigation, print behavior, and composer clearance. **Next:** only when the user explicitly resumes, reconcile `codex/chat-document-text-accordion-7cb4` with current `main` and complete the focused 320/390/1280 px tests. **Success:** default disclosures are closed; deep links and search open only the active passage; printing expands/restores state; no overflow. **Verify:** focused document-viewer Playwright, `verify:cheap`, `verify:ui`, and static production-readiness. **Stop:** remain paused until explicit user return; no provider calls. | paused document-viewer task; `codex/chat-document-text-accordion-7cb4` | 2026-07-24 | | #066 | P2 | task | Land and prove the streamlined six-item sidebar | Implementation and the corrected Therapy wiring assertion are recoverable from remote branch `origin/codex/sidebar-test-fix-20260723` at full commit `cd54e68fbf7b07b5dffe3220e36af2caa528da54`; fetch it in a fresh checkout with `git fetch origin refs/heads/codex/sidebar-test-fix-20260723`. Focused sidebar/favourites suites pass 18/18. Remaining: run `verify:pr-local`, start the app and inspect desktop/tablet/mobile plus short-height scrolling and keyboard/focus behavior, run `verify:ui`, production build and bundle-budget checks, then open/merge the PR and prove the exact content is on `origin/main`. | remote branch `origin/codex/sidebar-test-fix-20260723`; commit `cd54e68fbf7b07b5dffe3220e36af2caa528da54`; session 2026-07-24 | 2026-07-24 | @@ -114,8 +112,6 @@ removed after current-main verification; it is not missing recommended work. | #058 | P2 | task | Verify production content before any seed write | Against `the live target project`, verify registry, differentials, and medications surfaces are non-empty before writing. Seed only confirmed gaps idempotently with approved owner/project identity and confirmation flags. | `docs/launch-operator-runbook.md`; `docs/operator-backlog.md` | 2026-07-24 | | #005 | P3 | rec | `finalScore` saturates at clamp ceiling | Base + ~40 stacked boosts routinely exceed 1.0, so strong matches tie at 1.0 and order by an arbitrary `document_id` tiebreak. If ranking is ever revisited, break ties by the **pre-clamp** score rather than raising the `[0,1]` ceiling (downstream gates assume `[0,1]`). Ordering already sorts by the unbounded pre-clamp `rankScore` (`clinical-search.ts:1735,1927,1950-1955`), so the clamp confines only the reported confidence value, not result order. Not a defect on the current golden set; any change here is a protected RAG surface (canary required). | `docs/rag-hybrid-findings-and-todo.md` P1 item 4; `src/lib/clinical-search.ts:1735` | 2026-07-21 | | #007 | P3 | rec | `/tools` vs `/?mode=tools` parallel Tools entry points | `/tools` (standalone `ApplicationsLauncherPage`) has no inbound in-app link; the sidebar Tools item uses `/?mode=tools`. Decide the canonical entry point and wire nav consistently, or drop the standalone `/tools` page + `/applications` redirect. Currently allowlisted in `tests/route-reachability.test.ts`. | `src/app/tools/page.tsx`; `src/app/applications/route.ts` | 2026-07-21 | -| #009 | P3 | rec | Confirm `/api/jobs` is intentionally server/ops-only | No client `fetch()` reaches `/api/jobs` (only tests import it). Confirm it is a deliberate ops/manual surface; if abandoned, remove it. | `src/app/api/jobs/route.ts` | 2026-07-21 | -| #010 | P3 | task | Un-built "Coming soon" controls across forms/favourites | ~10 disabled placeholders (forms refine/reset, favourites sort/add/new-set, move-to-set, remove-favourite) plus presentation Compact/Detailed density toggle (honest coming-soon placeholders; selected styling removed 2026-07-24). Correctly non-interactive — wire when the underlying features land. | `forms-search-results-page.tsx`; `favourites-hub.tsx`; `favourites-command-library-page.tsx`; `differential-presentation-workflow-page.tsx` | 2026-07-21 | | #011 | P3 | task | Auth DB-connection allocation is operator-only | Supabase Auth (GoTrue) is capped at ~10 absolute DB connections (Supabase perf advisor). Switch to **percentage-based** allocation in the Supabase **dashboard** before the first compute scale-up — **not settable via SQL/MCP** (operator-owned). Verify via a staging soak + an approval-gated read-only advisor re-check. | `docs/auth-connection-cap-runbook.md`; `docs/process-hardening.md` (Known follow-up debts) | 2026-07-21 | | #012 | P3 | rec | Slim the lazy cross-mode differentials chunk | `cross-mode-differentials.ts` is dynamically imported (correctly code-split **out** of the initial/dashboard bundle — verified), but it pulls the full ~860 KB differentials snapshot (~125 KB gzip lazy chunk) just to build a tiny `{slug,title,clinicalHinge}` + presentations + aliases catalog. A precomputed lightweight index (generator + drift check, like the `specifiers-content` split / medications `fields=index`) would cut that lazy chunk ~5–10×. Not a bundle leak — an M-effort slim. | `src/lib/cross-mode-differentials.ts`; `src/components/clinical-dashboard/cross-mode-links.tsx:150`; session 2026-07-21 (build:analyze) | 2026-07-21 | | #013 | P3 | rec | Route-chunk + mockup catalogue JSON weight | `build:analyze`: `/specifiers` ships `specifiers-search-index.json` (~180 KB parsed), `/forms` ships `forms-catalog.json` (~132 KB), `/formulation` ships `formulation-content.json` (~52 KB, client-side local search — needs index/full split or a search endpoint, architectural). All route-scoped (not initial bundle). Also `*-mockups.tsx` (~100 KB across chunks) build though `/mockups` 404s in prod — exclude from the prod artifact. | session 2026-07-21 (build:analyze) | 2026-07-21 | @@ -132,7 +128,6 @@ removed after current-main verification; it is not missing recommended work. | #028 | P3 | rec | Runtime error tracking (Sentry or similar) | No error tracking in the repo — production exceptions on `psychiatry.tools`, including how often `RAG_PROVIDER_MODE=auto` silently degrades to source-only, are invisible. Weigh adding `@sentry/nextjs` (dependency + DSN secret + instrumentation) vs cost; alert → chat/issue. Provider-backed; needs explicit sign-off before adding the dependency. | session 2026-07-22 webhook review | 2026-07-22 | | #029 | P2 | issue | 12 of 30 answer-quality cases return the fallback stub | run #61 --dump-answers: 12/30 quality cases emit the source_backed_review_fallback boilerplate with answer_sections: [], all grounded with 4-6 citations. Some still PASS targeting because the stub echoes query keywords (the contraindication/document_lookup matchers need only a keyword), so the targeting metric MASKS the problem for those intents. Superset of #018 — fix in the extractive composer, validate with the provider-backed answer eval. | run #61 dump artifact; session 2026-07-22 | 2026-07-22 | | #030 | P2 | issue | Wide-tier alias lets one doc satisfy both comparison slots | In src/lib/eval-document-matching.ts, "Admission to Discharge for Mental Health Inpatients" appears in BOTH the AdmissionCommunityPts and Discharge alias lists, so a single document can satisfy both expectedFiles slots and make allHit true — a latent false-pass on admission-discharge cases. Not firing today (that doc is not in the failing top-5) but it would mask a real miss. Tighten the tables so one doc cannot fill both sides. | src/lib/eval-document-matching.ts:32-65; session 2026-07-22 | 2026-07-22 | -| #032 | P3 | rec | Governance ranking weighting: REFUTED, not debt | The source-governance audit (PR #1051) flagged three "gaps": `review_due` carries no ranking penalty, `unknownCurrentnessPenalty` ships at 0, and `selectBestSourceRecommendation` ignores governance metadata. **These are deliberate, measured decisions — do NOT implement them as written.** Blanket metadata boosts/penalties in selection ordering were measured on 2026-07-02 to regress the golden retrieval eval to 16/23 (doc-recall@5 1.0→0.76, mrr 0.75→0.64). Two corpus facts make it unsafe: scores saturate at the clamp so stacked boosts fully override lexical relevance, and the corpus is only partially metadata-enriched while `normalizeSourceMetadata` coerces unenriched docs to `unknown`/`unverified` — so "unknown" ≠ "bad" and blanket weighting swings ranking approx. 0.35 for reasons unrelated to relevance. Even governance-as-tiebreak buried correct unenriched docs (3 designs bisected). Next action: none — treat as a guardrail. If ever revisited, RC8 (source-strength as a _filter_) is the tracked path, gated on `eval:retrieval:quality` 36/36 plus a live canary pair. | PR #118; `docs/rag-behaviour/refuted-approaches.md`; PR #1051 items 4/5/6 | 2026-07-22 | | #033 | P3 | rec | Source governance metadata absent from the LLM prompt | `buildRagSourceBlock` omits `document_status`, `clinical_validation_status`, and `extraction_quality`, so the model cannot self-caveat during generation and governance is enforced only post-hoc. Generation-surface change: needs `eval:rag` plus `eval:quality --rag-only` (grounded-supported must not drop, citation-failure 0) and explicit approval. Carries the same "unknown ≠ bad" hazard as #032 — on a partially-enriched corpus the model would likely over-caveat correct sources, so design the prompt wording before spending an eval. | `src/lib/rag/rag-source-block.ts:126-198`; PR #1051 audit item 8 | 2026-07-22 | | #035 | P3 | rec | Threshold-conflict detection covers only 3 params | `detectThresholdDisagreements` checks only ANC, WBC, and platelets paired with withholding verbs, so cross-source conflicts on medication doses, lithium/thyroid levels, or vital signs go undetected. Deliberately narrow (see the comment at `:469-474`). Broadening changes when an answer is classified `conflicting` and adds warnings — real false-positive risk. Needs new fixtures plus a behaviour review before any change. | `src/lib/evidence.ts:469-574`; PR #1051 audit item 7 | 2026-07-22 | | #036 | P3 | rec | 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 promotion migrations but never used as a retrieval filter. Promotion is unconditional on `clinical_validation_status`, so unverified documents are publicly searchable — compensated by keeping `unverified_source` in the frontend-visible warning set. A hard schema flag touches RLS and the clinical-risk-gated retrieval RPCs; weigh against the existing compensating control before acting. | `supabase/schema.sql:61-108`; `src/lib/search-scope.ts:181-236`; PR #1051 audit item 3 | 2026-07-22 | @@ -140,7 +135,6 @@ removed after current-main verification; it is not missing recommended work. | #038 | P3 | rec | Consolidate shared comparison behavior | Several clinical modes expose comparison workflows with similar selection, empty-state and mobile-dock needs. Define one shared behavioral contract before another comparison surface is added; keep mode-specific clinical content separate. This is a design-system recommendation, not a current defect. | design audit reconciliation; session 2026-07-22 | 2026-07-22 | | #039 | P3 | rec | Consolidate catalogue toolbar patterns | Catalogue/search pages have independently evolved filter, sort, result-count and mobile toolbar behavior. Inventory the existing implementations and converge only the repeated interaction contract; do not flatten mode-specific search semantics. | design audit reconciliation; session 2026-07-22 | 2026-07-22 | | #040 | P3 | rec | Add targeted visual-regression baselines | Keep a small approved baseline set for high-value desktop/mobile surfaces and accessibility modes instead of screenshotting every route. Start with account/settings, document viewer, mode homes and bottom-composer interactions; define an intentional-update workflow before enabling blocking comparisons. | design audit reconciliation; session 2026-07-22 | 2026-07-22 | -| #041 | P3 | rec | Extend the existing Factsheets reading model | Do not add a second patient-facing Factsheets mode. Future patient-content work should extend the existing Easy Read/Standard presentation and its accessibility/content contracts. Revisit only with a concrete user need and source-governance plan. | design audit reconciliation; session 2026-07-22 | 2026-07-22 | | #075 | P2 | issue | Search-scope label enumeration can truncate after 1,000 rows | **Outcome:** every owner-visible source label can participate in scoped search without silently dropping rows at the Supabase response cap. **Next:** reproduce on current `main` with more than 1,000 distinct labels, then add bounded deterministic pagination and a focused multi-page regression. **Verify:** search-scope unit/API contracts, offline RAG contracts, `verify:cheap`, and production-readiness. **Stop:** do not replay mixed PR #1132, widen aliases, change ranking, or run a live canary unless the isolated fix demonstrably changes protected retrieval behaviour. | PR #1132 (`src/lib/search-scope.ts`, `tests/search-scope.test.ts`); primary reconciliation 2026-07-24 | 2026-07-24 | | #076 | P3 | task | Reproduce malformed fallback PDF image/table crops | **Outcome:** a real current-main fixture proves whether fallback images or table crops are malformed before retention/storage behaviour changes. **Next:** capture one minimal authorised fixture, identify the exact extraction stage and expected geometry, and add a red Python/DOM regression. **Success:** the smallest fix preserves valid assets within existing count/byte budgets and signed-image privacy boundaries. **Stop:** do not merge broad PR #1129, arbitrary crop thresholds/padding, storage expansion, or timeout increases without the reproducer and budget evidence. | PR #1129; `worker/python/extract_pdf_assets.py`; `src/lib/image-filtering.ts`; primary reconciliation 2026-07-24 | 2026-07-24 | | #077 | P2 | issue | Concurrent tasks can re-dirty the canonical primary checkout | **Outcome:** `C:\Dev\Apps\Database` remains a clean synchronization target while write work happens in task-owned worktrees. **Next:** add a cooperative owner/lease check to task-start and lifecycle transitions; before a primary write, branch switch, fast-forward, or cleanup, report owner, dirty state, and Git operation markers and fail closed on an active owner. Include stale-lease recovery. **Success:** a focused concurrency test refuses a second primary writer while read-only commands and separate worktrees continue normally. **Stop:** do not add an OS-wide lock, kill processes, discard existing dirty files, or serialize independent feature worktrees. | primary re-dirtied by another active task immediately after reconciliation proof; session 2026-07-24 | 2026-07-24 | @@ -153,6 +147,11 @@ Move resolved rows here with the resolution date and a one-line outcome. Keep th | ID | Type | Summary | Outcome | Resolved | | ---- | ----- | ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | +| #009 | rec | Confirm `/api/jobs` is intentionally server/ops-only | Kept as deliberate administrator/ops listing: no client `fetch("/api/jobs")` (UI uses `/api/ingestion/jobs`); documented in `docs/api-jobs-ops-surface.md` plus wiring/codebase-index/site-map notes. Not abandoned — do not remove without updating API contract tests. | 2026-07-24 | +| #010 | task | Un-built "Coming soon" controls across forms/favourites | Audited forms/favourites/presentation placeholders: all use honest `disabled` or `aria-disabled` + coming-soon copy (or presentational `ToggleSwitch` without `onToggle`). No fake-interactive controls; leave unwired until features land. Recorded in `docs/wiring-conventions.md`. | 2026-07-24 | +| #032 | rec | Governance ranking weighting: REFUTED, not debt | Reinforced as guardrail only in `docs/rag-behaviour/refuted-approaches.md` (Refutation 3), README, and safeguards — do **not** implement `review_due`/unknownCurrentness ranking penalties or boosts. No retrieval/ranking code changed. RC8 filter path remains the only revisit route behind canary gates. | 2026-07-24 | +| #041 | rec | Extend the existing Factsheets reading model | Brief recorded in `docs/factsheets-reading-model-brief.md`: extend Easy Read/Standard on existing Factsheets routes; reject a second patient-facing Factsheets mode unless concrete need + source-governance plan exist. | 2026-07-24 | +| #063 | rec | Define “Current Clinical Work” before implementation | Product/privacy/persistence brief recorded in `docs/current-clinical-work-brief.md`. Default v0 = no new storage (tab/URL resume); Class C free text needs privacy clearance. Stop without demand evidence. No UI/schema implemented. | 2026-07-24 | | #070 | issue | Presentation mobile tabs misroute Overview/Map/Related | Fixed in PR #1135: Overview/Map/Related deep-link to diagnosis `?tab=` sections; Compare stays on the presentation page. Regression in `tests/mobile-interaction-regressions.test.ts`. (Provisional PR-branch IDs `#068`–`#072` were renumbered after `main` claimed `#068`/`#069`.) | 2026-07-24 | | #071 | issue | Evidence/Clinical Notes Add fakes success without persistence | Fixed in PR #1135: sticky Add controls use the focusable coming-soon placeholder pattern instead of optimistic `setAdded(true)`. | 2026-07-24 | | #072 | issue | Tools hub exposes false Sort/More affordances | Fixed in PR #1135: Sort is a status label, More filter targets coordination/saved without a fake menu chevron, and the favourites shortcut is labelled Saved/Favourites. | 2026-07-24 | diff --git a/docs/rag-behaviour/README.md b/docs/rag-behaviour/README.md index 2f12cea5e..92bd3106b 100644 --- a/docs/rag-behaviour/README.md +++ b/docs/rag-behaviour/README.md @@ -8,7 +8,7 @@ selection, release-ordering, or eval-ground-truth surface. | File | What it holds | | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `behaviour-map.md` | The verified mechanics: score imputation sites, the release comparator chains, the gate/threshold ladder, second-stage engagement rules, and which live cases exercise which path. | -| `refuted-approaches.md` | The two live-refuted improvement attempts with their numbers, the root-cause post-mortems, and the binding constraints any third attempt must satisfy. | +| `refuted-approaches.md` | Live-refuted improvement attempts (feature-weight tuning, saturation-tail spread, governance ranking penalties/boosts) with numbers, post-mortems, and binding constraints. | | `safeguards.md` | The protection stack: protected-surface list, the pr-policy `RAG impact:` gate, the source-pin contract test, the canary-pair protocol, and the regeneration procedures. | Standing rules (mirrored in `AGENTS.md` so every agent session inherits them): diff --git a/docs/rag-behaviour/refuted-approaches.md b/docs/rag-behaviour/refuted-approaches.md index 819443313..309f3007d 100644 --- a/docs/rag-behaviour/refuted-approaches.md +++ b/docs/rag-behaviour/refuted-approaches.md @@ -58,6 +58,21 @@ Full audit trail: `docs/branch-review-ledger.md` (2026-07-20 rows), PRs #1003– 5. **Honest sizing:** the prize is rank depth on 3–4 already-passing cases (~0.03–0.08 mrr). Weigh against the demonstrated regression risk before attempting at all. +## Refutation 3 — governance metadata ranking penalties/boosts: measured regression (do not implement) + +Ledger `#032` / source-governance audit (PR #1051) items that look like “gaps” but are **deliberate, measured non-features**: + +- `review_due` carries **no** ranking penalty +- `unknownCurrentnessPenalty` ships at **0** +- `selectBestSourceRecommendation` **ignores** governance metadata for ordering + +**Do not implement blanket governance ranking penalties or boosts.** + +- **Measured harm (2026-07-02):** golden retrieval regressed to 16/23 (doc-recall@5 1.0→0.76, mrr 0.75→0.64) when metadata boosts/penalties reordered selection. +- **Why it fails here:** relevance scores saturate at the clamp, so stacked metadata swings override lexical relevance; the corpus is only partially enriched and `normalizeSourceMetadata` coerces unenriched docs to `unknown`/`unverified` — **unknown ≠ bad**. Even governance-as-tiebreak buried correct unenriched docs (three designs bisected). +- **Standing guard:** `tests/retrieval-selection.test.ts` keeps relevance ordering and asserts a higher-relevance `review_due`/`unverified` source outranks a lower-relevance `current`/`reviewed` one (`docs/rag-hybrid-findings-and-todo.md` item 20). +- **If ever revisited:** only via **RC8 — source-strength as a filter, not a penalty/boost in selection ordering**, gated on `eval:retrieval:quality` 36/36 plus an approved live canary pair. Prompt-side governance caveats are a separate generation-surface item (`#033`), not a ranking change. + ## Related follow-up plans - **Word-boundary content matcher — ✅ IMPLEMENTED (2026-07-20, same-day follow-up).** diff --git a/docs/rag-behaviour/safeguards.md b/docs/rag-behaviour/safeguards.md index dc83c2acf..5a94f999a 100644 --- a/docs/rag-behaviour/safeguards.md +++ b/docs/rag-behaviour/safeguards.md @@ -59,7 +59,9 @@ comparator key ORDER as source text. Any edit — including by a task that never `AGENTS.md` § "RAG ranking protection" mirrors these rules so every agent session loads them: flag RAG impact before editing, canary pair for behaviour changes, never insert comparator -keys above relevance, read this folder first. The eval-canary pair protocol: +keys above relevance, read this folder first. **Also:** do not add `review_due` / +`unknownCurrentness` / governance-metadata ranking penalties or boosts — that shape is +refuted (`refuted-approaches.md` § Refutation 3; ledger `#032`). The eval-canary pair protocol: 1. Baseline: latest green canary on current main (or one dispatch). 2. Change merges (or runs from a branch via the `ref` dispatch input). diff --git a/docs/site-map.md b/docs/site-map.md index 3a57a8dc1..9274aa3d3 100644 --- a/docs/site-map.md +++ b/docs/site-map.md @@ -1054,7 +1054,7 @@ This file is generated by `npm run sitemap:update`. Run `npm run sitemap:check` - `/api/ingestion/jobs` - Ingestion job collection. Source: `src/app/api/ingestion/jobs/route.ts`. - `/api/ingestion/jobs/[id]/retry` - Retry ingestion job. Source: `src/app/api/ingestion/jobs/[id]/retry/route.ts`. - `/api/ingestion/quality` - Ingestion quality reporting. Source: `src/app/api/ingestion/quality/route.ts`. -- `/api/jobs` - Job state. Source: `src/app/api/jobs/route.ts`. +- `/api/jobs` - Administrator/ops job listing (not a client product API; see docs/api-jobs-ops-surface.md). Source: `src/app/api/jobs/route.ts`. - `/api/local-project-id` - Local project identity guard. Source: `src/app/api/local-project-id/route.ts`. - `/api/medications` - Route discovered from app directory Source: `src/app/api/medications/route.ts`. - `/api/medications/[slug]` - Route discovered from app directory Source: `src/app/api/medications/[slug]/route.ts`. diff --git a/docs/wiring-conventions.md b/docs/wiring-conventions.md index ac278f386..241919252 100644 --- a/docs/wiring-conventions.md +++ b/docs/wiring-conventions.md @@ -96,5 +96,15 @@ Intentional exceptions are documented, not silenced: ## Known wiring debts Tracked in `docs/outstanding-issues.md` (`/issues`): the `/tools` vs `/?mode=tools` duplicate Tools -entry point, the unused `document-flow-routes.ts` href builders, the server-only `/api/jobs` endpoint, -and the un-built "coming soon" placeholders across forms/favourites. +entry point remains open (`#007`). + +### Closed wiring audits (2026-07-24) + +- **`/api/jobs` (`#009`)** — intentional administrator/ops listing, not a client product API. Product UI + uses `/api/ingestion/jobs`. Decision: `docs/api-jobs-ops-surface.md`. Keep the route; do not remove + without updating API contract tests and docs together. +- **Coming-soon placeholders (`#010`)** — audited forms refine/reset + Forms tab, favourites hub + sort/add/new-set, favourites command-library move/remove, and presentation Compact/Detailed density. + All use `disabled` or the `aria-disabled` + `title` + `sr-only` / `aria-describedby` pattern (or + presentational `ToggleSwitch` without `onToggle`). No fake-interactive controls found; leave + unwired until the underlying features land. Reference markup remains `favourites-hub.tsx`. diff --git a/scripts/generate-site-map.ts b/scripts/generate-site-map.ts index 2d6268159..1406dc1f8 100644 --- a/scripts/generate-site-map.ts +++ b/scripts/generate-site-map.ts @@ -122,7 +122,7 @@ const apiDescriptions: Record = { "/api/ingestion/jobs": "Ingestion job collection.", "/api/ingestion/jobs/[id]/retry": "Retry ingestion job.", "/api/ingestion/quality": "Ingestion quality reporting.", - "/api/jobs": "Job state.", + "/api/jobs": "Administrator/ops job listing (not a client product API; see docs/api-jobs-ops-surface.md).", "/api/local-project-id": "Local project identity guard.", "/api/registry/records": "Registry record collection.", "/api/registry/records/[slug]": "Registry record detail.", From f3986abc39468e077643611ec2d95e374c2e901f Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 24 Jul 2026 17:41:47 +0000 Subject: [PATCH 2/7] fix(ci): prettier ledger docs and drop stale PR_POLICY_BODY Static PR checks failed on Prettier for five docs files. Also remove leftover PR_POLICY_BODY.md from merged #1134 so Sync PR policy body stops overwriting this docs PR description. Co-authored-by: BigSimmo --- PR_POLICY_BODY.md | 33 --------- docs/codebase-index.md | 30 ++++----- docs/current-clinical-work-brief.md | 32 ++++----- docs/factsheets-reading-model-brief.md | 12 ++-- docs/outstanding-issues.md | 92 +++++++++++++------------- docs/rag-behaviour/README.md | 2 +- 6 files changed, 84 insertions(+), 117 deletions(-) delete mode 100644 PR_POLICY_BODY.md diff --git a/PR_POLICY_BODY.md b/PR_POLICY_BODY.md deleted file mode 100644 index 80864e873..000000000 --- a/PR_POLICY_BODY.md +++ /dev/null @@ -1,33 +0,0 @@ -## Summary - -- Fix cross-mode search performance findings: prescribing catalogue debounce/abort/`fields=index`, differentials abort/debounce, universal documents typeahead soft-timeout (750ms), shared `(search-app)` shell to avoid composer remount, and Answer rate-limit in-memory fallback outside production. -- Fix Bugbot regressions: shared-shell pathname navigation (`/services` → `/dsm`) syncs `searchMode` during render (no stale-mode paint) even when the query string is unchanged; extracted ClinicalDashboard lazy imports to stay under the maintainability budget. - -RAG impact: no retrieval behaviour change — typeahead documents domain timeout and shell URL sync only; ranking formulas and full `/api/search` retrieval path unchanged. - -## Verification - -- [x] `npm run verify:pr-local` — focused Vitest on touched sources (362) plus api-rate-limit / search-shell / universal / route / site-map suites green; `docs:check-index` OK -- [x] UI verification not run: full `verify:ui` not required for this pass; mode-home smoke via `npm run ensure` returned HTTP 200 for `/`, `/services`, `/dsm`, `/documents/search`, `/therapy-compass`, `/?mode=prescribing`, and `/api/answer/stream` returned 200 after the rate-limit fallback fix -- Verification not run: `eval:retrieval:latency` / soak / live OpenAI canary — approval-gated provider work; not needed for timeout-only typeahead change - -## Risk and rollout - -- Risk: medium — shared layout remount change and rate-limit fallback behaviour in non-production; production Answer/upload still fail closed when the durable limiter is unavailable -- Rollback: revert this PR; mode routes return to per-segment `GlobalSearchShell` layouts and prior timeout/fallback behaviour -- Provider or production effects: None - -## Clinical Governance Preflight - -- [x] Source-backed claims still require linked source verification before clinical use -- [x] No patient-identifiable document workflow was introduced or expanded without explicit governance approval -- [x] Supabase target remains `[REDACTED]` (`[REDACTED]`) -- [x] Service-role keys and private document access remain server-only -- [x] Demo/synthetic content remains clearly separated from real clinical sources -- [x] Source metadata, review status, and outdated/unknown-source behavior remain conservative -- [x] Deployment classification/TGA SaMD impact was checked when clinical decision-support behavior changed - -## Notes - -- Prescribing list rows keep the full catalogue payload so Safety/Monitoring filters and patient alerts still see section-derived signals; keystroke storms are controlled by debounce + abort. `fields=index` remains for identity-only consumers (cross-mode links). -- Live hybrid RPC cold tails remain a separate approval-gated follow-up. diff --git a/docs/codebase-index.md b/docs/codebase-index.md index cda78cbd3..7780c78b7 100644 --- a/docs/codebase-index.md +++ b/docs/codebase-index.md @@ -76,21 +76,21 @@ Structured map for AI agents and onboarding. For live routes, see `docs/site-map ### API routes (`src/app/api/`) -| Area | Routes | Entry files | -| ------------- | ------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | -| Account | `/api/account/favourites`, `/api/account/preferences` | `account/` | -| Answers | `/api/answer`, `/api/answer/stream`, `/api/answer-feedback` | `answer/route.ts`, `answer/stream/route.ts`, `answer-feedback/` | -| Search | `/api/search`, `/api/search/interaction`, `/api/search/universal` | `search/` | -| Upload | `/api/upload` | `upload/route.ts` | -| Documents | `/api/documents`, `/api/documents/[id]`, bulk/reindex, labels, reviews, search, signed URLs, summaries, table facts | `documents/` | -| Differentials | `/api/differentials`, `/api/differentials/[slug]`, `/api/differentials/presentations/[slug]` | `differentials/` | -| Medications | `/api/medications`, `/api/medications/[slug]` | `medications/` | -| Ingestion | `/api/ingestion/batches`, `/api/ingestion/jobs`, retry, quality | `ingestion/` | -| Registry | `/api/registry/records`, `/api/registry/records/[slug]` | `registry/records/` | -| Images | `/api/images/[id]/signed-url` | `images/[id]/signed-url/route.ts` | -| Ops | `/api/health`, `/api/health/ready`, `/api/setup-status`, `/api/local-project-id` | `health/`, `setup-status/`, `local-project-id/` | -| Eval / jobs | `/api/eval-cases`; `/api/jobs` (admin/ops listing — see `docs/api-jobs-ops-surface.md`; UI uses `/api/ingestion/jobs`) | `eval-cases/`, `jobs/` | -| Webhooks | `/api/webhooks/railway`, `/api/webhooks/supabase/document-change` (inbound; secret-gated — see docs/webhooks.md) | `webhooks/` | +| Area | Routes | Entry files | +| ------------- | ---------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | +| Account | `/api/account/favourites`, `/api/account/preferences` | `account/` | +| Answers | `/api/answer`, `/api/answer/stream`, `/api/answer-feedback` | `answer/route.ts`, `answer/stream/route.ts`, `answer-feedback/` | +| Search | `/api/search`, `/api/search/interaction`, `/api/search/universal` | `search/` | +| Upload | `/api/upload` | `upload/route.ts` | +| Documents | `/api/documents`, `/api/documents/[id]`, bulk/reindex, labels, reviews, search, signed URLs, summaries, table facts | `documents/` | +| Differentials | `/api/differentials`, `/api/differentials/[slug]`, `/api/differentials/presentations/[slug]` | `differentials/` | +| Medications | `/api/medications`, `/api/medications/[slug]` | `medications/` | +| Ingestion | `/api/ingestion/batches`, `/api/ingestion/jobs`, retry, quality | `ingestion/` | +| Registry | `/api/registry/records`, `/api/registry/records/[slug]` | `registry/records/` | +| Images | `/api/images/[id]/signed-url` | `images/[id]/signed-url/route.ts` | +| Ops | `/api/health`, `/api/health/ready`, `/api/setup-status`, `/api/local-project-id` | `health/`, `setup-status/`, `local-project-id/` | +| Eval / jobs | `/api/eval-cases`; `/api/jobs` (admin/ops listing — see `docs/api-jobs-ops-surface.md`; UI uses `/api/ingestion/jobs`) | `eval-cases/`, `jobs/` | +| Webhooks | `/api/webhooks/railway`, `/api/webhooks/supabase/document-change` (inbound; secret-gated — see docs/webhooks.md) | `webhooks/` | --- diff --git a/docs/current-clinical-work-brief.md b/docs/current-clinical-work-brief.md index 4dbc36fbf..ccfca1fda 100644 --- a/docs/current-clinical-work-brief.md +++ b/docs/current-clinical-work-brief.md @@ -21,22 +21,22 @@ Adjacent shipping surfaces today: Favourites / Saved workflows (`/favourites`, T ## Users -| Actor | Need | -| ----- | ---- | -| Authenticated clinician | Resume interrupted multi-step reference work across sessions/devices | -| Guest / anonymous | **Out of scope** for durable Current Clinical Work (align with Favourites gating) | -| Administrator / ops | Not a consumer; may need retention/deletion tooling if server persistence exists | +| Actor | Need | +| ----------------------- | --------------------------------------------------------------------------------- | +| Authenticated clinician | Resume interrupted multi-step reference work across sessions/devices | +| Guest / anonymous | **Out of scope** for durable Current Clinical Work (align with Favourites gating) | +| Administrator / ops | Not a consumer; may need retention/deletion tooling if server persistence exists | ## Data classes (privacy) Classify before any persistence design. Prefer the Safety Plan / PIA posture: **no patient identifiers**, identifier-free working content only. -| Class | Examples | Sensitivity | Allowed persistence (draft policy) | -| ----- | -------- | ----------- | ---------------------------------- | -| A — Navigation husks | Tool ids, mode hrefs, last-opened route | Low | Server or device OK if owner-scoped | -| B — Clinical working selections | Compare slugs, pinned document ids, formulation section ids | Medium (workflow, not PHI by itself) | Owner-scoped server OK with retention | -| C — Free-text working notes | Formulation prose, comparison notes, untitled drafts | **High incidental PHI risk** | Prefer tab-local or explicit “save draft” with retention + deletion; never default-sync raw text to logs/providers | -| D — Source pins | Document ids / titles already in corpus | Medium | Owner-scoped; titles may be corpus public | +| Class | Examples | Sensitivity | Allowed persistence (draft policy) | +| ------------------------------- | ----------------------------------------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------ | +| A — Navigation husks | Tool ids, mode hrefs, last-opened route | Low | Server or device OK if owner-scoped | +| B — Clinical working selections | Compare slugs, pinned document ids, formulation section ids | Medium (workflow, not PHI by itself) | Owner-scoped server OK with retention | +| C — Free-text working notes | Formulation prose, comparison notes, untitled drafts | **High incidental PHI risk** | Prefer tab-local or explicit “save draft” with retention + deletion; never default-sync raw text to logs/providers | +| D — Source pins | Document ids / titles already in corpus | Medium | Owner-scoped; titles may be corpus public | **Hard stop:** do not implement cross-device sync of Class C until privacy/#053 counsel path accepts retention, residency, and deletion semantics. Do not send Class C to OpenAI as a “workspace restore” side channel. @@ -50,11 +50,11 @@ Classify before any persistence design. Prefer the Safety Plan / PIA posture: ** ## Cross-device expectations -| Option | Pros | Cons | Recommendation | -| ------ | ---- | ---- | -------------- | -| Tab-local only | Matches Safety Plan; lowest privacy risk | No multi-device resume | Default until demand proven | -| Device localStorage | Survives refresh | No cross-device; XSS/shared-device risk | Acceptable for Class A only | -| Owner-scoped Supabase rows | Real resume | Retention, RLS, deletion, PHI incident surface | Only after demand + Class C policy | +| Option | Pros | Cons | Recommendation | +| -------------------------- | ---------------------------------------- | ---------------------------------------------- | ---------------------------------- | +| Tab-local only | Matches Safety Plan; lowest privacy risk | No multi-device resume | Default until demand proven | +| Device localStorage | Survives refresh | No cross-device; XSS/shared-device risk | Acceptable for Class A only | +| Owner-scoped Supabase rows | Real resume | Retention, RLS, deletion, PHI incident surface | Only after demand + Class C policy | **Product default for v0:** tab-local / URL state; no new tables. diff --git a/docs/factsheets-reading-model-brief.md b/docs/factsheets-reading-model-brief.md index 3b8fd6e14..b8b899d53 100644 --- a/docs/factsheets-reading-model-brief.md +++ b/docs/factsheets-reading-model-brief.md @@ -8,12 +8,12 @@ Future patient-content work **extends the existing Factsheets reading model** (E ## Current model (keep) -| Piece | Location / behaviour | -| ----- | -------------------- | -| Mode home / search / detail | `/factsheets`, `/factsheets/search`, `/factsheets/[slug]` | -| Reading levels | `easy` \| `standard` toggle on med-rich detail (`factsheet-detail-page.tsx`) | -| Content fields | `whatEasy` / `whatStandard` (and related section bodies) in `factsheets-data.ts` | -| Presentation contracts | Existing accessibility, print/PDF, and theme tokens on the Factsheets surface | +| Piece | Location / behaviour | +| --------------------------- | -------------------------------------------------------------------------------- | +| Mode home / search / detail | `/factsheets`, `/factsheets/search`, `/factsheets/[slug]` | +| Reading levels | `easy` \| `standard` toggle on med-rich detail (`factsheet-detail-page.tsx`) | +| Content fields | `whatEasy` / `whatStandard` (and related section bodies) in `factsheets-data.ts` | +| Presentation contracts | Existing accessibility, print/PDF, and theme tokens on the Factsheets surface | The Easy Read / Standard control is already a first-class reading-level switch, not a separate product mode. diff --git a/docs/outstanding-issues.md b/docs/outstanding-issues.md index d22b3dee0..cf6265545 100644 --- a/docs/outstanding-issues.md +++ b/docs/outstanding-issues.md @@ -94,52 +94,52 @@ removed after current-main verification; it is not missing recommended work. > > **RAG reconciliation correction (2026-07-23):** fresh current-main live evidence supersedes the broad diagnosis in #018. The three named misses are not one composer defect. Lithium reproduced an unrelated-table retrieval fast-path defect; ADHD still retrieves a relevant chart-heavy CAMHS source but exhausts the extractive route budget; metabolic retrieves the correct AKG source but selects schedule-free prose; #019 remains post-retrieval comparison source selection. A narrow lithium subject-evidence guard improved its targeting result from 0 to 1 with golden recall 1.0 and no reciprocal-rank regressions, but was reverted and rejected because the required full canary failed. Keep #029 open for the remaining fallback-stub cases. Do not combine these residuals or change ranking scores, comparator ordering, aliases, clamps, or semantic reranking without a separate reproducer and passing canary pair. -| ID | Pri | Type | Summary | Detail / next action | Source | Added | -| ---- | --- | ----- | --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | -| #059 | P1 | task | Verify containment of every credential reported exposed in chat | **Outcome:** every reported exposed credential is rejected or retired. **Next:** in approved security windows, verify and revoke or rotate the GitHub token, OpenAI key, Supabase service-role JWT, database password, and E2E credential; create replacements only when required and update only intended secret stores. **Success:** provider evidence confirms the old credentials cannot authenticate, replacements are distinct and minimally scoped, presence/readiness checks pass, and secret scans remain clean. **Stop:** no provider or secret-store action without approval; never print or paste values into Git, logs, issues, or chat. | session 2026-07-24 security reconciliation; AI Agent Target Manifest | 2026-07-24 | -| #064 | P2 | task | Reconcile the preserved browser and contrast patch | **Outcome:** the isolated dirty formulation/contrast patch is safely landed or explicitly dispositioned. **Next:** rebase its intent against current `main` without overwriting the worktree, then run focused Playwright coverage and `verify:ui`. **Success:** intended disabled/contrast behavior is accessible, browser assertions remain meaningful, and unrelated work is preserved. **Stop:** do not discard or auto-merge the dirty worktree; pause on ambiguous ownership or scope. | `agent/formulation-disabled-contrast`; session 2026-07-24 | 2026-07-24 | -| #065 | P2 | task | Complete the paused compact document source-text accordion | **Outcome:** the document viewer uses compact nested disclosures while retaining complete text, citation/search navigation, print behavior, and composer clearance. **Next:** only when the user explicitly resumes, reconcile `codex/chat-document-text-accordion-7cb4` with current `main` and complete the focused 320/390/1280 px tests. **Success:** default disclosures are closed; deep links and search open only the active passage; printing expands/restores state; no overflow. **Verify:** focused document-viewer Playwright, `verify:cheap`, `verify:ui`, and static production-readiness. **Stop:** remain paused until explicit user return; no provider calls. | paused document-viewer task; `codex/chat-document-text-accordion-7cb4` | 2026-07-24 | -| #066 | P2 | task | Land and prove the streamlined six-item sidebar | Implementation and the corrected Therapy wiring assertion are recoverable from remote branch `origin/codex/sidebar-test-fix-20260723` at full commit `cd54e68fbf7b07b5dffe3220e36af2caa528da54`; fetch it in a fresh checkout with `git fetch origin refs/heads/codex/sidebar-test-fix-20260723`. Focused sidebar/favourites suites pass 18/18. Remaining: run `verify:pr-local`, start the app and inspect desktop/tablet/mobile plus short-height scrolling and keyboard/focus behavior, run `verify:ui`, production build and bundle-budget checks, then open/merge the PR and prove the exact content is on `origin/main`. | remote branch `origin/codex/sidebar-test-fix-20260723`; commit `cd54e68fbf7b07b5dffe3220e36af2caa528da54`; session 2026-07-24 | 2026-07-24 | -| #067 | P2 | issue | Reconciliation preflight test times out under full-suite load | **Outcome:** the reconciliation preflight subprocess test is deterministic under the repository's serialized heavy-test workflow. During PR #1119 validation, the 30-second test timeout occurred twice under loaded full-suite execution, while the isolated file passed 5/5 and a separate `verify:cheap` full suite passed. **Next:** reproduce with timing around subprocess startup, output and teardown, then fix the smallest proven harness lifecycle cause. **Success:** repeated focused and full-suite runs complete without extending the global timeout. **Stop:** do not hide the cause by raising broad timeouts, adding retries, or bypassing the shared test lock. | `tests/reconciliation-preflight.test.ts`; PR #1119 validation; session 2026-07-24 | 2026-07-24 | -| #051 | P2 | task | Stabilise the live answer-quality canary before more RAG tuning | Diagnostics landed in PR #1095: structured JSON/Markdown artifacts now record the actual checked-out SHA, run identity and latency context, and the offline trend tool separates content, provider-route and latency outcomes. First validating run `30018289898` recorded the expected tree and cost, with 36/36 retrieval green, but one report cannot establish variability; PR #1097 prevents a single failure being mislabeled as repeated. Next: compare the scheduled 2026-07-26 structured report with this run. Do not spend on an immediate retry or reapply the archived lithium guard before that comparison. | PR #1095; run `30018289898`; PR #1097; archive ref `refs/archive/rejected-rag/20260723/monitoring-subject-gate` | 2026-07-23 | -| #001 | P2 | task | Semantic reranking still gated off | `RAG_SEMANTIC_RERANK_ENABLED=false` from PR #901. Do not enable until the provider-backed 36/36 retrieval-quality gate **and** an ambiguity-focused canary are explicitly approved and recorded. | `docs/process-hardening.md` (Semantic reranking rollout debt); PR #901 | 2026-07-21 | -| #069 | P3 | task | Live-profile table-facts plpgsql+EXECUTE latency | Migration `20260724120000_table_facts_plpgsql_execute.sql` plus P3 follow-ups (`20260724130000_*`, `20260724130100_*`) are in PR #1133. Hosted apply is blocked in this environment (no `SUPABASE_DB_URL`; Supabase MCP `needsAuth`). A live `profile:retrieval --rpc match_document_table_facts_text --analyze` attempt returned `Unregistered API key` against the injected service-role secret. **Next:** operator applies the three pending migrations on the live target project, then re-runs approval-gated `profile:retrieval` / `explain_retrieval_rpc` and confirms ~70ms-class plans with no ranking change. **Stop** without mutating ranking. | session 2026-07-24 Database interface audit; PR #1133 | 2026-07-24 | -| #053 | P1 | task | Execute cross-border privacy/legal package | Execute OpenAI and Railway DPAs; decide ZDR and Australian data residency; obtain prompt-cache behavior in writing; review subprocessors; obtain APP 8 and APP 5/1 counsel sign-off. Do not represent the release as privacy-approved or alter final public privacy wording before sign-off. | `docs/openai-cross-border-basis.md`; `docs/privacy-impact-assessment.md` | 2026-07-24 | -| #054 | P2 | task | Reconcile local and hosted secrets/config | Presence-check safety-identifier, query-hash, deep-probe, Supabase service-role, OpenAI, project-identity, and schedule settings; set only confirmed gaps with distinct per-environment values. Never record secret values. Provider reads/writes require approval. | `.env.example`; production-readiness warning; `docs/operator-backlog.md` | 2026-07-24 | -| #055 | P2 | task | Run one exact-SHA full release and PR gate | Before the next full-confidence release/handoff, record the candidate/PR SHA and run the local/provider release gates, Firefox/WebKit, required hosted CI, and actionable GitHub review-thread closure once. Stop at the first actionable failure and rerun only the repaired smallest gate. | `docs/launch-operator-runbook.md`; `docs/codex-review-protocol.md` | 2026-07-24 | -| #056 | P2 | task | Provision isolated staging environment | After explicit cost/ownership approval, provision `Clinical KB Staging` Supabase and Railway tiers with distinct secrets and synthetic/non-clinical data. Verify identity, schema, indexing, health, and the production-data boundary. | `docs/staging-setup.md`; `docs/operator-backlog.md` | 2026-07-24 | -| #057 | P2 | task | Complete staging soak and rollback rehearsal | After #056, run the documented soak and rollback against an exact candidate; retain latency/error/rollback evidence. Stop on unsafe data, identity mismatch, or an unowned rollback decision. | `docs/launch-operator-runbook.md`; `docs/capacity-review.md` | 2026-07-24 | -| #058 | P2 | task | Verify production content before any seed write | Against `the live target project`, verify registry, differentials, and medications surfaces are non-empty before writing. Seed only confirmed gaps idempotently with approved owner/project identity and confirmation flags. | `docs/launch-operator-runbook.md`; `docs/operator-backlog.md` | 2026-07-24 | -| #005 | P3 | rec | `finalScore` saturates at clamp ceiling | Base + ~40 stacked boosts routinely exceed 1.0, so strong matches tie at 1.0 and order by an arbitrary `document_id` tiebreak. If ranking is ever revisited, break ties by the **pre-clamp** score rather than raising the `[0,1]` ceiling (downstream gates assume `[0,1]`). Ordering already sorts by the unbounded pre-clamp `rankScore` (`clinical-search.ts:1735,1927,1950-1955`), so the clamp confines only the reported confidence value, not result order. Not a defect on the current golden set; any change here is a protected RAG surface (canary required). | `docs/rag-hybrid-findings-and-todo.md` P1 item 4; `src/lib/clinical-search.ts:1735` | 2026-07-21 | -| #007 | P3 | rec | `/tools` vs `/?mode=tools` parallel Tools entry points | `/tools` (standalone `ApplicationsLauncherPage`) has no inbound in-app link; the sidebar Tools item uses `/?mode=tools`. Decide the canonical entry point and wire nav consistently, or drop the standalone `/tools` page + `/applications` redirect. Currently allowlisted in `tests/route-reachability.test.ts`. | `src/app/tools/page.tsx`; `src/app/applications/route.ts` | 2026-07-21 | -| #011 | P3 | task | Auth DB-connection allocation is operator-only | Supabase Auth (GoTrue) is capped at ~10 absolute DB connections (Supabase perf advisor). Switch to **percentage-based** allocation in the Supabase **dashboard** before the first compute scale-up — **not settable via SQL/MCP** (operator-owned). Verify via a staging soak + an approval-gated read-only advisor re-check. | `docs/auth-connection-cap-runbook.md`; `docs/process-hardening.md` (Known follow-up debts) | 2026-07-21 | -| #012 | P3 | rec | Slim the lazy cross-mode differentials chunk | `cross-mode-differentials.ts` is dynamically imported (correctly code-split **out** of the initial/dashboard bundle — verified), but it pulls the full ~860 KB differentials snapshot (~125 KB gzip lazy chunk) just to build a tiny `{slug,title,clinicalHinge}` + presentations + aliases catalog. A precomputed lightweight index (generator + drift check, like the `specifiers-content` split / medications `fields=index`) would cut that lazy chunk ~5–10×. Not a bundle leak — an M-effort slim. | `src/lib/cross-mode-differentials.ts`; `src/components/clinical-dashboard/cross-mode-links.tsx:150`; session 2026-07-21 (build:analyze) | 2026-07-21 | -| #013 | P3 | rec | Route-chunk + mockup catalogue JSON weight | `build:analyze`: `/specifiers` ships `specifiers-search-index.json` (~180 KB parsed), `/forms` ships `forms-catalog.json` (~132 KB), `/formulation` ships `formulation-content.json` (~52 KB, client-side local search — needs index/full split or a search endpoint, architectural). All route-scoped (not initial bundle). Also `*-mockups.tsx` (~100 KB across chunks) build though `/mockups` 404s in prod — exclude from the prod artifact. | session 2026-07-21 (build:analyze) | 2026-07-21 | -| #016 | P3 | rec | "Big but not easy" structural + motion perf | Deferred larger levers: (a) nonce-CSP forces every product route to `ƒ Dynamic` (zero static generation) — evaluate Partial Prerendering / static shells for the static clinical catalogues (DSM/differentials/therapy/specifiers/formulation); (b) sidebar expand/collapse animates `grid-template-columns` (biggest smoothness cost, motion-gated — needs a transform-overlay rethink); (c) Therapy Compass fetches 692 KB / 2.5 MB JSON client-side (defer until interaction + confirm brotli); (d) settings/setup/admin dialogs static-imported into the home chunk (`next/dynamic` them). | session 2026-07-21 (build route table + design audit) | 2026-07-21 | -| #017 | P3 | task | Field Web-Vitals baseline via live Lighthouse | In-sandbox runtime vitals were blocked (prod server hard-requires Supabase secrets; dev-mode CLS measured excellent at 0.00–0.04, content-first pages 0.000). Run Lighthouse against `psychiatry.tools` for real LCP/INP/CLS to prioritize #012–#016 by measured impact rather than reasoning. | session 2026-07-21 (measurement pass) | 2026-07-21 | -| #018 | P2 | task | Split the lithium, ADHD and metabolic residuals by mechanism | Revalidated on current main 2026-07-23: these are not one composer defect. Lithium reproduced an unrelated-table retrieval fast-path defect; ADHD retrieves a relevant chart-heavy CAMHS source but exhausts the extractive route budget; metabolic retrieves the correct AKG source but selects schedule-free prose. The narrow lithium subject-evidence guard improved targeting from 0 to 1 with golden recall 1.0 and no reciprocal-rank regressions, but it was reverted because the full canary failed. After #051 stabilises the canary, add independent current-main reproducers and assess each mechanism separately. Do not widen the matcher or combine these into a broad ranking/composer change. | runs `30007833352` and `30009207429`; PR #1093; session 2026-07-23 | 2026-07-21 | -| #019 | P2 | task | Admission doc dropped after deterministic comparison packing | Reconfirmed on merged-main run `30018289898`: golden retrieval remained 36/36 and retrieved `MHSP.AdmissionCommunityPts.pdf`, but the answer's top five sources retained only `MHSP.Discharge.pdf` after `generation_fallback:generation_quality_failed; comparison_source_extractive_fallback`. PR #1096 replays the live score/order shape and proves deterministic answer ranking plus cross-document packing retain both admission and discharge evidence, so retrieval scores, aliases and comparator ordering are not the fix. Next: create a red fallback-layer unit reproducer using the live source shape; any behavior change still needs the existing baseline and a passing post canary. | run `30018289898`; PR #1096; session 2026-07-23 | 2026-07-21 | -| #021 | P3 | rec | E-3d H2 residual: strong/comparison generation discards | approx. 6 generation attempts per full 44-case run still fail the final quality gate and fall to extractive on strong-route comparison/complex shapes (the designed-conservative outcome). PARKED: weakest cost/benefit on the queue — a wave (approx. $2-4 pair + reviewer cycle) to shave seconds off a few hard cases. Revisit only if latency/waste complaints or a cheaper lever appears. | E-3c design record; runs #59-#61 diagnostics | 2026-07-21 | -| #022 | P2 | task | Source-governance metadata refresh (operator) | **Worklist generated 2026-07-22 ($0, read-only): `docs/source-governance-refresh-worklist-2026-07-22.md`.** Reframed - this is NOT 59 clinical reviews. Of the 124 documents surfacing in canary top results, 59 are review-required, and **38 (64 pct) are the BMJ published-reference tier all sitting at `clinical_validation_status: unverified`** - one attestation-policy decision, not 38 reviews. The remaining 21 are genuine local WA health-service reviews (FSH 7, NMHS 4, CAMHS 3, AKG 2, KEMH 2, RPBG 2, RKPG 1), mostly `document_status: review_due`. Burn-down: top-10 documents clear 44 pct of flagged slots, top-20 clear 66 pct. Next: decide the BMJ attestation policy, then attest local docs by visibility (start `Clozapine Management by GP (NMHS)`, 22 slots at rank 1). | runs #61/#57 Source Governance data; `docs/source-governance-refresh-worklist-2026-07-22.md` | 2026-07-21 | -| #023 | P2 | task | Read Sunday 2026-07-26 scheduled-run artifacts | The 18:00 UTC scheduled runs deliver three free datapoints at once: first full-44 weekly canary (validates the #1044 ANSWER_CASE_LIMIT raise), browser-matrix flake second datapoint (webkit ui-route-coverage now reproduced + root-caused 2026-07-22 → see #024; firefox ui-formulation:91 still awaits a datapoint), and the irrelevant@10 labeling-audit artifact (§3.1 human-decision class). Read all three, then disposition. | sessions 2026-07-20/21; branch-review-ledger convergence notes | 2026-07-21 | -| #024 | P3 | issue | WebKit e2e `_rsc`-prefetch access-control-checks errors | verify:release:offline on `main` ce32fe170 (2026-07-22) reproduced #023's webkit clause: **6/6 deterministic** failures in `tests/ui-route-coverage.spec.ts` (Therapy Compass; DSM home/comparison; Specifier comparison/map; Differential stream), each a `pageerror … ?_rsc=… due to access control checks` on Next.js RSC prefetch — Chromium + Firefox clean. Not merge-blocking (required gate `test:e2e:pr` is chromium-only; the full webkit matrix is advisory/release-time). Most likely a Playwright route-interception × WebKit interaction, not a Safari user defect. Next: decide (a) allow/mock the `_rsc` routes for the `webkit` e2e project, or (b) confirm real Safari impact — before trusting the full-matrix webkit gate at release. NB the 2 other webkit fails (`ui-stress:412`, `ui-universal-search:210`) passed on isolated re-run = true flake. | session 2026-07-22 (verify:release:offline, `main` ce32fe170); refines #023 | 2026-07-22 | -| #025 | P2 | task | Activate the three webhooks (operator secrets) | Merged (#968/#1100) + deployed but inert — verified live: `POST /api/webhooks/railway` returns `503 webhook_not_configured`; the Supabase document-change trigger exists but lacks both activation inputs. To turn on: (1) Railway → set `RAILWAY_WEBHOOK_SECRET` + add the `?token=…` webhook URL; (2) set `SLACK_WEBHOOK_URL`/`DISCORD_WEBHOOK_URL` in BOTH the Railway **app/server env** and **GitHub repo secrets**; (3) set one matching document-change secret in the Railway app env as `SUPABASE_INGESTION_WEBHOOK_SECRET` and in Supabase Vault as `ingestion_webhook_secret`, then set the per-environment database GUC `app.ingestion_webhook_base_url` to the deployed app origin. Each path fails closed until fully configured, so this is pure ops. See `docs/webhooks.md` for verification and rotation. | sessions 2026-07-22/24; PRs #968/#1100; docs/webhooks.md | 2026-07-22 | -| #027 | P3 | rec | External uptime monitor independent of GitHub/Railway | `live-domain-monitor.yml` runs on GitHub's cron, so it won't run in exactly the outage it should catch (Actions or the deploy itself down). Add an off-platform synthetic monitor (UptimeRobot / Better Stack / Checkly) hitting `/api/health` with a webhook alert. Provider setup, not code. | session 2026-07-22 webhook review | 2026-07-22 | -| #028 | P3 | rec | Runtime error tracking (Sentry or similar) | No error tracking in the repo — production exceptions on `psychiatry.tools`, including how often `RAG_PROVIDER_MODE=auto` silently degrades to source-only, are invisible. Weigh adding `@sentry/nextjs` (dependency + DSN secret + instrumentation) vs cost; alert → chat/issue. Provider-backed; needs explicit sign-off before adding the dependency. | session 2026-07-22 webhook review | 2026-07-22 | -| #029 | P2 | issue | 12 of 30 answer-quality cases return the fallback stub | run #61 --dump-answers: 12/30 quality cases emit the source_backed_review_fallback boilerplate with answer_sections: [], all grounded with 4-6 citations. Some still PASS targeting because the stub echoes query keywords (the contraindication/document_lookup matchers need only a keyword), so the targeting metric MASKS the problem for those intents. Superset of #018 — fix in the extractive composer, validate with the provider-backed answer eval. | run #61 dump artifact; session 2026-07-22 | 2026-07-22 | -| #030 | P2 | issue | Wide-tier alias lets one doc satisfy both comparison slots | In src/lib/eval-document-matching.ts, "Admission to Discharge for Mental Health Inpatients" appears in BOTH the AdmissionCommunityPts and Discharge alias lists, so a single document can satisfy both expectedFiles slots and make allHit true — a latent false-pass on admission-discharge cases. Not firing today (that doc is not in the failing top-5) but it would mask a real miss. Tighten the tables so one doc cannot fill both sides. | src/lib/eval-document-matching.ts:32-65; session 2026-07-22 | 2026-07-22 | -| #033 | P3 | rec | Source governance metadata absent from the LLM prompt | `buildRagSourceBlock` omits `document_status`, `clinical_validation_status`, and `extraction_quality`, so the model cannot self-caveat during generation and governance is enforced only post-hoc. Generation-surface change: needs `eval:rag` plus `eval:quality --rag-only` (grounded-supported must not drop, citation-failure 0) and explicit approval. Carries the same "unknown ≠ bad" hazard as #032 — on a partially-enriched corpus the model would likely over-caveat correct sources, so design the prompt wording before spending an eval. | `src/lib/rag/rag-source-block.ts:126-198`; PR #1051 audit item 8 | 2026-07-22 | -| #035 | P3 | rec | Threshold-conflict detection covers only 3 params | `detectThresholdDisagreements` checks only ANC, WBC, and platelets paired with withholding verbs, so cross-source conflicts on medication doses, lithium/thyroid levels, or vital signs go undetected. Deliberately narrow (see the comment at `:469-474`). Broadening changes when an answer is classified `conflicting` and adds warnings — real false-positive risk. Needs new fixtures plus a behaviour review before any change. | `src/lib/evidence.ts:469-574`; PR #1051 audit item 7 | 2026-07-22 | -| #036 | P3 | rec | 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 promotion migrations but never used as a retrieval filter. Promotion is unconditional on `clinical_validation_status`, so unverified documents are publicly searchable — compensated by keeping `unverified_source` in the frontend-visible warning set. A hard schema flag touches RLS and the clinical-risk-gated retrieval RPCs; weigh against the existing compensating control before acting. | `supabase/schema.sql:61-108`; `src/lib/search-scope.ts:181-236`; PR #1051 audit item 3 | 2026-07-22 | -| #037 | P3 | rec | D5 trust-cap-all-claims flag parked OFF | `NEXT_PUBLIC_RAG_TRUST_CAP_ALL_CLAIMS` extends authority gating from high-risk claims to **all** supported claims (`deriveTrust`). Ships OFF by design; flipping it caps trust to `medium` for routine claims across the board — a product/clinical-UX decision, not a defect. Both states are test-pinned. Next action: product decision, then flip and re-baseline the UI expectations. | `src/lib/answer-render-policy.ts:159-177`; PR #1051 audit item 11 | 2026-07-22 | -| #038 | P3 | rec | Consolidate shared comparison behavior | Several clinical modes expose comparison workflows with similar selection, empty-state and mobile-dock needs. Define one shared behavioral contract before another comparison surface is added; keep mode-specific clinical content separate. This is a design-system recommendation, not a current defect. | design audit reconciliation; session 2026-07-22 | 2026-07-22 | -| #039 | P3 | rec | Consolidate catalogue toolbar patterns | Catalogue/search pages have independently evolved filter, sort, result-count and mobile toolbar behavior. Inventory the existing implementations and converge only the repeated interaction contract; do not flatten mode-specific search semantics. | design audit reconciliation; session 2026-07-22 | 2026-07-22 | -| #040 | P3 | rec | Add targeted visual-regression baselines | Keep a small approved baseline set for high-value desktop/mobile surfaces and accessibility modes instead of screenshotting every route. Start with account/settings, document viewer, mode homes and bottom-composer interactions; define an intentional-update workflow before enabling blocking comparisons. | design audit reconciliation; session 2026-07-22 | 2026-07-22 | -| #075 | P2 | issue | Search-scope label enumeration can truncate after 1,000 rows | **Outcome:** every owner-visible source label can participate in scoped search without silently dropping rows at the Supabase response cap. **Next:** reproduce on current `main` with more than 1,000 distinct labels, then add bounded deterministic pagination and a focused multi-page regression. **Verify:** search-scope unit/API contracts, offline RAG contracts, `verify:cheap`, and production-readiness. **Stop:** do not replay mixed PR #1132, widen aliases, change ranking, or run a live canary unless the isolated fix demonstrably changes protected retrieval behaviour. | PR #1132 (`src/lib/search-scope.ts`, `tests/search-scope.test.ts`); primary reconciliation 2026-07-24 | 2026-07-24 | -| #076 | P3 | task | Reproduce malformed fallback PDF image/table crops | **Outcome:** a real current-main fixture proves whether fallback images or table crops are malformed before retention/storage behaviour changes. **Next:** capture one minimal authorised fixture, identify the exact extraction stage and expected geometry, and add a red Python/DOM regression. **Success:** the smallest fix preserves valid assets within existing count/byte budgets and signed-image privacy boundaries. **Stop:** do not merge broad PR #1129, arbitrary crop thresholds/padding, storage expansion, or timeout increases without the reproducer and budget evidence. | PR #1129; `worker/python/extract_pdf_assets.py`; `src/lib/image-filtering.ts`; primary reconciliation 2026-07-24 | 2026-07-24 | -| #077 | P2 | issue | Concurrent tasks can re-dirty the canonical primary checkout | **Outcome:** `C:\Dev\Apps\Database` remains a clean synchronization target while write work happens in task-owned worktrees. **Next:** add a cooperative owner/lease check to task-start and lifecycle transitions; before a primary write, branch switch, fast-forward, or cleanup, report owner, dirty state, and Git operation markers and fail closed on an active owner. Include stale-lease recovery. **Success:** a focused concurrency test refuses a second primary writer while read-only commands and separate worktrees continue normally. **Stop:** do not add an OS-wide lock, kill processes, discard existing dirty files, or serialize independent feature worktrees. | primary re-dirtied by another active task immediately after reconciliation proof; session 2026-07-24 | 2026-07-24 | -| #078 | P3 | task | Generate a deterministic reconciliation evidence pack | **Outcome:** one report-only command produces the final local evidence now assembled manually. **Next:** extend the reconciliation lifecycle with an explicit output path and include the frozen base/HEAD, per-worktree dispositions, operation markers resolved through Git, archive refs, bundle path/size/SHA-256/verify result, retained worktree count, and local/base tree equality. Accept remote PR state only as explicit approved input. **Success:** fixture tests prove deterministic output and redaction; an interrupted run leaves no false completion record. **Stop:** never fetch, call GitHub/providers, inspect secret values, mutate refs, or delete work implicitly. | `scripts/reconciliation-preflight.mjs`; `docs/reconciliation-playbook.md`; session 2026-07-24 | 2026-07-24 | -| #079 | P3 | task | Disposition retained worktrees in bounded cleanup batches | **Outcome:** the retained reconciliation tail is gradually classified without another disruptive all-worktree sweep. **Next:** process no more than ten worktrees per explicitly scheduled pass using current owner/process metadata, open-PR state, exact review-ledger coverage, ancestry, and cherry-pick-aware content proof. **Success:** remove only clean, inactive, bundled worktrees whose content is merged or explicitly rejected; record every disposition and retain recovery evidence. **Stop:** preserve dirty, active, secret-bearing, post-freeze, paused, or ambiguous work and never use reset, force deletion, broad clean, or process killing. | final reconciliation inventory retained 104 independent worktrees; session 2026-07-24 | 2026-07-24 | +| ID | Pri | Type | Summary | Detail / next action | Source | Added | +| ---- | --- | ----- | --------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ---------- | +| #059 | P1 | task | Verify containment of every credential reported exposed in chat | **Outcome:** every reported exposed credential is rejected or retired. **Next:** in approved security windows, verify and revoke or rotate the GitHub token, OpenAI key, Supabase service-role JWT, database password, and E2E credential; create replacements only when required and update only intended secret stores. **Success:** provider evidence confirms the old credentials cannot authenticate, replacements are distinct and minimally scoped, presence/readiness checks pass, and secret scans remain clean. **Stop:** no provider or secret-store action without approval; never print or paste values into Git, logs, issues, or chat. | session 2026-07-24 security reconciliation; AI Agent Target Manifest | 2026-07-24 | +| #064 | P2 | task | Reconcile the preserved browser and contrast patch | **Outcome:** the isolated dirty formulation/contrast patch is safely landed or explicitly dispositioned. **Next:** rebase its intent against current `main` without overwriting the worktree, then run focused Playwright coverage and `verify:ui`. **Success:** intended disabled/contrast behavior is accessible, browser assertions remain meaningful, and unrelated work is preserved. **Stop:** do not discard or auto-merge the dirty worktree; pause on ambiguous ownership or scope. | `agent/formulation-disabled-contrast`; session 2026-07-24 | 2026-07-24 | +| #065 | P2 | task | Complete the paused compact document source-text accordion | **Outcome:** the document viewer uses compact nested disclosures while retaining complete text, citation/search navigation, print behavior, and composer clearance. **Next:** only when the user explicitly resumes, reconcile `codex/chat-document-text-accordion-7cb4` with current `main` and complete the focused 320/390/1280 px tests. **Success:** default disclosures are closed; deep links and search open only the active passage; printing expands/restores state; no overflow. **Verify:** focused document-viewer Playwright, `verify:cheap`, `verify:ui`, and static production-readiness. **Stop:** remain paused until explicit user return; no provider calls. | paused document-viewer task; `codex/chat-document-text-accordion-7cb4` | 2026-07-24 | +| #066 | P2 | task | Land and prove the streamlined six-item sidebar | Implementation and the corrected Therapy wiring assertion are recoverable from remote branch `origin/codex/sidebar-test-fix-20260723` at full commit `cd54e68fbf7b07b5dffe3220e36af2caa528da54`; fetch it in a fresh checkout with `git fetch origin refs/heads/codex/sidebar-test-fix-20260723`. Focused sidebar/favourites suites pass 18/18. Remaining: run `verify:pr-local`, start the app and inspect desktop/tablet/mobile plus short-height scrolling and keyboard/focus behavior, run `verify:ui`, production build and bundle-budget checks, then open/merge the PR and prove the exact content is on `origin/main`. | remote branch `origin/codex/sidebar-test-fix-20260723`; commit `cd54e68fbf7b07b5dffe3220e36af2caa528da54`; session 2026-07-24 | 2026-07-24 | +| #067 | P2 | issue | Reconciliation preflight test times out under full-suite load | **Outcome:** the reconciliation preflight subprocess test is deterministic under the repository's serialized heavy-test workflow. During PR #1119 validation, the 30-second test timeout occurred twice under loaded full-suite execution, while the isolated file passed 5/5 and a separate `verify:cheap` full suite passed. **Next:** reproduce with timing around subprocess startup, output and teardown, then fix the smallest proven harness lifecycle cause. **Success:** repeated focused and full-suite runs complete without extending the global timeout. **Stop:** do not hide the cause by raising broad timeouts, adding retries, or bypassing the shared test lock. | `tests/reconciliation-preflight.test.ts`; PR #1119 validation; session 2026-07-24 | 2026-07-24 | +| #051 | P2 | task | Stabilise the live answer-quality canary before more RAG tuning | Diagnostics landed in PR #1095: structured JSON/Markdown artifacts now record the actual checked-out SHA, run identity and latency context, and the offline trend tool separates content, provider-route and latency outcomes. First validating run `30018289898` recorded the expected tree and cost, with 36/36 retrieval green, but one report cannot establish variability; PR #1097 prevents a single failure being mislabeled as repeated. Next: compare the scheduled 2026-07-26 structured report with this run. Do not spend on an immediate retry or reapply the archived lithium guard before that comparison. | PR #1095; run `30018289898`; PR #1097; archive ref `refs/archive/rejected-rag/20260723/monitoring-subject-gate` | 2026-07-23 | +| #001 | P2 | task | Semantic reranking still gated off | `RAG_SEMANTIC_RERANK_ENABLED=false` from PR #901. Do not enable until the provider-backed 36/36 retrieval-quality gate **and** an ambiguity-focused canary are explicitly approved and recorded. | `docs/process-hardening.md` (Semantic reranking rollout debt); PR #901 | 2026-07-21 | +| #069 | P3 | task | Live-profile table-facts plpgsql+EXECUTE latency | Migration `20260724120000_table_facts_plpgsql_execute.sql` plus P3 follow-ups (`20260724130000_*`, `20260724130100_*`) are in PR #1133. Hosted apply is blocked in this environment (no `SUPABASE_DB_URL`; Supabase MCP `needsAuth`). A live `profile:retrieval --rpc match_document_table_facts_text --analyze` attempt returned `Unregistered API key` against the injected service-role secret. **Next:** operator applies the three pending migrations on the live target project, then re-runs approval-gated `profile:retrieval` / `explain_retrieval_rpc` and confirms ~70ms-class plans with no ranking change. **Stop** without mutating ranking. | session 2026-07-24 Database interface audit; PR #1133 | 2026-07-24 | +| #053 | P1 | task | Execute cross-border privacy/legal package | Execute OpenAI and Railway DPAs; decide ZDR and Australian data residency; obtain prompt-cache behavior in writing; review subprocessors; obtain APP 8 and APP 5/1 counsel sign-off. Do not represent the release as privacy-approved or alter final public privacy wording before sign-off. | `docs/openai-cross-border-basis.md`; `docs/privacy-impact-assessment.md` | 2026-07-24 | +| #054 | P2 | task | Reconcile local and hosted secrets/config | Presence-check safety-identifier, query-hash, deep-probe, Supabase service-role, OpenAI, project-identity, and schedule settings; set only confirmed gaps with distinct per-environment values. Never record secret values. Provider reads/writes require approval. | `.env.example`; production-readiness warning; `docs/operator-backlog.md` | 2026-07-24 | +| #055 | P2 | task | Run one exact-SHA full release and PR gate | Before the next full-confidence release/handoff, record the candidate/PR SHA and run the local/provider release gates, Firefox/WebKit, required hosted CI, and actionable GitHub review-thread closure once. Stop at the first actionable failure and rerun only the repaired smallest gate. | `docs/launch-operator-runbook.md`; `docs/codex-review-protocol.md` | 2026-07-24 | +| #056 | P2 | task | Provision isolated staging environment | After explicit cost/ownership approval, provision `Clinical KB Staging` Supabase and Railway tiers with distinct secrets and synthetic/non-clinical data. Verify identity, schema, indexing, health, and the production-data boundary. | `docs/staging-setup.md`; `docs/operator-backlog.md` | 2026-07-24 | +| #057 | P2 | task | Complete staging soak and rollback rehearsal | After #056, run the documented soak and rollback against an exact candidate; retain latency/error/rollback evidence. Stop on unsafe data, identity mismatch, or an unowned rollback decision. | `docs/launch-operator-runbook.md`; `docs/capacity-review.md` | 2026-07-24 | +| #058 | P2 | task | Verify production content before any seed write | Against `the live target project`, verify registry, differentials, and medications surfaces are non-empty before writing. Seed only confirmed gaps idempotently with approved owner/project identity and confirmation flags. | `docs/launch-operator-runbook.md`; `docs/operator-backlog.md` | 2026-07-24 | +| #005 | P3 | rec | `finalScore` saturates at clamp ceiling | Base + ~40 stacked boosts routinely exceed 1.0, so strong matches tie at 1.0 and order by an arbitrary `document_id` tiebreak. If ranking is ever revisited, break ties by the **pre-clamp** score rather than raising the `[0,1]` ceiling (downstream gates assume `[0,1]`). Ordering already sorts by the unbounded pre-clamp `rankScore` (`clinical-search.ts:1735,1927,1950-1955`), so the clamp confines only the reported confidence value, not result order. Not a defect on the current golden set; any change here is a protected RAG surface (canary required). | `docs/rag-hybrid-findings-and-todo.md` P1 item 4; `src/lib/clinical-search.ts:1735` | 2026-07-21 | +| #007 | P3 | rec | `/tools` vs `/?mode=tools` parallel Tools entry points | `/tools` (standalone `ApplicationsLauncherPage`) has no inbound in-app link; the sidebar Tools item uses `/?mode=tools`. Decide the canonical entry point and wire nav consistently, or drop the standalone `/tools` page + `/applications` redirect. Currently allowlisted in `tests/route-reachability.test.ts`. | `src/app/tools/page.tsx`; `src/app/applications/route.ts` | 2026-07-21 | +| #011 | P3 | task | Auth DB-connection allocation is operator-only | Supabase Auth (GoTrue) is capped at ~10 absolute DB connections (Supabase perf advisor). Switch to **percentage-based** allocation in the Supabase **dashboard** before the first compute scale-up — **not settable via SQL/MCP** (operator-owned). Verify via a staging soak + an approval-gated read-only advisor re-check. | `docs/auth-connection-cap-runbook.md`; `docs/process-hardening.md` (Known follow-up debts) | 2026-07-21 | +| #012 | P3 | rec | Slim the lazy cross-mode differentials chunk | `cross-mode-differentials.ts` is dynamically imported (correctly code-split **out** of the initial/dashboard bundle — verified), but it pulls the full ~860 KB differentials snapshot (~125 KB gzip lazy chunk) just to build a tiny `{slug,title,clinicalHinge}` + presentations + aliases catalog. A precomputed lightweight index (generator + drift check, like the `specifiers-content` split / medications `fields=index`) would cut that lazy chunk ~5–10×. Not a bundle leak — an M-effort slim. | `src/lib/cross-mode-differentials.ts`; `src/components/clinical-dashboard/cross-mode-links.tsx:150`; session 2026-07-21 (build:analyze) | 2026-07-21 | +| #013 | P3 | rec | Route-chunk + mockup catalogue JSON weight | `build:analyze`: `/specifiers` ships `specifiers-search-index.json` (~180 KB parsed), `/forms` ships `forms-catalog.json` (~132 KB), `/formulation` ships `formulation-content.json` (~52 KB, client-side local search — needs index/full split or a search endpoint, architectural). All route-scoped (not initial bundle). Also `*-mockups.tsx` (~100 KB across chunks) build though `/mockups` 404s in prod — exclude from the prod artifact. | session 2026-07-21 (build:analyze) | 2026-07-21 | +| #016 | P3 | rec | "Big but not easy" structural + motion perf | Deferred larger levers: (a) nonce-CSP forces every product route to `ƒ Dynamic` (zero static generation) — evaluate Partial Prerendering / static shells for the static clinical catalogues (DSM/differentials/therapy/specifiers/formulation); (b) sidebar expand/collapse animates `grid-template-columns` (biggest smoothness cost, motion-gated — needs a transform-overlay rethink); (c) Therapy Compass fetches 692 KB / 2.5 MB JSON client-side (defer until interaction + confirm brotli); (d) settings/setup/admin dialogs static-imported into the home chunk (`next/dynamic` them). | session 2026-07-21 (build route table + design audit) | 2026-07-21 | +| #017 | P3 | task | Field Web-Vitals baseline via live Lighthouse | In-sandbox runtime vitals were blocked (prod server hard-requires Supabase secrets; dev-mode CLS measured excellent at 0.00–0.04, content-first pages 0.000). Run Lighthouse against `psychiatry.tools` for real LCP/INP/CLS to prioritize #012–#016 by measured impact rather than reasoning. | session 2026-07-21 (measurement pass) | 2026-07-21 | +| #018 | P2 | task | Split the lithium, ADHD and metabolic residuals by mechanism | Revalidated on current main 2026-07-23: these are not one composer defect. Lithium reproduced an unrelated-table retrieval fast-path defect; ADHD retrieves a relevant chart-heavy CAMHS source but exhausts the extractive route budget; metabolic retrieves the correct AKG source but selects schedule-free prose. The narrow lithium subject-evidence guard improved targeting from 0 to 1 with golden recall 1.0 and no reciprocal-rank regressions, but it was reverted because the full canary failed. After #051 stabilises the canary, add independent current-main reproducers and assess each mechanism separately. Do not widen the matcher or combine these into a broad ranking/composer change. | runs `30007833352` and `30009207429`; PR #1093; session 2026-07-23 | 2026-07-21 | +| #019 | P2 | task | Admission doc dropped after deterministic comparison packing | Reconfirmed on merged-main run `30018289898`: golden retrieval remained 36/36 and retrieved `MHSP.AdmissionCommunityPts.pdf`, but the answer's top five sources retained only `MHSP.Discharge.pdf` after `generation_fallback:generation_quality_failed; comparison_source_extractive_fallback`. PR #1096 replays the live score/order shape and proves deterministic answer ranking plus cross-document packing retain both admission and discharge evidence, so retrieval scores, aliases and comparator ordering are not the fix. Next: create a red fallback-layer unit reproducer using the live source shape; any behavior change still needs the existing baseline and a passing post canary. | run `30018289898`; PR #1096; session 2026-07-23 | 2026-07-21 | +| #021 | P3 | rec | E-3d H2 residual: strong/comparison generation discards | approx. 6 generation attempts per full 44-case run still fail the final quality gate and fall to extractive on strong-route comparison/complex shapes (the designed-conservative outcome). PARKED: weakest cost/benefit on the queue — a wave (approx. $2-4 pair + reviewer cycle) to shave seconds off a few hard cases. Revisit only if latency/waste complaints or a cheaper lever appears. | E-3c design record; runs #59-#61 diagnostics | 2026-07-21 | +| #022 | P2 | task | Source-governance metadata refresh (operator) | **Worklist generated 2026-07-22 ($0, read-only): `docs/source-governance-refresh-worklist-2026-07-22.md`.** Reframed - this is NOT 59 clinical reviews. Of the 124 documents surfacing in canary top results, 59 are review-required, and **38 (64 pct) are the BMJ published-reference tier all sitting at `clinical_validation_status: unverified`** - one attestation-policy decision, not 38 reviews. The remaining 21 are genuine local WA health-service reviews (FSH 7, NMHS 4, CAMHS 3, AKG 2, KEMH 2, RPBG 2, RKPG 1), mostly `document_status: review_due`. Burn-down: top-10 documents clear 44 pct of flagged slots, top-20 clear 66 pct. Next: decide the BMJ attestation policy, then attest local docs by visibility (start `Clozapine Management by GP (NMHS)`, 22 slots at rank 1). | runs #61/#57 Source Governance data; `docs/source-governance-refresh-worklist-2026-07-22.md` | 2026-07-21 | +| #023 | P2 | task | Read Sunday 2026-07-26 scheduled-run artifacts | The 18:00 UTC scheduled runs deliver three free datapoints at once: first full-44 weekly canary (validates the #1044 ANSWER_CASE_LIMIT raise), browser-matrix flake second datapoint (webkit ui-route-coverage now reproduced + root-caused 2026-07-22 → see #024; firefox ui-formulation:91 still awaits a datapoint), and the irrelevant@10 labeling-audit artifact (§3.1 human-decision class). Read all three, then disposition. | sessions 2026-07-20/21; branch-review-ledger convergence notes | 2026-07-21 | +| #024 | P3 | issue | WebKit e2e `_rsc`-prefetch access-control-checks errors | verify:release:offline on `main` ce32fe170 (2026-07-22) reproduced #023's webkit clause: **6/6 deterministic** failures in `tests/ui-route-coverage.spec.ts` (Therapy Compass; DSM home/comparison; Specifier comparison/map; Differential stream), each a `pageerror … ?_rsc=… due to access control checks` on Next.js RSC prefetch — Chromium + Firefox clean. Not merge-blocking (required gate `test:e2e:pr` is chromium-only; the full webkit matrix is advisory/release-time). Most likely a Playwright route-interception × WebKit interaction, not a Safari user defect. Next: decide (a) allow/mock the `_rsc` routes for the `webkit` e2e project, or (b) confirm real Safari impact — before trusting the full-matrix webkit gate at release. NB the 2 other webkit fails (`ui-stress:412`, `ui-universal-search:210`) passed on isolated re-run = true flake. | session 2026-07-22 (verify:release:offline, `main` ce32fe170); refines #023 | 2026-07-22 | +| #025 | P2 | task | Activate the three webhooks (operator secrets) | Merged (#968/#1100) + deployed but inert — verified live: `POST /api/webhooks/railway` returns `503 webhook_not_configured`; the Supabase document-change trigger exists but lacks both activation inputs. To turn on: (1) Railway → set `RAILWAY_WEBHOOK_SECRET` + add the `?token=…` webhook URL; (2) set `SLACK_WEBHOOK_URL`/`DISCORD_WEBHOOK_URL` in BOTH the Railway **app/server env** and **GitHub repo secrets**; (3) set one matching document-change secret in the Railway app env as `SUPABASE_INGESTION_WEBHOOK_SECRET` and in Supabase Vault as `ingestion_webhook_secret`, then set the per-environment database GUC `app.ingestion_webhook_base_url` to the deployed app origin. Each path fails closed until fully configured, so this is pure ops. See `docs/webhooks.md` for verification and rotation. | sessions 2026-07-22/24; PRs #968/#1100; docs/webhooks.md | 2026-07-22 | +| #027 | P3 | rec | External uptime monitor independent of GitHub/Railway | `live-domain-monitor.yml` runs on GitHub's cron, so it won't run in exactly the outage it should catch (Actions or the deploy itself down). Add an off-platform synthetic monitor (UptimeRobot / Better Stack / Checkly) hitting `/api/health` with a webhook alert. Provider setup, not code. | session 2026-07-22 webhook review | 2026-07-22 | +| #028 | P3 | rec | Runtime error tracking (Sentry or similar) | No error tracking in the repo — production exceptions on `psychiatry.tools`, including how often `RAG_PROVIDER_MODE=auto` silently degrades to source-only, are invisible. Weigh adding `@sentry/nextjs` (dependency + DSN secret + instrumentation) vs cost; alert → chat/issue. Provider-backed; needs explicit sign-off before adding the dependency. | session 2026-07-22 webhook review | 2026-07-22 | +| #029 | P2 | issue | 12 of 30 answer-quality cases return the fallback stub | run #61 --dump-answers: 12/30 quality cases emit the source_backed_review_fallback boilerplate with answer_sections: [], all grounded with 4-6 citations. Some still PASS targeting because the stub echoes query keywords (the contraindication/document_lookup matchers need only a keyword), so the targeting metric MASKS the problem for those intents. Superset of #018 — fix in the extractive composer, validate with the provider-backed answer eval. | run #61 dump artifact; session 2026-07-22 | 2026-07-22 | +| #030 | P2 | issue | Wide-tier alias lets one doc satisfy both comparison slots | In src/lib/eval-document-matching.ts, "Admission to Discharge for Mental Health Inpatients" appears in BOTH the AdmissionCommunityPts and Discharge alias lists, so a single document can satisfy both expectedFiles slots and make allHit true — a latent false-pass on admission-discharge cases. Not firing today (that doc is not in the failing top-5) but it would mask a real miss. Tighten the tables so one doc cannot fill both sides. | src/lib/eval-document-matching.ts:32-65; session 2026-07-22 | 2026-07-22 | +| #033 | P3 | rec | Source governance metadata absent from the LLM prompt | `buildRagSourceBlock` omits `document_status`, `clinical_validation_status`, and `extraction_quality`, so the model cannot self-caveat during generation and governance is enforced only post-hoc. Generation-surface change: needs `eval:rag` plus `eval:quality --rag-only` (grounded-supported must not drop, citation-failure 0) and explicit approval. Carries the same "unknown ≠ bad" hazard as #032 — on a partially-enriched corpus the model would likely over-caveat correct sources, so design the prompt wording before spending an eval. | `src/lib/rag/rag-source-block.ts:126-198`; PR #1051 audit item 8 | 2026-07-22 | +| #035 | P3 | rec | Threshold-conflict detection covers only 3 params | `detectThresholdDisagreements` checks only ANC, WBC, and platelets paired with withholding verbs, so cross-source conflicts on medication doses, lithium/thyroid levels, or vital signs go undetected. Deliberately narrow (see the comment at `:469-474`). Broadening changes when an answer is classified `conflicting` and adds warnings — real false-positive risk. Needs new fixtures plus a behaviour review before any change. | `src/lib/evidence.ts:469-574`; PR #1051 audit item 7 | 2026-07-22 | +| #036 | P3 | rec | 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 promotion migrations but never used as a retrieval filter. Promotion is unconditional on `clinical_validation_status`, so unverified documents are publicly searchable — compensated by keeping `unverified_source` in the frontend-visible warning set. A hard schema flag touches RLS and the clinical-risk-gated retrieval RPCs; weigh against the existing compensating control before acting. | `supabase/schema.sql:61-108`; `src/lib/search-scope.ts:181-236`; PR #1051 audit item 3 | 2026-07-22 | +| #037 | P3 | rec | D5 trust-cap-all-claims flag parked OFF | `NEXT_PUBLIC_RAG_TRUST_CAP_ALL_CLAIMS` extends authority gating from high-risk claims to **all** supported claims (`deriveTrust`). Ships OFF by design; flipping it caps trust to `medium` for routine claims across the board — a product/clinical-UX decision, not a defect. Both states are test-pinned. Next action: product decision, then flip and re-baseline the UI expectations. | `src/lib/answer-render-policy.ts:159-177`; PR #1051 audit item 11 | 2026-07-22 | +| #038 | P3 | rec | Consolidate shared comparison behavior | Several clinical modes expose comparison workflows with similar selection, empty-state and mobile-dock needs. Define one shared behavioral contract before another comparison surface is added; keep mode-specific clinical content separate. This is a design-system recommendation, not a current defect. | design audit reconciliation; session 2026-07-22 | 2026-07-22 | +| #039 | P3 | rec | Consolidate catalogue toolbar patterns | Catalogue/search pages have independently evolved filter, sort, result-count and mobile toolbar behavior. Inventory the existing implementations and converge only the repeated interaction contract; do not flatten mode-specific search semantics. | design audit reconciliation; session 2026-07-22 | 2026-07-22 | +| #040 | P3 | rec | Add targeted visual-regression baselines | Keep a small approved baseline set for high-value desktop/mobile surfaces and accessibility modes instead of screenshotting every route. Start with account/settings, document viewer, mode homes and bottom-composer interactions; define an intentional-update workflow before enabling blocking comparisons. | design audit reconciliation; session 2026-07-22 | 2026-07-22 | +| #075 | P2 | issue | Search-scope label enumeration can truncate after 1,000 rows | **Outcome:** every owner-visible source label can participate in scoped search without silently dropping rows at the Supabase response cap. **Next:** reproduce on current `main` with more than 1,000 distinct labels, then add bounded deterministic pagination and a focused multi-page regression. **Verify:** search-scope unit/API contracts, offline RAG contracts, `verify:cheap`, and production-readiness. **Stop:** do not replay mixed PR #1132, widen aliases, change ranking, or run a live canary unless the isolated fix demonstrably changes protected retrieval behaviour. | PR #1132 (`src/lib/search-scope.ts`, `tests/search-scope.test.ts`); primary reconciliation 2026-07-24 | 2026-07-24 | +| #076 | P3 | task | Reproduce malformed fallback PDF image/table crops | **Outcome:** a real current-main fixture proves whether fallback images or table crops are malformed before retention/storage behaviour changes. **Next:** capture one minimal authorised fixture, identify the exact extraction stage and expected geometry, and add a red Python/DOM regression. **Success:** the smallest fix preserves valid assets within existing count/byte budgets and signed-image privacy boundaries. **Stop:** do not merge broad PR #1129, arbitrary crop thresholds/padding, storage expansion, or timeout increases without the reproducer and budget evidence. | PR #1129; `worker/python/extract_pdf_assets.py`; `src/lib/image-filtering.ts`; primary reconciliation 2026-07-24 | 2026-07-24 | +| #077 | P2 | issue | Concurrent tasks can re-dirty the canonical primary checkout | **Outcome:** `C:\Dev\Apps\Database` remains a clean synchronization target while write work happens in task-owned worktrees. **Next:** add a cooperative owner/lease check to task-start and lifecycle transitions; before a primary write, branch switch, fast-forward, or cleanup, report owner, dirty state, and Git operation markers and fail closed on an active owner. Include stale-lease recovery. **Success:** a focused concurrency test refuses a second primary writer while read-only commands and separate worktrees continue normally. **Stop:** do not add an OS-wide lock, kill processes, discard existing dirty files, or serialize independent feature worktrees. | primary re-dirtied by another active task immediately after reconciliation proof; session 2026-07-24 | 2026-07-24 | +| #078 | P3 | task | Generate a deterministic reconciliation evidence pack | **Outcome:** one report-only command produces the final local evidence now assembled manually. **Next:** extend the reconciliation lifecycle with an explicit output path and include the frozen base/HEAD, per-worktree dispositions, operation markers resolved through Git, archive refs, bundle path/size/SHA-256/verify result, retained worktree count, and local/base tree equality. Accept remote PR state only as explicit approved input. **Success:** fixture tests prove deterministic output and redaction; an interrupted run leaves no false completion record. **Stop:** never fetch, call GitHub/providers, inspect secret values, mutate refs, or delete work implicitly. | `scripts/reconciliation-preflight.mjs`; `docs/reconciliation-playbook.md`; session 2026-07-24 | 2026-07-24 | +| #079 | P3 | task | Disposition retained worktrees in bounded cleanup batches | **Outcome:** the retained reconciliation tail is gradually classified without another disruptive all-worktree sweep. **Next:** process no more than ten worktrees per explicitly scheduled pass using current owner/process metadata, open-PR state, exact review-ledger coverage, ancestry, and cherry-pick-aware content proof. **Success:** remove only clean, inactive, bundled worktrees whose content is merged or explicitly rejected; record every disposition and retain recovery evidence. **Stop:** preserve dirty, active, secret-bearing, post-freeze, paused, or ambiguous work and never use reset, force deletion, broad clean, or process killing. | final reconciliation inventory retained 104 independent worktrees; session 2026-07-24 | 2026-07-24 | ## Resolved / archive diff --git a/docs/rag-behaviour/README.md b/docs/rag-behaviour/README.md index 92bd3106b..7afb3595b 100644 --- a/docs/rag-behaviour/README.md +++ b/docs/rag-behaviour/README.md @@ -8,7 +8,7 @@ selection, release-ordering, or eval-ground-truth surface. | File | What it holds | | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `behaviour-map.md` | The verified mechanics: score imputation sites, the release comparator chains, the gate/threshold ladder, second-stage engagement rules, and which live cases exercise which path. | -| `refuted-approaches.md` | Live-refuted improvement attempts (feature-weight tuning, saturation-tail spread, governance ranking penalties/boosts) with numbers, post-mortems, and binding constraints. | +| `refuted-approaches.md` | Live-refuted improvement attempts (feature-weight tuning, saturation-tail spread, governance ranking penalties/boosts) with numbers, post-mortems, and binding constraints. | | `safeguards.md` | The protection stack: protected-surface list, the pr-policy `RAG impact:` gate, the source-pin contract test, the canary-pair protocol, and the regeneration procedures. | Standing rules (mirrored in `AGENTS.md` so every agent session inherits them): From f52039390230d7bb1fc80431bcd5e9b6c6a99ec8 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 24 Jul 2026 17:41:47 +0000 Subject: [PATCH 3/7] docs: record PR #1175 review ledger outcome Co-authored-by: BigSimmo --- docs/branch-review-ledger.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md index a694ec191..d8a65213b 100644 --- a/docs/branch-review-ledger.md +++ b/docs/branch-review-ledger.md @@ -760,3 +760,4 @@ This file is append-only. Never rewrite or delete an existing review record; app | 2026-07-25 | cursor/pr-babysit-bugbot-agents-6c52 (PR #1167) | ee44812aae9dad1973d8302eba5bfca5000dffb6 | Open-PR maintenance: review-thread fixes | Before: 8 unresolved Codex/CodeRabbit threads; branch current with main. After: target-head pinning, fresh-main verification, exact `cursor[bot]` identity checks, explicit mutation/provider authorization, direct reply-then-resolve semantics, and no-op ledger bookkeeping are documented. | Prettier check on both agent files pass; `git diff --check` pass; GitHub author probe confirmed `cursor[bot]` account type `Bot`; no provider-backed checks run. | | 2026-07-25 | codex/fix-merge-conflicts-and-ci-on-open-prs (PR #1170) | e979fc892f11a17b1a8f2ef1ab058ef40d629182 | Open-PR maintenance: CI fix + threads + drift | Before: Static PR checks failed because route-group moves made nine valid legacy `src/app/*` documentation references appear missing; 0 unresolved threads; branch already contained current main. After: docs-link resolution checks known App Router route groups and the focused failure is fixed. | `node scripts/check-docs-links.mjs` pass (1162 references); Prettier check pass; `git diff --check` pass; no provider-backed checks run. | | 2026-07-25 | cursor/search-performance-review-4ee9 (PR #1134) | 692834a86e612cc8b311dc6895e007f182f5c5b8 | Open-PR maintenance: superseded docs-link thread and clean main sync | Before: branch was behind current main with one outdated docs-link thread; its product tree already matched main. After: merged current main cleanly and verified the route-group-aware docs-link fix now covers legacy route references. RAG impact: no retrieval behaviour change — history sync and docs tooling verification only. | `node scripts/check-docs-links.mjs` pass (1154 references); clean merge-tree; no live RAG canary or provider-backed check run. | +| 2026-07-24 | PR #1175 / `cursor/ledger-009-010-032-041-063-519b` | f3986abc39468e077643611ec2d95e374c2e901f | PR review + CI fix (ledger docs #009/#010/#032/#041/#063) | FINDINGS FIXED. P1: Static PR checks failed on Prettier (5 docs). P1: leftover `PR_POLICY_BODY.md` from merged #1134 caused Sync PR policy body to overwrite this docs PR description with search-performance text — deleted the stale template. No P0. Product scope remains docs-only; gated brief follow-ups (wire coming-soon, Current Clinical Work storage, Factsheets second mode, governance ranking) correctly not implemented. Residual: human approving review once CI green. | Local: prettier --check on touched docs; ledger open/resolved/queue integrity for five IDs; no client fetch(`/api/jobs`); `verify:cheap` earlier on tip 95d68c6b. No OpenAI/Supabase writes. | From 47f1b8861bb1f51fd3e7566329e76b12aed9d111 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 24 Jul 2026 17:42:25 +0000 Subject: [PATCH 4/7] chore: restore PR #1175 description via PR_POLICY_BODY sync Temporary template so CI Sync PR policy body replaces the polluted search-performance description left from merged #1134. Co-authored-by: BigSimmo --- PR_POLICY_BODY.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 PR_POLICY_BODY.md diff --git a/PR_POLICY_BODY.md b/PR_POLICY_BODY.md new file mode 100644 index 000000000..45f3a2914 --- /dev/null +++ b/PR_POLICY_BODY.md @@ -0,0 +1,34 @@ +## Summary + +Closes outstanding-issues ledger items with docs/decision records only (no application or RAG behavior changes): + +- **#009** — Keep `GET /api/jobs` as intentional administrator/ops listing; product UI uses `/api/ingestion/jobs`. Decision: `docs/api-jobs-ops-surface.md`. +- **#010** — Audited coming-soon placeholders in forms/favourites/presentation; all honest `disabled` / `aria-disabled` (or presentational toggles). No fake-interactive controls; leave unwired. +- **#032** — Reinforce governance ranking penalties/boosts as **REFUTED** guardrail in `docs/rag-behaviour/*`. Do not implement. +- **#041** — Brief: extend Easy Read/Standard Factsheets model; no second patient-facing mode (`docs/factsheets-reading-model-brief.md`). +- **#063** — Brief: Current Clinical Work product/privacy/persistence; no storage/UI (`docs/current-clinical-work-brief.md`). + +Also fixes CI/PR hygiene found on review: + +- Prettier formatting on touched docs (Static PR checks failure). +- Removes leftover `PR_POLICY_BODY.md` from merged #1134 that had overwritten this PR description with unrelated search-performance text (this file is the temporary sync template for the correct body). + +`RAG impact: no retrieval behaviour change — docs/guardrail reinforcement and product briefs only; no edits under src/lib/rag/**, clinical-search, ranking, or eval fixtures.` + +## Verification + +- [x] `npm run verify:cheap` (passed on tip `95d68c6b`; 3318 tests) +- [x] `npx prettier --check` on touched docs after format fix +- [x] `npm run check:branch-review-ledger` +- UI verification not run: docs-only; no UI/routing/styling product changes +- Provider/eval gates not run: no retrieval/ranking/answer behavior change + +## Risk and rollout + +- Risk: Low — documentation, ledger archive, and PR-body template hygiene +- Rollback: Revert the docs commits +- Provider or production effects: None + +## Notes + +Recommended queue order gap closed after removing `#063`. Gated brief follow-ups (wire coming-soon features, Current Clinical Work storage/UI, second Factsheets mode, governance ranking) are intentionally **not** implemented. From 15a5d080a375635ca6ef042659fe8837d485c8e3 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 24 Jul 2026 17:44:08 +0000 Subject: [PATCH 5/7] chore: remove temporary PR_POLICY_BODY after description sync Keep the corrected PR #1175 description without leaving the sync template on the branch for merge to main. Co-authored-by: BigSimmo --- PR_POLICY_BODY.md | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 PR_POLICY_BODY.md diff --git a/PR_POLICY_BODY.md b/PR_POLICY_BODY.md deleted file mode 100644 index 45f3a2914..000000000 --- a/PR_POLICY_BODY.md +++ /dev/null @@ -1,34 +0,0 @@ -## Summary - -Closes outstanding-issues ledger items with docs/decision records only (no application or RAG behavior changes): - -- **#009** — Keep `GET /api/jobs` as intentional administrator/ops listing; product UI uses `/api/ingestion/jobs`. Decision: `docs/api-jobs-ops-surface.md`. -- **#010** — Audited coming-soon placeholders in forms/favourites/presentation; all honest `disabled` / `aria-disabled` (or presentational toggles). No fake-interactive controls; leave unwired. -- **#032** — Reinforce governance ranking penalties/boosts as **REFUTED** guardrail in `docs/rag-behaviour/*`. Do not implement. -- **#041** — Brief: extend Easy Read/Standard Factsheets model; no second patient-facing mode (`docs/factsheets-reading-model-brief.md`). -- **#063** — Brief: Current Clinical Work product/privacy/persistence; no storage/UI (`docs/current-clinical-work-brief.md`). - -Also fixes CI/PR hygiene found on review: - -- Prettier formatting on touched docs (Static PR checks failure). -- Removes leftover `PR_POLICY_BODY.md` from merged #1134 that had overwritten this PR description with unrelated search-performance text (this file is the temporary sync template for the correct body). - -`RAG impact: no retrieval behaviour change — docs/guardrail reinforcement and product briefs only; no edits under src/lib/rag/**, clinical-search, ranking, or eval fixtures.` - -## Verification - -- [x] `npm run verify:cheap` (passed on tip `95d68c6b`; 3318 tests) -- [x] `npx prettier --check` on touched docs after format fix -- [x] `npm run check:branch-review-ledger` -- UI verification not run: docs-only; no UI/routing/styling product changes -- Provider/eval gates not run: no retrieval/ranking/answer behavior change - -## Risk and rollout - -- Risk: Low — documentation, ledger archive, and PR-body template hygiene -- Rollback: Revert the docs commits -- Provider or production effects: None - -## Notes - -Recommended queue order gap closed after removing `#063`. Gated brief follow-ups (wire coming-soon features, Current Clinical Work storage/UI, second Factsheets mode, governance ranking) are intentionally **not** implemented. From 8d3deb87a23c3af1c306ae450bdcd448163e272b Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 24 Jul 2026 17:44:18 +0000 Subject: [PATCH 6/7] docs: supersede PR #1175 review ledger after body sync Co-authored-by: BigSimmo --- docs/branch-review-ledger.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md index d8a65213b..81f9d6446 100644 --- a/docs/branch-review-ledger.md +++ b/docs/branch-review-ledger.md @@ -761,3 +761,4 @@ This file is append-only. Never rewrite or delete an existing review record; app | 2026-07-25 | codex/fix-merge-conflicts-and-ci-on-open-prs (PR #1170) | e979fc892f11a17b1a8f2ef1ab058ef40d629182 | Open-PR maintenance: CI fix + threads + drift | Before: Static PR checks failed because route-group moves made nine valid legacy `src/app/*` documentation references appear missing; 0 unresolved threads; branch already contained current main. After: docs-link resolution checks known App Router route groups and the focused failure is fixed. | `node scripts/check-docs-links.mjs` pass (1162 references); Prettier check pass; `git diff --check` pass; no provider-backed checks run. | | 2026-07-25 | cursor/search-performance-review-4ee9 (PR #1134) | 692834a86e612cc8b311dc6895e007f182f5c5b8 | Open-PR maintenance: superseded docs-link thread and clean main sync | Before: branch was behind current main with one outdated docs-link thread; its product tree already matched main. After: merged current main cleanly and verified the route-group-aware docs-link fix now covers legacy route references. RAG impact: no retrieval behaviour change — history sync and docs tooling verification only. | `node scripts/check-docs-links.mjs` pass (1154 references); clean merge-tree; no live RAG canary or provider-backed check run. | | 2026-07-24 | PR #1175 / `cursor/ledger-009-010-032-041-063-519b` | f3986abc39468e077643611ec2d95e374c2e901f | PR review + CI fix (ledger docs #009/#010/#032/#041/#063) | FINDINGS FIXED. P1: Static PR checks failed on Prettier (5 docs). P1: leftover `PR_POLICY_BODY.md` from merged #1134 caused Sync PR policy body to overwrite this docs PR description with search-performance text — deleted the stale template. No P0. Product scope remains docs-only; gated brief follow-ups (wire coming-soon, Current Clinical Work storage, Factsheets second mode, governance ranking) correctly not implemented. Residual: human approving review once CI green. | Local: prettier --check on touched docs; ledger open/resolved/queue integrity for five IDs; no client fetch(`/api/jobs`); `verify:cheap` earlier on tip 95d68c6b. No OpenAI/Supabase writes. | +| 2026-07-24 | PR #1175 / `cursor/ledger-009-010-032-041-063-519b` | 15a5d080a375635ca6ef042659fe8837d485c8e3 | PR #1175 follow-up (description restore + template removal) | SUPERSEDES prior #1175 row on `f3986abc`. PR description restored via temporary `PR_POLICY_BODY.md` sync then file deleted again so merge will not reintroduce the #1134 leftover. Scope unchanged: docs-only ledger closeout. | Sync PR policy body SUCCESS with correct ledger summary; prettier clean on prior tip. Awaiting Static/Unit on final tip. No providers. | From 7c583025d1621a20ea2a9f3bad707f09dc67b698 Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Sat, 25 Jul 2026 13:23:42 +0800 Subject: [PATCH 7/7] style: prettier-format outstanding-issues after ledger merge --- docs/outstanding-issues.md | 170 ++++++++++++++++++------------------- 1 file changed, 85 insertions(+), 85 deletions(-) diff --git a/docs/outstanding-issues.md b/docs/outstanding-issues.md index bb674d16a..f84cc9390 100644 --- a/docs/outstanding-issues.md +++ b/docs/outstanding-issues.md @@ -48,43 +48,43 @@ removed after current-main verification; it is not missing recommended work. database/RAG/clinical/privacy expertise; Operator = named provider/product/legal authority. - **Estimate:** focused active time, excluding approval, hosted runtime, soak, and review waits. -| Order | ID(s) | Acuity | Capability | When | Estimate | Outcome, gate, verification, and stopping condition | -| ----: | ---------------------- | -------- | ------------------------------------------- | ---------------------------------------------------------------------- | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 1 | `#059` | A1 | Operator security + independent reviewer | Immediate approved security window | 1ΓÇô3 hours plus verification | Verify every reported exposed credential (GitHub, OpenAI, Supabase service role/database, E2E) is retired; rotate anything still valid and update only intended secret stores. Never record values; stop before provider action without approval. | +| Order | ID(s) | Acuity | Capability | When | Estimate | Outcome, gate, verification, and stopping condition | +| ----: | ---------------------- | -------- | --------------------------------------------- | ---------------------------------------------------------------------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | `#059` | A1 | Operator security + independent reviewer | Immediate approved security window | 1ΓÇô3 hours plus verification | Verify every reported exposed credential (GitHub, OpenAI, Supabase service role/database, E2E) is retired; rotate anything still valid and update only intended secret stores. Never record values; stop before provider action without approval. | | 2 | `#053` | A1 | Operator ΓÇö legal/privacy | Start now; finish before real patient use/privacy-approved release | 4ΓÇô8 hours internal; 1ΓÇô6 weeks elapsed | Execute DPAs; decide ZDR/residency; obtain cache behavior in writing; review subprocessors; obtain APP 8 and APP 5/1 counsel sign-off. Do not change public copy before approval. | -| 3 | `#067` | A3 | High ΓÇö test reliability | Next flake-hardening window | 1ΓÇô2 hours | Reproduce the load-sensitive reconciliation-preflight subprocess timeout, instrument its lifecycle, and make the smallest deterministic harness fix. Do not raise the global timeout or bypass the shared heavy-test lock without causal proof. | -| 4 | `#030`, `#075` | A2 | High ΓÇö search correctness | Decision-ready | 2ΓÇô4 hours each | Handle as separate PRs: #030 requires distinct source identities; #075 reproduces more than 1,000 labels and adds bounded pagination. Run focused contracts and `verify:cheap`; stop before alias, retrieval, or ranking changes without protected evidence. | -| 5 | `#069` | A3 | Specialist ΓÇö retrieval latency | After hosted apply of PR #1133 migrations; approval-gated live profile | 30ΓÇô60 min | Operator applies `20260724120000`/`20260724130000`/`20260724130100`, then re-profiles `match_document_table_facts_text` (~70ms-class plans). Stop without mutating ranking or unpaid evals. Cloud agent blocked: no DB URL / MCP auth; live profile hit Unregistered API key. | -| 6 | `#019` | A2 | Specialist ΓÇö RAG answer pipeline | Local reproducer now; behavior change after `#051`/`#023` | 0.5ΓÇô1 day reproducer | Reproduce admission-source loss in the fallback layer using PR #1096ΓÇÖs source shape. Any behavior change needs protected review and an approved baseline/post canary; stop if independently non-reproducible. | -| 7 | `#054` | A2 | Standard locally; Operator hosted | Local safety identifier now; hosted next approved window | 15ΓÇô30 min local; 1ΓÇô2 hours hosted | Presence-check and fill confirmed secret/config gaps with distinct per-environment values. Never record values. Require clean readiness/secret checks; stop on ambiguous environment or project identity. | +| 3 | `#067` | A3 | High ΓÇö test reliability | Next flake-hardening window | 1ΓÇô2 hours | Reproduce the load-sensitive reconciliation-preflight subprocess timeout, instrument its lifecycle, and make the smallest deterministic harness fix. Do not raise the global timeout or bypass the shared heavy-test lock without causal proof. | +| 4 | `#030`, `#075` | A2 | High ΓÇö search correctness | Decision-ready | 2ΓÇô4 hours each | Handle as separate PRs: #030 requires distinct source identities; #075 reproduces more than 1,000 labels and adds bounded pagination. Run focused contracts and `verify:cheap`; stop before alias, retrieval, or ranking changes without protected evidence. | +| 5 | `#069` | A3 | Specialist ΓÇö retrieval latency | After hosted apply of PR #1133 migrations; approval-gated live profile | 30ΓÇô60 min | Operator applies `20260724120000`/`20260724130000`/`20260724130100`, then re-profiles `match_document_table_facts_text` (~70ms-class plans). Stop without mutating ranking or unpaid evals. Cloud agent blocked: no DB URL / MCP auth; live profile hit Unregistered API key. | +| 6 | `#019` | A2 | Specialist ΓÇö RAG answer pipeline | Local reproducer now; behavior change after `#051`/`#023` | 0.5ΓÇô1 day reproducer | Reproduce admission-source loss in the fallback layer using PR #1096ΓÇÖs source shape. Any behavior change needs protected review and an approved baseline/post canary; stop if independently non-reproducible. | +| 7 | `#054` | A2 | Standard locally; Operator hosted | Local safety identifier now; hosted next approved window | 15ΓÇô30 min local; 1ΓÇô2 hours hosted | Presence-check and fill confirmed secret/config gaps with distinct per-environment values. Never record values. Require clean readiness/secret checks; stop on ambiguous environment or project identity. | | 8 | `#022` | A2 | Operator ΓÇö clinical governance + Specialist | Decision-ready | 1ΓÇô2 hours policy; 0.5ΓÇô1 day first ten | Decide BMJ attestation policy and review the ten highest-impact local documents. Record reviewer/evidence/time; stop after ten and remeasure warning debt. | -| 9 | `#051`, `#023` | A2 | Specialist ΓÇö RAG diagnostics | After scheduled 2026-07-26 run | 2ΓÇô4 hours | With GitHub-read approval, compare structured canary/browser/irrelevant-at-10 artifacts without dispatching a rerun. Record deterministic/provider/latency deltas and disposition residuals; stop without spending. | -| 10 | `#018` | A2 | Specialist ΓÇö clinical RAG/retrieval | After `#051`/`#023`, one mechanism at a time | 1ΓÇô2 days diagnosis | Give lithium, ADHD, and metabolic residuals separate current-main reproducers and candidates. Behavior canaries require approval; stop any item without a deterministic reproducer or on regression. | +| 9 | `#051`, `#023` | A2 | Specialist ΓÇö RAG diagnostics | After scheduled 2026-07-26 run | 2ΓÇô4 hours | With GitHub-read approval, compare structured canary/browser/irrelevant-at-10 artifacts without dispatching a rerun. Record deterministic/provider/latency deltas and disposition residuals; stop without spending. | +| 10 | `#018` | A2 | Specialist ΓÇö clinical RAG/retrieval | After `#051`/`#023`, one mechanism at a time | 1ΓÇô2 days diagnosis | Give lithium, ADHD, and metabolic residuals separate current-main reproducers and candidates. Behavior canaries require approval; stop any item without a deterministic reproducer or on regression. | | 11 | `#029` | A2 | Specialist ΓÇö answer quality/clinical safety | After `#051`/`#023` and `#018` | 0.5ΓÇô1 day inventory; 1ΓÇô3 days per fix | Re-enumerate current fallback stubs and fix one causal cluster at a time without weakening grounding/citation gates. Stop if a change merely makes the metric easier to pass. | -| 12 | `#001` | A2 | Specialist ΓÇö retrieval/ranking | After `#051`/`#023` and rollout approval | 0.5ΓÇô1 day plus canary | Keep semantic reranking off unless an approved ambiguity comparison preserves 36/36, recall 1.0, zero per-case regressions, and shows measured gain; otherwise record keep-off and stop. | -| 13 | `#025` | A2 | Operator ΓÇö Railway/GitHub/chat/Supabase | Next approved observability window | 1ΓÇô3 hours/channel | Choose owned deployment, CI, ingestion, and SLO alerts; mock first, then one approved controlled provider event/channel. The merged Supabase trigger remains inert until its verified inputs are configured. Stop without an accountable responder. | -| 14 | `#064` | A2 | High ΓÇö frontend/browser | After higher-acuity local fixes; before the release UI gate | 4ΓÇô8 hours | Preserve the isolated dirty formulation/contrast patch, reconcile its intent against current `main`, and run focused Playwright plus `verify:ui`. Stop rather than overwriting unrelated work or weakening access-control assertions. | -| 15 | `#055` | A2 | Specialist release owner + Operator | Before next full-confidence release/handoff | 2ΓÇô4 hours plus runtime | On one exact SHA, run local/provider gates, Firefox/WebKit, required hosted CI, and close actionable GitHub threads. Stop at first failure and rerun only the repaired smallest gate. | -| 16 | `#056` | A2 | Operator ΓÇö Supabase/Railway + Specialist | After cost/ownership approval | 0.5ΓÇô1 day | Provision isolated `Clinical KB Staging` with synthetic data and distinct secrets. Verify identity, schema, indexing, health, and data boundary; never copy production clinical documents. | -| 17 | `#057` | A2 | High ΓÇö release/SRE + Operator | After `#056` | 2ΓÇô4 hours plus soak | Run documented staging soak and rollback against an exact candidate. Retain latency/error/rollback evidence; stop on unsafe data, identity mismatch, or unowned rollback. | +| 12 | `#001` | A2 | Specialist ΓÇö retrieval/ranking | After `#051`/`#023` and rollout approval | 0.5ΓÇô1 day plus canary | Keep semantic reranking off unless an approved ambiguity comparison preserves 36/36, recall 1.0, zero per-case regressions, and shows measured gain; otherwise record keep-off and stop. | +| 13 | `#025` | A2 | Operator ΓÇö Railway/GitHub/chat/Supabase | Next approved observability window | 1ΓÇô3 hours/channel | Choose owned deployment, CI, ingestion, and SLO alerts; mock first, then one approved controlled provider event/channel. The merged Supabase trigger remains inert until its verified inputs are configured. Stop without an accountable responder. | +| 14 | `#064` | A2 | High ΓÇö frontend/browser | After higher-acuity local fixes; before the release UI gate | 4ΓÇô8 hours | Preserve the isolated dirty formulation/contrast patch, reconcile its intent against current `main`, and run focused Playwright plus `verify:ui`. Stop rather than overwriting unrelated work or weakening access-control assertions. | +| 15 | `#055` | A2 | Specialist release owner + Operator | Before next full-confidence release/handoff | 2ΓÇô4 hours plus runtime | On one exact SHA, run local/provider gates, Firefox/WebKit, required hosted CI, and close actionable GitHub threads. Stop at first failure and rerun only the repaired smallest gate. | +| 16 | `#056` | A2 | Operator ΓÇö Supabase/Railway + Specialist | After cost/ownership approval | 0.5ΓÇô1 day | Provision isolated `Clinical KB Staging` with synthetic data and distinct secrets. Verify identity, schema, indexing, health, and data boundary; never copy production clinical documents. | +| 17 | `#057` | A2 | High ΓÇö release/SRE + Operator | After `#056` | 2ΓÇô4 hours plus soak | Run documented staging soak and rollback against an exact candidate. Retain latency/error/rollback evidence; stop on unsafe data, identity mismatch, or unowned rollback. | | 18 | `#058` | A2 | Operator ΓÇö production data + Specialist | Next approved production verification window | 30ΓÇô60 min read-only; 1ΓÇô2 hours if needed | Verify registry/differentials/medications are non-empty before writing; seed only confirmed gaps idempotently. Stop when healthy or owner/project identity is ambiguous. | -| 19 | `#007` | A3 | Operator decision + Standard frontend | When product chooses canonical Tools route | 15ΓÇô30 min decision; 0.5 day | Align navigation, redirect, sitemap, and reachability around one entry point. Stop while the standalone page has an unresolved requirement. | -| 20 | `#011` | A3 | Operator ΓÇö Supabase capacity | Immediately before first compute scale-up | 30ΓÇô60 min plus observation | Switch Auth to percentage allocation, record before/after, and run approved advisor/health checks. Stop if no scale-up is planned. | -| 21 | `#017` | A3 | High ΓÇö performance/browser | Before `#012`/`#013`/`#016`; approved live-site window | 1ΓÇô2 hours | Capture reproducible mobile/desktop Lighthouse/Web-Vitals evidence and decide whether payload work is justified. Stop if metrics are acceptable or evidence is too noisy. | -| 22 | `#024` | A3 | High ΓÇö Next.js/Playwright/WebKit | After `#051`/`#023` or real Safari reproduction | 0.5ΓÇô1 day | Distinguish test interception from a Safari defect. Apply test-only correction only with a discriminating repro; keep access-control assertions meaningful. | -| 23 | `#033` | A3 | Specialist ΓÇö prompt/source governance | After `#022` and `#051`/`#023` | 1ΓÇô2 days plus approved eval | Design unknown-vs-adverse metadata wording and prompt tests. Require no supported-grounding drop and zero citation failures; stop on broad over-caveating or degradation. | -| 24 | `#037` | A3 | Operator ΓÇö clinical/product + Standard | Next trust-policy review | 30ΓÇô60 min; up to 0.5 day | Decide whether routine claims cap at medium trust. Record policy; if accepted, change only the flag/expectations and run focused tests. | -| 25 | `#012`, `#013`, `#016` | A3 | High ΓÇö bundling/runtime performance | After `#017` or equivalent evidence | 0.5ΓÇô2 days/route | Optimize only a production route with measured payload/render/motion harm. Require material gain plus focused, `verify:cheap`, and browser evidence; stop on small gain. | -| 26 | `#035` | A3 | Specialist ΓÇö evidence rules | After a demonstrated missed conflict | 0.5ΓÇô1 day design; code separate | Define a clinically reviewed conflict class with positive and negative fixtures. Stop if no bounded class can be shown; behavior change requires protected review. | -| 27 | `#027` | Optional | Operator ΓÇö SRE/provider | When an owned external alert path is wanted | 1ΓÇô2 hours | Decide vendor/cost/privacy/owner; if accepted, prove one non-PHI outage and recovery alert. Stop when no responder owns it. | -| 28 | `#028` | Optional | Specialist privacy/observability + Operator | After privacy/ownership/cost approval | 1ΓÇô3 days | Define vendor/region/retention/redaction/sampling/source-map envelope before SDK work. Prove no clinical text, identifiers, or secrets leave; stop if unacceptable. | -| 29 | `#038` | Optional | High ΓÇö product/design architecture | When a new comparison surface is approved | 0.5ΓÇô1 day | Define a shared interaction contract without flattening mode-specific content. Stop when no concrete new surface exists. | -| 30 | `#040` | Optional | High ΓÇö visual QA/accessibility | When baseline owner/update workflow exists | 1ΓÇô2 days | Establish a small stable desktop/mobile/accessibility baseline set. Do not make it blocking if flake or maintenance cost outweighs detection value. | +| 19 | `#007` | A3 | Operator decision + Standard frontend | When product chooses canonical Tools route | 15ΓÇô30 min decision; 0.5 day | Align navigation, redirect, sitemap, and reachability around one entry point. Stop while the standalone page has an unresolved requirement. | +| 20 | `#011` | A3 | Operator ΓÇö Supabase capacity | Immediately before first compute scale-up | 30ΓÇô60 min plus observation | Switch Auth to percentage allocation, record before/after, and run approved advisor/health checks. Stop if no scale-up is planned. | +| 21 | `#017` | A3 | High ΓÇö performance/browser | Before `#012`/`#013`/`#016`; approved live-site window | 1ΓÇô2 hours | Capture reproducible mobile/desktop Lighthouse/Web-Vitals evidence and decide whether payload work is justified. Stop if metrics are acceptable or evidence is too noisy. | +| 22 | `#024` | A3 | High ΓÇö Next.js/Playwright/WebKit | After `#051`/`#023` or real Safari reproduction | 0.5ΓÇô1 day | Distinguish test interception from a Safari defect. Apply test-only correction only with a discriminating repro; keep access-control assertions meaningful. | +| 23 | `#033` | A3 | Specialist ΓÇö prompt/source governance | After `#022` and `#051`/`#023` | 1ΓÇô2 days plus approved eval | Design unknown-vs-adverse metadata wording and prompt tests. Require no supported-grounding drop and zero citation failures; stop on broad over-caveating or degradation. | +| 24 | `#037` | A3 | Operator ΓÇö clinical/product + Standard | Next trust-policy review | 30ΓÇô60 min; up to 0.5 day | Decide whether routine claims cap at medium trust. Record policy; if accepted, change only the flag/expectations and run focused tests. | +| 25 | `#012`, `#013`, `#016` | A3 | High ΓÇö bundling/runtime performance | After `#017` or equivalent evidence | 0.5ΓÇô2 days/route | Optimize only a production route with measured payload/render/motion harm. Require material gain plus focused, `verify:cheap`, and browser evidence; stop on small gain. | +| 26 | `#035` | A3 | Specialist ΓÇö evidence rules | After a demonstrated missed conflict | 0.5ΓÇô1 day design; code separate | Define a clinically reviewed conflict class with positive and negative fixtures. Stop if no bounded class can be shown; behavior change requires protected review. | +| 27 | `#027` | Optional | Operator ΓÇö SRE/provider | When an owned external alert path is wanted | 1ΓÇô2 hours | Decide vendor/cost/privacy/owner; if accepted, prove one non-PHI outage and recovery alert. Stop when no responder owns it. | +| 28 | `#028` | Optional | Specialist privacy/observability + Operator | After privacy/ownership/cost approval | 1ΓÇô3 days | Define vendor/region/retention/redaction/sampling/source-map envelope before SDK work. Prove no clinical text, identifiers, or secrets leave; stop if unacceptable. | +| 29 | `#038` | Optional | High ΓÇö product/design architecture | When a new comparison surface is approved | 0.5ΓÇô1 day | Define a shared interaction contract without flattening mode-specific content. Stop when no concrete new surface exists. | +| 30 | `#040` | Optional | High ΓÇö visual QA/accessibility | When baseline owner/update workflow exists | 1ΓÇô2 days | Establish a small stable desktop/mobile/accessibility baseline set. Do not make it blocking if flake or maintenance cost outweighs detection value. | | 31 | `#039` | Optional | High ΓÇö frontend architecture | During a concrete catalogue-toolbar project | 0.5ΓÇô1 day inventory; 1ΓÇô3 days code | Converge only repeated toolbar behavior without flattening search semantics. Stop when there is no bounded implementation target. | -| 33 | `#065` | A2 | High ΓÇö document-viewer UI | Only when the user explicitly resumes the paused task | 0.5ΓÇô1.5 days | Finish the compact source-text accordion, citation/search auto-open, print restoration, and 320/390/1280 px coverage. Keep the preserved branch untouched until explicit resume; no provider calls. | -| 34 | `#077` | A3 | High ΓÇö workflow safety | Next workflow-hardening window | 1ΓÇô2 hours | Add a cooperative primary-checkout write lease/check that prevents a second task from writing, switching, or synchronizing the canonical checkout while another owner or dirty state exists. Keep read-only work and independent feature worktrees unblocked. | -| 35 | `#078` | A3 | Standard ΓÇö reconciliation tooling | After `#067`; before another broad reconciliation | 2ΓÇô4 hours | Generate one deterministic, secret-safe evidence pack from the reconciliation lifecycle: disposition rows, operation markers, archive refs, bundle verification, hashes, worktree counts, and local/base equality. Never fetch, call providers, or delete implicitly. | -| 36 | `#079` | Optional | High ΓÇö repository hygiene | In explicitly scheduled batches | 30ΓÇô60 minutes per batch | Disposition at most ten retained worktrees per pass using owner, PR, review-ledger, ancestry, and patch evidence. Preserve every dirty, active, secret-bearing, post-freeze, or ambiguous worktree and stop rather than broad-cleaning. | +| 33 | `#065` | A2 | High ΓÇö document-viewer UI | Only when the user explicitly resumes the paused task | 0.5ΓÇô1.5 days | Finish the compact source-text accordion, citation/search auto-open, print restoration, and 320/390/1280 px coverage. Keep the preserved branch untouched until explicit resume; no provider calls. | +| 34 | `#077` | A3 | High ΓÇö workflow safety | Next workflow-hardening window | 1ΓÇô2 hours | Add a cooperative primary-checkout write lease/check that prevents a second task from writing, switching, or synchronizing the canonical checkout while another owner or dirty state exists. Keep read-only work and independent feature worktrees unblocked. | +| 35 | `#078` | A3 | Standard ΓÇö reconciliation tooling | After `#067`; before another broad reconciliation | 2ΓÇô4 hours | Generate one deterministic, secret-safe evidence pack from the reconciliation lifecycle: disposition rows, operation markers, archive refs, bundle verification, hashes, worktree counts, and local/base equality. Never fetch, call providers, or delete implicitly. | +| 36 | `#079` | Optional | High ΓÇö repository hygiene | In explicitly scheduled batches | 30ΓÇô60 minutes per batch | Disposition at most ten retained worktrees per pass using owner, PR, review-ledger, ancestry, and patch evidence. Preserve every dirty, active, secret-bearing, post-freeze, or ambiguous worktree and stop rather than broad-cleaning. | @@ -96,51 +96,51 @@ removed after current-main verification; it is not missing recommended work. > > **RAG reconciliation correction (2026-07-23):** fresh current-main live evidence supersedes the broad diagnosis in #018. The three named misses are not one composer defect. Lithium reproduced an unrelated-table retrieval fast-path defect; ADHD still retrieves a relevant chart-heavy CAMHS source but exhausts the extractive route budget; metabolic retrieves the correct AKG source but selects schedule-free prose; #019 remains post-retrieval comparison source selection. A narrow lithium subject-evidence guard improved its targeting result from 0 to 1 with golden recall 1.0 and no reciprocal-rank regressions, but was reverted and rejected because the required full canary failed. Keep #029 open for the remaining fallback-stub cases. Do not combine these residuals or change ranking scores, comparator ordering, aliases, clamps, or semantic reranking without a separate reproducer and passing canary pair. -| ID | Pri | Type | Summary | Detail / next action | Source | Added | -| ---- | --- | ----- | --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | -| #059 | P1 | task | Verify containment of every credential reported exposed in chat | **Outcome:** every reported exposed credential is rejected or retired. **Next:** in approved security windows, verify and revoke or rotate the GitHub token, OpenAI key, Supabase service-role JWT, database password, and E2E credential; create replacements only when required and update only intended secret stores. **Success:** provider evidence confirms the old credentials cannot authenticate, replacements are distinct and minimally scoped, presence/readiness checks pass, and secret scans remain clean. **Stop:** no provider or secret-store action without approval; never print or paste values into Git, logs, issues, or chat. | session 2026-07-24 security reconciliation; AI Agent Target Manifest | 2026-07-24 | -| #064 | P2 | task | Reconcile the preserved browser and contrast patch | **Outcome:** the isolated dirty formulation/contrast patch is safely landed or explicitly dispositioned. **Next:** rebase its intent against current `main` without overwriting the worktree, then run focused Playwright coverage and `verify:ui`. **Success:** intended disabled/contrast behavior is accessible, browser assertions remain meaningful, and unrelated work is preserved. **Stop:** do not discard or auto-merge the dirty worktree; pause on ambiguous ownership or scope. | `agent/formulation-disabled-contrast`; session 2026-07-24 | 2026-07-24 | -| #065 | P2 | task | Complete the paused compact document source-text accordion | **Outcome:** the document viewer uses compact nested disclosures while retaining complete text, citation/search navigation, print behavior, and composer clearance. **Next:** only when the user explicitly resumes, reconcile `codex/chat-document-text-accordion-7cb4` with current `main` and complete the focused 320/390/1280 px tests. **Success:** default disclosures are closed; deep links and search open only the active passage; printing expands/restores state; no overflow. **Verify:** focused document-viewer Playwright, `verify:cheap`, `verify:ui`, and static production-readiness. **Stop:** remain paused until explicit user return; no provider calls. | paused document-viewer task; `codex/chat-document-text-accordion-7cb4` | 2026-07-24 | -| #066 | P2 | task | Land and prove the streamlined six-item sidebar | Implementation and the corrected Therapy wiring assertion are recoverable from remote branch `origin/codex/sidebar-test-fix-20260723` at full commit `cd54e68fbf7b07b5dffe3220e36af2caa528da54`; fetch it in a fresh checkout with `git fetch origin refs/heads/codex/sidebar-test-fix-20260723`. Focused sidebar/favourites suites pass 18/18. Remaining: run `verify:pr-local`, start the app and inspect desktop/tablet/mobile plus short-height scrolling and keyboard/focus behavior, run `verify:ui`, production build and bundle-budget checks, then open/merge the PR and prove the exact content is on `origin/main`. | remote branch `origin/codex/sidebar-test-fix-20260723`; commit `cd54e68fbf7b07b5dffe3220e36af2caa528da54`; session 2026-07-24 | 2026-07-24 | -| #067 | P2 | issue | Reconciliation preflight test times out under full-suite load | **Outcome:** the reconciliation preflight subprocess test is deterministic under the repository's serialized heavy-test workflow. During PR #1119 validation, the 30-second test timeout occurred twice under loaded full-suite execution, while the isolated file passed 5/5 and a separate `verify:cheap` full suite passed. **Next:** reproduce with timing around subprocess startup, output and teardown, then fix the smallest proven harness lifecycle cause. **Success:** repeated focused and full-suite runs complete without extending the global timeout. **Stop:** do not hide the cause by raising broad timeouts, adding retries, or bypassing the shared test lock. | `tests/reconciliation-preflight.test.ts`; PR #1119 validation; session 2026-07-24 | 2026-07-24 | -| #051 | P2 | task | Stabilise the live answer-quality canary before more RAG tuning | Diagnostics landed in PR #1095: structured JSON/Markdown artifacts now record the actual checked-out SHA, run identity and latency context, and the offline trend tool separates content, provider-route and latency outcomes. First validating run `30018289898` recorded the expected tree and cost, with 36/36 retrieval green, but one report cannot establish variability; PR #1097 prevents a single failure being mislabeled as repeated. Next: compare the scheduled 2026-07-26 structured report with this run. Do not spend on an immediate retry or reapply the archived lithium guard before that comparison. | PR #1095; run `30018289898`; PR #1097; archive ref `refs/archive/rejected-rag/20260723/monitoring-subject-gate` | 2026-07-23 | -| #001 | P2 | task | Semantic reranking still gated off | `RAG_SEMANTIC_RERANK_ENABLED=false` from PR #901. Do not enable until the provider-backed 36/36 retrieval-quality gate **and** an ambiguity-focused canary are explicitly approved and recorded. | `docs/process-hardening.md` (Semantic reranking rollout debt); PR #901 | 2026-07-21 | -| #069 | P3 | task | Live-profile table-facts plpgsql+EXECUTE latency | Migration `20260724120000_table_facts_plpgsql_execute.sql` plus P3 follow-ups (`20260724130000_*`, `20260724130100_*`) are in PR #1133. Hosted apply is blocked in this environment (no `SUPABASE_DB_URL`; Supabase MCP `needsAuth`). A live `profile:retrieval --rpc match_document_table_facts_text --analyze` attempt returned `Unregistered API key` against the injected service-role secret. **Next:** operator applies the three pending migrations on the live target project, then re-runs approval-gated `profile:retrieval` / `explain_retrieval_rpc` and confirms ~70ms-class plans with no ranking change. **Stop** without mutating ranking. | session 2026-07-24 Database interface audit; PR #1133 | 2026-07-24 | -| #053 | P1 | task | Execute cross-border privacy/legal package | Execute OpenAI and Railway DPAs; decide ZDR and Australian data residency; obtain prompt-cache behavior in writing; review subprocessors; obtain APP 8 and APP 5/1 counsel sign-off. Do not represent the release as privacy-approved or alter final public privacy wording before sign-off. | `docs/openai-cross-border-basis.md`; `docs/privacy-impact-assessment.md` | 2026-07-24 | -| #054 | P2 | task | Reconcile local and hosted secrets/config | Presence-check safety-identifier, query-hash, deep-probe, Supabase service-role, OpenAI, project-identity, and schedule settings; set only confirmed gaps with distinct per-environment values. Never record secret values. Provider reads/writes require approval. | `.env.example`; production-readiness warning; `docs/operator-backlog.md` | 2026-07-24 | -| #055 | P2 | task | Run one exact-SHA full release and PR gate | Before the next full-confidence release/handoff, record the candidate/PR SHA and run the local/provider release gates, Firefox/WebKit, required hosted CI, and actionable GitHub review-thread closure once. Stop at the first actionable failure and rerun only the repaired smallest gate. | `docs/launch-operator-runbook.md`; `docs/codex-review-protocol.md` | 2026-07-24 | -| #056 | P2 | task | Provision isolated staging environment | After explicit cost/ownership approval, provision `Clinical KB Staging` Supabase and Railway tiers with distinct secrets and synthetic/non-clinical data. Verify identity, schema, indexing, health, and the production-data boundary. | `docs/staging-setup.md`; `docs/operator-backlog.md` | 2026-07-24 | -| #057 | P2 | task | Complete staging soak and rollback rehearsal | After #056, run the documented soak and rollback against an exact candidate; retain latency/error/rollback evidence. Stop on unsafe data, identity mismatch, or an unowned rollback decision. | `docs/launch-operator-runbook.md`; `docs/capacity-review.md` | 2026-07-24 | -| #058 | P2 | task | Verify production content before any seed write | Against `the live target project`, verify registry, differentials, and medications surfaces are non-empty before writing. Seed only confirmed gaps idempotently with approved owner/project identity and confirmation flags. | `docs/launch-operator-runbook.md`; `docs/operator-backlog.md` | 2026-07-24 | -| #005 | P3 | rec | `finalScore` saturates at clamp ceiling | Base + ~40 stacked boosts routinely exceed 1.0, so strong matches tie at 1.0 and order by an arbitrary `document_id` tiebreak. If ranking is ever revisited, break ties by the **pre-clamp** score rather than raising the `[0,1]` ceiling (downstream gates assume `[0,1]`). Ordering already sorts by the unbounded pre-clamp `rankScore` (`clinical-search.ts:1735,1927,1950-1955`), so the clamp confines only the reported confidence value, not result order. Not a defect on the current golden set; any change here is a protected RAG surface (canary required). | `docs/rag-hybrid-findings-and-todo.md` P1 item 4; `src/lib/clinical-search.ts:1735` | 2026-07-21 | -| #007 | P3 | rec | `/tools` vs `/?mode=tools` parallel Tools entry points | `/tools` (standalone `ApplicationsLauncherPage`) has no inbound in-app link; the sidebar Tools item uses `/?mode=tools`. Decide the canonical entry point and wire nav consistently, or drop the standalone `/tools` page + `/applications` redirect. Currently allowlisted in `tests/route-reachability.test.ts`. | `src/app/tools/page.tsx`; `src/app/applications/route.ts` | 2026-07-21 | -| #011 | P3 | task | Auth DB-connection allocation is operator-only | Supabase Auth (GoTrue) is capped at ~10 absolute DB connections (Supabase perf advisor). Switch to **percentage-based** allocation in the Supabase **dashboard** before the first compute scale-up ΓÇö **not settable via SQL/MCP** (operator-owned). Verify via a staging soak + an approval-gated read-only advisor re-check. | `docs/auth-connection-cap-runbook.md`; `docs/process-hardening.md` (Known follow-up debts) | 2026-07-21 | -| #012 | P3 | rec | Slim the lazy cross-mode differentials chunk | `cross-mode-differentials.ts` is dynamically imported (correctly code-split **out** of the initial/dashboard bundle ΓÇö verified), but it pulls the full ~860 KB differentials snapshot (~125 KB gzip lazy chunk) just to build a tiny `{slug,title,clinicalHinge}` + presentations + aliases catalog. A precomputed lightweight index (generator + drift check, like the `specifiers-content` split / medications `fields=index`) would cut that lazy chunk ~5ΓÇô10├ù. Not a bundle leak ΓÇö an M-effort slim. | `src/lib/cross-mode-differentials.ts`; `src/components/clinical-dashboard/cross-mode-links.tsx:150`; session 2026-07-21 (build:analyze) | 2026-07-21 | -| #013 | P3 | rec | Route-chunk + mockup catalogue JSON weight | `build:analyze`: `/specifiers` ships `specifiers-search-index.json` (~180 KB parsed), `/forms` ships `forms-catalog.json` (~132 KB), `/formulation` ships `formulation-content.json` (~52 KB, client-side local search ΓÇö needs index/full split or a search endpoint, architectural). All route-scoped (not initial bundle). Also `*-mockups.tsx` (~100 KB across chunks) build though `/mockups` 404s in prod ΓÇö exclude from the prod artifact. | session 2026-07-21 (build:analyze) | 2026-07-21 | -| #016 | P3 | rec | "Big but not easy" structural + motion perf | Deferred larger levers: (a) nonce-CSP forces every product route to `╞Æ Dynamic` (zero static generation) ΓÇö evaluate Partial Prerendering / static shells for the static clinical catalogues (DSM/differentials/therapy/specifiers/formulation); (b) sidebar expand/collapse animates `grid-template-columns` (biggest smoothness cost, motion-gated ΓÇö needs a transform-overlay rethink); (c) Therapy Compass fetches 692 KB / 2.5 MB JSON client-side (defer until interaction + confirm brotli); (d) settings/setup/admin dialogs static-imported into the home chunk (`next/dynamic` them). | session 2026-07-21 (build route table + design audit) | 2026-07-21 | -| #017 | P3 | task | Field Web-Vitals baseline via live Lighthouse | In-sandbox runtime vitals were blocked (prod server hard-requires Supabase secrets; dev-mode CLS measured excellent at 0.00ΓÇô0.04, content-first pages 0.000). Run Lighthouse against `psychiatry.tools` for real LCP/INP/CLS to prioritize #012ΓÇô#016 by measured impact rather than reasoning. | session 2026-07-21 (measurement pass) | 2026-07-21 | -| #018 | P2 | task | Split the lithium, ADHD and metabolic residuals by mechanism | Revalidated on current main 2026-07-23: these are not one composer defect. Lithium reproduced an unrelated-table retrieval fast-path defect; ADHD retrieves a relevant chart-heavy CAMHS source but exhausts the extractive route budget; metabolic retrieves the correct AKG source but selects schedule-free prose. The narrow lithium subject-evidence guard improved targeting from 0 to 1 with golden recall 1.0 and no reciprocal-rank regressions, but it was reverted because the full canary failed. After #051 stabilises the canary, add independent current-main reproducers and assess each mechanism separately. Do not widen the matcher or combine these into a broad ranking/composer change. | runs `30007833352` and `30009207429`; PR #1093; session 2026-07-23 | 2026-07-21 | -| #019 | P2 | task | Admission doc dropped after deterministic comparison packing | Reconfirmed on merged-main run `30018289898`: golden retrieval remained 36/36 and retrieved `MHSP.AdmissionCommunityPts.pdf`, but the answer's top five sources retained only `MHSP.Discharge.pdf` after `generation_fallback:generation_quality_failed; comparison_source_extractive_fallback`. PR #1096 replays the live score/order shape and proves deterministic answer ranking plus cross-document packing retain both admission and discharge evidence, so retrieval scores, aliases and comparator ordering are not the fix. Next: create a red fallback-layer unit reproducer using the live source shape; any behavior change still needs the existing baseline and a passing post canary. | run `30018289898`; PR #1096; session 2026-07-23 | 2026-07-21 | -| #021 | P3 | rec | E-3d H2 residual: strong/comparison generation discards | approx. 6 generation attempts per full 44-case run still fail the final quality gate and fall to extractive on strong-route comparison/complex shapes (the designed-conservative outcome). PARKED: weakest cost/benefit on the queue ΓÇö a wave (approx. $2-4 pair + reviewer cycle) to shave seconds off a few hard cases. Revisit only if latency/waste complaints or a cheaper lever appears. | E-3c design record; runs #59-#61 diagnostics | 2026-07-21 | -| #022 | P2 | task | Source-governance metadata refresh (operator) | **Worklist generated 2026-07-22 ($0, read-only): `docs/source-governance-refresh-worklist-2026-07-22.md`.** Reframed - this is NOT 59 clinical reviews. Of the 124 documents surfacing in canary top results, 59 are review-required, and **38 (64 pct) are the BMJ published-reference tier all sitting at `clinical_validation_status: unverified`** - one attestation-policy decision, not 38 reviews. The remaining 21 are genuine local WA health-service reviews (FSH 7, NMHS 4, CAMHS 3, AKG 2, KEMH 2, RPBG 2, RKPG 1), mostly `document_status: review_due`. Burn-down: top-10 documents clear 44 pct of flagged slots, top-20 clear 66 pct. Next: decide the BMJ attestation policy, then attest local docs by visibility (start `Clozapine Management by GP (NMHS)`, 22 slots at rank 1). | runs #61/#57 Source Governance data; `docs/source-governance-refresh-worklist-2026-07-22.md` | 2026-07-21 | -| #023 | P2 | task | Read Sunday 2026-07-26 scheduled-run artifacts | The 18:00 UTC scheduled runs deliver three free datapoints at once: first full-44 weekly canary (validates the #1044 ANSWER_CASE_LIMIT raise), browser-matrix flake second datapoint (webkit ui-route-coverage now reproduced + root-caused 2026-07-22 ΓåÆ see #024; firefox ui-formulation:91 still awaits a datapoint), and the irrelevant@10 labeling-audit artifact (┬º3.1 human-decision class). Read all three, then disposition. | sessions 2026-07-20/21; branch-review-ledger convergence notes | 2026-07-21 | -| #024 | P3 | issue | WebKit e2e `_rsc`-prefetch access-control-checks errors | verify:release:offline on `main` ce32fe170 (2026-07-22) reproduced #023's webkit clause: **6/6 deterministic** failures in `tests/ui-route-coverage.spec.ts` (Therapy Compass; DSM home/comparison; Specifier comparison/map; Differential stream), each a `pageerror ΓǪ ?_rsc=ΓǪ due to access control checks` on Next.js RSC prefetch ΓÇö Chromium + Firefox clean. Not merge-blocking (required gate `test:e2e:pr` is chromium-only; the full webkit matrix is advisory/release-time). Most likely a Playwright route-interception ├ù WebKit interaction, not a Safari user defect. Next: decide (a) allow/mock the `_rsc` routes for the `webkit` e2e project, or (b) confirm real Safari impact ΓÇö before trusting the full-matrix webkit gate at release. NB the 2 other webkit fails (`ui-stress:412`, `ui-universal-search:210`) passed on isolated re-run = true flake. | session 2026-07-22 (verify:release:offline, `main` ce32fe170); refines #023 | 2026-07-22 | -| #025 | P2 | task | Activate the three webhooks (operator secrets) | Merged (#968/#1100) + deployed but inert ΓÇö verified live: `POST /api/webhooks/railway` returns `503 webhook_not_configured`; the Supabase document-change trigger exists but lacks both activation inputs. To turn on: (1) Railway ΓåÆ set `RAILWAY_WEBHOOK_SECRET` + add the `?token=ΓǪ` webhook URL; (2) set `SLACK_WEBHOOK_URL`/`DISCORD_WEBHOOK_URL` in BOTH the Railway **app/server env** and **GitHub repo secrets**; (3) set one matching document-change secret in the Railway app env as `SUPABASE_INGESTION_WEBHOOK_SECRET` and in Supabase Vault as `ingestion_webhook_secret`, then set the per-environment database GUC `app.ingestion_webhook_base_url` to the deployed app origin. Each path fails closed until fully configured, so this is pure ops. See `docs/webhooks.md` for verification and rotation. | sessions 2026-07-22/24; PRs #968/#1100; docs/webhooks.md | 2026-07-22 | -| #027 | P3 | rec | External uptime monitor independent of GitHub/Railway | `live-domain-monitor.yml` runs on GitHub's cron, so it won't run in exactly the outage it should catch (Actions or the deploy itself down). Add an off-platform synthetic monitor (UptimeRobot / Better Stack / Checkly) hitting `/api/health` with a webhook alert. Provider setup, not code. | session 2026-07-22 webhook review | 2026-07-22 | -| #028 | P3 | rec | Runtime error tracking (Sentry or similar) | No error tracking in the repo ΓÇö production exceptions on `psychiatry.tools`, including how often `RAG_PROVIDER_MODE=auto` silently degrades to source-only, are invisible. Weigh adding `@sentry/nextjs` (dependency + DSN secret + instrumentation) vs cost; alert ΓåÆ chat/issue. Provider-backed; needs explicit sign-off before adding the dependency. | session 2026-07-22 webhook review | 2026-07-22 | -| #029 | P2 | issue | 12 of 30 answer-quality cases return the fallback stub | run #61 --dump-answers: 12/30 quality cases emit the source_backed_review_fallback boilerplate with answer_sections: [], all grounded with 4-6 citations. Some still PASS targeting because the stub echoes query keywords (the contraindication/document_lookup matchers need only a keyword), so the targeting metric MASKS the problem for those intents. Superset of #018 ΓÇö fix in the extractive composer, validate with the provider-backed answer eval. | run #61 dump artifact; session 2026-07-22 | 2026-07-22 | -| #030 | P2 | issue | Wide-tier alias lets one doc satisfy both comparison slots | In src/lib/eval-document-matching.ts, "Admission to Discharge for Mental Health Inpatients" appears in BOTH the AdmissionCommunityPts and Discharge alias lists, so a single document can satisfy both expectedFiles slots and make allHit true ΓÇö a latent false-pass on admission-discharge cases. Not firing today (that doc is not in the failing top-5) but it would mask a real miss. Tighten the tables so one doc cannot fill both sides. | src/lib/eval-document-matching.ts:32-65; session 2026-07-22 | 2026-07-22 | -| #033 | P3 | rec | Source governance metadata absent from the LLM prompt | `buildRagSourceBlock` omits `document_status`, `clinical_validation_status`, and `extraction_quality`, so the model cannot self-caveat during generation and governance is enforced only post-hoc. Generation-surface change: needs `eval:rag` plus `eval:quality --rag-only` (grounded-supported must not drop, citation-failure 0) and explicit approval. Carries the same "unknown Γëá bad" hazard as #032 ΓÇö on a partially-enriched corpus the model would likely over-caveat correct sources, so design the prompt wording before spending an eval. | `src/lib/rag/rag-source-block.ts:126-198`; PR #1051 audit item 8 | 2026-07-22 | -| #035 | P3 | rec | Threshold-conflict detection covers only 3 params | `detectThresholdDisagreements` checks only ANC, WBC, and platelets paired with withholding verbs, so cross-source conflicts on medication doses, lithium/thyroid levels, or vital signs go undetected. Deliberately narrow (see the comment at `:469-474`). Broadening changes when an answer is classified `conflicting` and adds warnings ΓÇö real false-positive risk. Needs new fixtures plus a behaviour review before any change. | `src/lib/evidence.ts:469-574`; PR #1051 audit item 7 | 2026-07-22 | -| #036 | P3 | rec | 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 promotion migrations but never used as a retrieval filter. Promotion is unconditional on `clinical_validation_status`, so unverified documents are publicly searchable ΓÇö compensated by keeping `unverified_source` in the frontend-visible warning set. A hard schema flag touches RLS and the clinical-risk-gated retrieval RPCs; weigh against the existing compensating control before acting. | `supabase/schema.sql:61-108`; `src/lib/search-scope.ts:181-236`; PR #1051 audit item 3 | 2026-07-22 | -| #037 | P3 | rec | D5 trust-cap-all-claims flag parked OFF | `NEXT_PUBLIC_RAG_TRUST_CAP_ALL_CLAIMS` extends authority gating from high-risk claims to **all** supported claims (`deriveTrust`). Ships OFF by design; flipping it caps trust to `medium` for routine claims across the board ΓÇö a product/clinical-UX decision, not a defect. Both states are test-pinned. Next action: product decision, then flip and re-baseline the UI expectations. | `src/lib/answer-render-policy.ts:159-177`; PR #1051 audit item 11 | 2026-07-22 | -| #038 | P3 | rec | Consolidate shared comparison behavior | Several clinical modes expose comparison workflows with similar selection, empty-state and mobile-dock needs. Define one shared behavioral contract before another comparison surface is added; keep mode-specific clinical content separate. This is a design-system recommendation, not a current defect. | design audit reconciliation; session 2026-07-22 | 2026-07-22 | -| #039 | P3 | rec | Consolidate catalogue toolbar patterns | Catalogue/search pages have independently evolved filter, sort, result-count and mobile toolbar behavior. Inventory the existing implementations and converge only the repeated interaction contract; do not flatten mode-specific search semantics. | design audit reconciliation; session 2026-07-22 | 2026-07-22 | -| #040 | P3 | rec | Add targeted visual-regression baselines | Keep a small approved baseline set for high-value desktop/mobile surfaces and accessibility modes instead of screenshotting every route. Start with account/settings, document viewer, mode homes and bottom-composer interactions; define an intentional-update workflow before enabling blocking comparisons. | design audit reconciliation; session 2026-07-22 | 2026-07-22 | -| #075 | P2 | issue | Search-scope label enumeration can truncate after 1,000 rows | **Outcome:** every owner-visible source label can participate in scoped search without silently dropping rows at the Supabase response cap. **Next:** reproduce on current `main` with more than 1,000 distinct labels, then add bounded deterministic pagination and a focused multi-page regression. **Verify:** search-scope unit/API contracts, offline RAG contracts, `verify:cheap`, and production-readiness. **Stop:** do not replay mixed PR #1132, widen aliases, change ranking, or run a live canary unless the isolated fix demonstrably changes protected retrieval behaviour. | PR #1132 (`src/lib/search-scope.ts`, `tests/search-scope.test.ts`); primary reconciliation 2026-07-24 | 2026-07-24 | -| #077 | P2 | issue | Concurrent tasks can re-dirty the canonical primary checkout | **Outcome:** `C:\Dev\Apps\Database` remains a clean synchronization target while write work happens in task-owned worktrees. **Next:** add a cooperative owner/lease check to task-start and lifecycle transitions; before a primary write, branch switch, fast-forward, or cleanup, report owner, dirty state, and Git operation markers and fail closed on an active owner. Include stale-lease recovery. **Success:** a focused concurrency test refuses a second primary writer while read-only commands and separate worktrees continue normally. **Stop:** do not add an OS-wide lock, kill processes, discard existing dirty files, or serialize independent feature worktrees. | primary re-dirtied by another active task immediately after reconciliation proof; session 2026-07-24 | 2026-07-24 | -| #078 | P3 | task | Generate a deterministic reconciliation evidence pack | **Outcome:** one report-only command produces the final local evidence now assembled manually. **Next:** extend the reconciliation lifecycle with an explicit output path and include the frozen base/HEAD, per-worktree dispositions, operation markers resolved through Git, archive refs, bundle path/size/SHA-256/verify result, retained worktree count, and local/base tree equality. Accept remote PR state only as explicit approved input. **Success:** fixture tests prove deterministic output and redaction; an interrupted run leaves no false completion record. **Stop:** never fetch, call GitHub/providers, inspect secret values, mutate refs, or delete work implicitly. | `scripts/reconciliation-preflight.mjs`; `docs/reconciliation-playbook.md`; session 2026-07-24 | 2026-07-24 | -| #079 | P3 | task | Disposition retained worktrees in bounded cleanup batches | **Outcome:** the retained reconciliation tail is gradually classified without another disruptive all-worktree sweep. **Next:** process no more than ten worktrees per explicitly scheduled pass using current owner/process metadata, open-PR state, exact review-ledger coverage, ancestry, and cherry-pick-aware content proof. **Success:** remove only clean, inactive, bundled worktrees whose content is merged or explicitly rejected; record every disposition and retain recovery evidence. **Stop:** preserve dirty, active, secret-bearing, post-freeze, paused, or ambiguous work and never use reset, force deletion, broad clean, or process killing. | final reconciliation inventory retained 104 independent worktrees; session 2026-07-24 | 2026-07-24 | +| ID | Pri | Type | Summary | Detail / next action | Source | Added | +| ---- | --- | ----- | --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ---------- | +| #059 | P1 | task | Verify containment of every credential reported exposed in chat | **Outcome:** every reported exposed credential is rejected or retired. **Next:** in approved security windows, verify and revoke or rotate the GitHub token, OpenAI key, Supabase service-role JWT, database password, and E2E credential; create replacements only when required and update only intended secret stores. **Success:** provider evidence confirms the old credentials cannot authenticate, replacements are distinct and minimally scoped, presence/readiness checks pass, and secret scans remain clean. **Stop:** no provider or secret-store action without approval; never print or paste values into Git, logs, issues, or chat. | session 2026-07-24 security reconciliation; AI Agent Target Manifest | 2026-07-24 | +| #064 | P2 | task | Reconcile the preserved browser and contrast patch | **Outcome:** the isolated dirty formulation/contrast patch is safely landed or explicitly dispositioned. **Next:** rebase its intent against current `main` without overwriting the worktree, then run focused Playwright coverage and `verify:ui`. **Success:** intended disabled/contrast behavior is accessible, browser assertions remain meaningful, and unrelated work is preserved. **Stop:** do not discard or auto-merge the dirty worktree; pause on ambiguous ownership or scope. | `agent/formulation-disabled-contrast`; session 2026-07-24 | 2026-07-24 | +| #065 | P2 | task | Complete the paused compact document source-text accordion | **Outcome:** the document viewer uses compact nested disclosures while retaining complete text, citation/search navigation, print behavior, and composer clearance. **Next:** only when the user explicitly resumes, reconcile `codex/chat-document-text-accordion-7cb4` with current `main` and complete the focused 320/390/1280 px tests. **Success:** default disclosures are closed; deep links and search open only the active passage; printing expands/restores state; no overflow. **Verify:** focused document-viewer Playwright, `verify:cheap`, `verify:ui`, and static production-readiness. **Stop:** remain paused until explicit user return; no provider calls. | paused document-viewer task; `codex/chat-document-text-accordion-7cb4` | 2026-07-24 | +| #066 | P2 | task | Land and prove the streamlined six-item sidebar | Implementation and the corrected Therapy wiring assertion are recoverable from remote branch `origin/codex/sidebar-test-fix-20260723` at full commit `cd54e68fbf7b07b5dffe3220e36af2caa528da54`; fetch it in a fresh checkout with `git fetch origin refs/heads/codex/sidebar-test-fix-20260723`. Focused sidebar/favourites suites pass 18/18. Remaining: run `verify:pr-local`, start the app and inspect desktop/tablet/mobile plus short-height scrolling and keyboard/focus behavior, run `verify:ui`, production build and bundle-budget checks, then open/merge the PR and prove the exact content is on `origin/main`. | remote branch `origin/codex/sidebar-test-fix-20260723`; commit `cd54e68fbf7b07b5dffe3220e36af2caa528da54`; session 2026-07-24 | 2026-07-24 | +| #067 | P2 | issue | Reconciliation preflight test times out under full-suite load | **Outcome:** the reconciliation preflight subprocess test is deterministic under the repository's serialized heavy-test workflow. During PR #1119 validation, the 30-second test timeout occurred twice under loaded full-suite execution, while the isolated file passed 5/5 and a separate `verify:cheap` full suite passed. **Next:** reproduce with timing around subprocess startup, output and teardown, then fix the smallest proven harness lifecycle cause. **Success:** repeated focused and full-suite runs complete without extending the global timeout. **Stop:** do not hide the cause by raising broad timeouts, adding retries, or bypassing the shared test lock. | `tests/reconciliation-preflight.test.ts`; PR #1119 validation; session 2026-07-24 | 2026-07-24 | +| #051 | P2 | task | Stabilise the live answer-quality canary before more RAG tuning | Diagnostics landed in PR #1095: structured JSON/Markdown artifacts now record the actual checked-out SHA, run identity and latency context, and the offline trend tool separates content, provider-route and latency outcomes. First validating run `30018289898` recorded the expected tree and cost, with 36/36 retrieval green, but one report cannot establish variability; PR #1097 prevents a single failure being mislabeled as repeated. Next: compare the scheduled 2026-07-26 structured report with this run. Do not spend on an immediate retry or reapply the archived lithium guard before that comparison. | PR #1095; run `30018289898`; PR #1097; archive ref `refs/archive/rejected-rag/20260723/monitoring-subject-gate` | 2026-07-23 | +| #001 | P2 | task | Semantic reranking still gated off | `RAG_SEMANTIC_RERANK_ENABLED=false` from PR #901. Do not enable until the provider-backed 36/36 retrieval-quality gate **and** an ambiguity-focused canary are explicitly approved and recorded. | `docs/process-hardening.md` (Semantic reranking rollout debt); PR #901 | 2026-07-21 | +| #069 | P3 | task | Live-profile table-facts plpgsql+EXECUTE latency | Migration `20260724120000_table_facts_plpgsql_execute.sql` plus P3 follow-ups (`20260724130000_*`, `20260724130100_*`) are in PR #1133. Hosted apply is blocked in this environment (no `SUPABASE_DB_URL`; Supabase MCP `needsAuth`). A live `profile:retrieval --rpc match_document_table_facts_text --analyze` attempt returned `Unregistered API key` against the injected service-role secret. **Next:** operator applies the three pending migrations on the live target project, then re-runs approval-gated `profile:retrieval` / `explain_retrieval_rpc` and confirms ~70ms-class plans with no ranking change. **Stop** without mutating ranking. | session 2026-07-24 Database interface audit; PR #1133 | 2026-07-24 | +| #053 | P1 | task | Execute cross-border privacy/legal package | Execute OpenAI and Railway DPAs; decide ZDR and Australian data residency; obtain prompt-cache behavior in writing; review subprocessors; obtain APP 8 and APP 5/1 counsel sign-off. Do not represent the release as privacy-approved or alter final public privacy wording before sign-off. | `docs/openai-cross-border-basis.md`; `docs/privacy-impact-assessment.md` | 2026-07-24 | +| #054 | P2 | task | Reconcile local and hosted secrets/config | Presence-check safety-identifier, query-hash, deep-probe, Supabase service-role, OpenAI, project-identity, and schedule settings; set only confirmed gaps with distinct per-environment values. Never record secret values. Provider reads/writes require approval. | `.env.example`; production-readiness warning; `docs/operator-backlog.md` | 2026-07-24 | +| #055 | P2 | task | Run one exact-SHA full release and PR gate | Before the next full-confidence release/handoff, record the candidate/PR SHA and run the local/provider release gates, Firefox/WebKit, required hosted CI, and actionable GitHub review-thread closure once. Stop at the first actionable failure and rerun only the repaired smallest gate. | `docs/launch-operator-runbook.md`; `docs/codex-review-protocol.md` | 2026-07-24 | +| #056 | P2 | task | Provision isolated staging environment | After explicit cost/ownership approval, provision `Clinical KB Staging` Supabase and Railway tiers with distinct secrets and synthetic/non-clinical data. Verify identity, schema, indexing, health, and the production-data boundary. | `docs/staging-setup.md`; `docs/operator-backlog.md` | 2026-07-24 | +| #057 | P2 | task | Complete staging soak and rollback rehearsal | After #056, run the documented soak and rollback against an exact candidate; retain latency/error/rollback evidence. Stop on unsafe data, identity mismatch, or an unowned rollback decision. | `docs/launch-operator-runbook.md`; `docs/capacity-review.md` | 2026-07-24 | +| #058 | P2 | task | Verify production content before any seed write | Against `the live target project`, verify registry, differentials, and medications surfaces are non-empty before writing. Seed only confirmed gaps idempotently with approved owner/project identity and confirmation flags. | `docs/launch-operator-runbook.md`; `docs/operator-backlog.md` | 2026-07-24 | +| #005 | P3 | rec | `finalScore` saturates at clamp ceiling | Base + ~40 stacked boosts routinely exceed 1.0, so strong matches tie at 1.0 and order by an arbitrary `document_id` tiebreak. If ranking is ever revisited, break ties by the **pre-clamp** score rather than raising the `[0,1]` ceiling (downstream gates assume `[0,1]`). Ordering already sorts by the unbounded pre-clamp `rankScore` (`clinical-search.ts:1735,1927,1950-1955`), so the clamp confines only the reported confidence value, not result order. Not a defect on the current golden set; any change here is a protected RAG surface (canary required). | `docs/rag-hybrid-findings-and-todo.md` P1 item 4; `src/lib/clinical-search.ts:1735` | 2026-07-21 | +| #007 | P3 | rec | `/tools` vs `/?mode=tools` parallel Tools entry points | `/tools` (standalone `ApplicationsLauncherPage`) has no inbound in-app link; the sidebar Tools item uses `/?mode=tools`. Decide the canonical entry point and wire nav consistently, or drop the standalone `/tools` page + `/applications` redirect. Currently allowlisted in `tests/route-reachability.test.ts`. | `src/app/tools/page.tsx`; `src/app/applications/route.ts` | 2026-07-21 | +| #011 | P3 | task | Auth DB-connection allocation is operator-only | Supabase Auth (GoTrue) is capped at ~10 absolute DB connections (Supabase perf advisor). Switch to **percentage-based** allocation in the Supabase **dashboard** before the first compute scale-up ΓÇö **not settable via SQL/MCP** (operator-owned). Verify via a staging soak + an approval-gated read-only advisor re-check. | `docs/auth-connection-cap-runbook.md`; `docs/process-hardening.md` (Known follow-up debts) | 2026-07-21 | +| #012 | P3 | rec | Slim the lazy cross-mode differentials chunk | `cross-mode-differentials.ts` is dynamically imported (correctly code-split **out** of the initial/dashboard bundle ΓÇö verified), but it pulls the full ~860 KB differentials snapshot (~125 KB gzip lazy chunk) just to build a tiny `{slug,title,clinicalHinge}` + presentations + aliases catalog. A precomputed lightweight index (generator + drift check, like the `specifiers-content` split / medications `fields=index`) would cut that lazy chunk ~5ΓÇô10├ù. Not a bundle leak ΓÇö an M-effort slim. | `src/lib/cross-mode-differentials.ts`; `src/components/clinical-dashboard/cross-mode-links.tsx:150`; session 2026-07-21 (build:analyze) | 2026-07-21 | +| #013 | P3 | rec | Route-chunk + mockup catalogue JSON weight | `build:analyze`: `/specifiers` ships `specifiers-search-index.json` (~180 KB parsed), `/forms` ships `forms-catalog.json` (~132 KB), `/formulation` ships `formulation-content.json` (~52 KB, client-side local search ΓÇö needs index/full split or a search endpoint, architectural). All route-scoped (not initial bundle). Also `*-mockups.tsx` (~100 KB across chunks) build though `/mockups` 404s in prod ΓÇö exclude from the prod artifact. | session 2026-07-21 (build:analyze) | 2026-07-21 | +| #016 | P3 | rec | "Big but not easy" structural + motion perf | Deferred larger levers: (a) nonce-CSP forces every product route to `╞Æ Dynamic` (zero static generation) ΓÇö evaluate Partial Prerendering / static shells for the static clinical catalogues (DSM/differentials/therapy/specifiers/formulation); (b) sidebar expand/collapse animates `grid-template-columns` (biggest smoothness cost, motion-gated ΓÇö needs a transform-overlay rethink); (c) Therapy Compass fetches 692 KB / 2.5 MB JSON client-side (defer until interaction + confirm brotli); (d) settings/setup/admin dialogs static-imported into the home chunk (`next/dynamic` them). | session 2026-07-21 (build route table + design audit) | 2026-07-21 | +| #017 | P3 | task | Field Web-Vitals baseline via live Lighthouse | In-sandbox runtime vitals were blocked (prod server hard-requires Supabase secrets; dev-mode CLS measured excellent at 0.00ΓÇô0.04, content-first pages 0.000). Run Lighthouse against `psychiatry.tools` for real LCP/INP/CLS to prioritize #012ΓÇô#016 by measured impact rather than reasoning. | session 2026-07-21 (measurement pass) | 2026-07-21 | +| #018 | P2 | task | Split the lithium, ADHD and metabolic residuals by mechanism | Revalidated on current main 2026-07-23: these are not one composer defect. Lithium reproduced an unrelated-table retrieval fast-path defect; ADHD retrieves a relevant chart-heavy CAMHS source but exhausts the extractive route budget; metabolic retrieves the correct AKG source but selects schedule-free prose. The narrow lithium subject-evidence guard improved targeting from 0 to 1 with golden recall 1.0 and no reciprocal-rank regressions, but it was reverted because the full canary failed. After #051 stabilises the canary, add independent current-main reproducers and assess each mechanism separately. Do not widen the matcher or combine these into a broad ranking/composer change. | runs `30007833352` and `30009207429`; PR #1093; session 2026-07-23 | 2026-07-21 | +| #019 | P2 | task | Admission doc dropped after deterministic comparison packing | Reconfirmed on merged-main run `30018289898`: golden retrieval remained 36/36 and retrieved `MHSP.AdmissionCommunityPts.pdf`, but the answer's top five sources retained only `MHSP.Discharge.pdf` after `generation_fallback:generation_quality_failed; comparison_source_extractive_fallback`. PR #1096 replays the live score/order shape and proves deterministic answer ranking plus cross-document packing retain both admission and discharge evidence, so retrieval scores, aliases and comparator ordering are not the fix. Next: create a red fallback-layer unit reproducer using the live source shape; any behavior change still needs the existing baseline and a passing post canary. | run `30018289898`; PR #1096; session 2026-07-23 | 2026-07-21 | +| #021 | P3 | rec | E-3d H2 residual: strong/comparison generation discards | approx. 6 generation attempts per full 44-case run still fail the final quality gate and fall to extractive on strong-route comparison/complex shapes (the designed-conservative outcome). PARKED: weakest cost/benefit on the queue ΓÇö a wave (approx. $2-4 pair + reviewer cycle) to shave seconds off a few hard cases. Revisit only if latency/waste complaints or a cheaper lever appears. | E-3c design record; runs #59-#61 diagnostics | 2026-07-21 | +| #022 | P2 | task | Source-governance metadata refresh (operator) | **Worklist generated 2026-07-22 ($0, read-only): `docs/source-governance-refresh-worklist-2026-07-22.md`.** Reframed - this is NOT 59 clinical reviews. Of the 124 documents surfacing in canary top results, 59 are review-required, and **38 (64 pct) are the BMJ published-reference tier all sitting at `clinical_validation_status: unverified`** - one attestation-policy decision, not 38 reviews. The remaining 21 are genuine local WA health-service reviews (FSH 7, NMHS 4, CAMHS 3, AKG 2, KEMH 2, RPBG 2, RKPG 1), mostly `document_status: review_due`. Burn-down: top-10 documents clear 44 pct of flagged slots, top-20 clear 66 pct. Next: decide the BMJ attestation policy, then attest local docs by visibility (start `Clozapine Management by GP (NMHS)`, 22 slots at rank 1). | runs #61/#57 Source Governance data; `docs/source-governance-refresh-worklist-2026-07-22.md` | 2026-07-21 | +| #023 | P2 | task | Read Sunday 2026-07-26 scheduled-run artifacts | The 18:00 UTC scheduled runs deliver three free datapoints at once: first full-44 weekly canary (validates the #1044 ANSWER_CASE_LIMIT raise), browser-matrix flake second datapoint (webkit ui-route-coverage now reproduced + root-caused 2026-07-22 ΓåÆ see #024; firefox ui-formulation:91 still awaits a datapoint), and the irrelevant@10 labeling-audit artifact (┬º3.1 human-decision class). Read all three, then disposition. | sessions 2026-07-20/21; branch-review-ledger convergence notes | 2026-07-21 | +| #024 | P3 | issue | WebKit e2e `_rsc`-prefetch access-control-checks errors | verify:release:offline on `main` ce32fe170 (2026-07-22) reproduced #023's webkit clause: **6/6 deterministic** failures in `tests/ui-route-coverage.spec.ts` (Therapy Compass; DSM home/comparison; Specifier comparison/map; Differential stream), each a `pageerror ΓǪ ?_rsc=ΓǪ due to access control checks` on Next.js RSC prefetch ΓÇö Chromium + Firefox clean. Not merge-blocking (required gate `test:e2e:pr` is chromium-only; the full webkit matrix is advisory/release-time). Most likely a Playwright route-interception ├ù WebKit interaction, not a Safari user defect. Next: decide (a) allow/mock the `_rsc` routes for the `webkit` e2e project, or (b) confirm real Safari impact ΓÇö before trusting the full-matrix webkit gate at release. NB the 2 other webkit fails (`ui-stress:412`, `ui-universal-search:210`) passed on isolated re-run = true flake. | session 2026-07-22 (verify:release:offline, `main` ce32fe170); refines #023 | 2026-07-22 | +| #025 | P2 | task | Activate the three webhooks (operator secrets) | Merged (#968/#1100) + deployed but inert ΓÇö verified live: `POST /api/webhooks/railway` returns `503 webhook_not_configured`; the Supabase document-change trigger exists but lacks both activation inputs. To turn on: (1) Railway ΓåÆ set `RAILWAY_WEBHOOK_SECRET` + add the `?token=ΓǪ` webhook URL; (2) set `SLACK_WEBHOOK_URL`/`DISCORD_WEBHOOK_URL` in BOTH the Railway **app/server env** and **GitHub repo secrets**; (3) set one matching document-change secret in the Railway app env as `SUPABASE_INGESTION_WEBHOOK_SECRET` and in Supabase Vault as `ingestion_webhook_secret`, then set the per-environment database GUC `app.ingestion_webhook_base_url` to the deployed app origin. Each path fails closed until fully configured, so this is pure ops. See `docs/webhooks.md` for verification and rotation. | sessions 2026-07-22/24; PRs #968/#1100; docs/webhooks.md | 2026-07-22 | +| #027 | P3 | rec | External uptime monitor independent of GitHub/Railway | `live-domain-monitor.yml` runs on GitHub's cron, so it won't run in exactly the outage it should catch (Actions or the deploy itself down). Add an off-platform synthetic monitor (UptimeRobot / Better Stack / Checkly) hitting `/api/health` with a webhook alert. Provider setup, not code. | session 2026-07-22 webhook review | 2026-07-22 | +| #028 | P3 | rec | Runtime error tracking (Sentry or similar) | No error tracking in the repo ΓÇö production exceptions on `psychiatry.tools`, including how often `RAG_PROVIDER_MODE=auto` silently degrades to source-only, are invisible. Weigh adding `@sentry/nextjs` (dependency + DSN secret + instrumentation) vs cost; alert ΓåÆ chat/issue. Provider-backed; needs explicit sign-off before adding the dependency. | session 2026-07-22 webhook review | 2026-07-22 | +| #029 | P2 | issue | 12 of 30 answer-quality cases return the fallback stub | run #61 --dump-answers: 12/30 quality cases emit the source_backed_review_fallback boilerplate with answer_sections: [], all grounded with 4-6 citations. Some still PASS targeting because the stub echoes query keywords (the contraindication/document_lookup matchers need only a keyword), so the targeting metric MASKS the problem for those intents. Superset of #018 ΓÇö fix in the extractive composer, validate with the provider-backed answer eval. | run #61 dump artifact; session 2026-07-22 | 2026-07-22 | +| #030 | P2 | issue | Wide-tier alias lets one doc satisfy both comparison slots | In src/lib/eval-document-matching.ts, "Admission to Discharge for Mental Health Inpatients" appears in BOTH the AdmissionCommunityPts and Discharge alias lists, so a single document can satisfy both expectedFiles slots and make allHit true ΓÇö a latent false-pass on admission-discharge cases. Not firing today (that doc is not in the failing top-5) but it would mask a real miss. Tighten the tables so one doc cannot fill both sides. | src/lib/eval-document-matching.ts:32-65; session 2026-07-22 | 2026-07-22 | +| #033 | P3 | rec | Source governance metadata absent from the LLM prompt | `buildRagSourceBlock` omits `document_status`, `clinical_validation_status`, and `extraction_quality`, so the model cannot self-caveat during generation and governance is enforced only post-hoc. Generation-surface change: needs `eval:rag` plus `eval:quality --rag-only` (grounded-supported must not drop, citation-failure 0) and explicit approval. Carries the same "unknown Γëá bad" hazard as #032 ΓÇö on a partially-enriched corpus the model would likely over-caveat correct sources, so design the prompt wording before spending an eval. | `src/lib/rag/rag-source-block.ts:126-198`; PR #1051 audit item 8 | 2026-07-22 | +| #035 | P3 | rec | Threshold-conflict detection covers only 3 params | `detectThresholdDisagreements` checks only ANC, WBC, and platelets paired with withholding verbs, so cross-source conflicts on medication doses, lithium/thyroid levels, or vital signs go undetected. Deliberately narrow (see the comment at `:469-474`). Broadening changes when an answer is classified `conflicting` and adds warnings ΓÇö real false-positive risk. Needs new fixtures plus a behaviour review before any change. | `src/lib/evidence.ts:469-574`; PR #1051 audit item 7 | 2026-07-22 | +| #036 | P3 | rec | 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 promotion migrations but never used as a retrieval filter. Promotion is unconditional on `clinical_validation_status`, so unverified documents are publicly searchable ΓÇö compensated by keeping `unverified_source` in the frontend-visible warning set. A hard schema flag touches RLS and the clinical-risk-gated retrieval RPCs; weigh against the existing compensating control before acting. | `supabase/schema.sql:61-108`; `src/lib/search-scope.ts:181-236`; PR #1051 audit item 3 | 2026-07-22 | +| #037 | P3 | rec | D5 trust-cap-all-claims flag parked OFF | `NEXT_PUBLIC_RAG_TRUST_CAP_ALL_CLAIMS` extends authority gating from high-risk claims to **all** supported claims (`deriveTrust`). Ships OFF by design; flipping it caps trust to `medium` for routine claims across the board ΓÇö a product/clinical-UX decision, not a defect. Both states are test-pinned. Next action: product decision, then flip and re-baseline the UI expectations. | `src/lib/answer-render-policy.ts:159-177`; PR #1051 audit item 11 | 2026-07-22 | +| #038 | P3 | rec | Consolidate shared comparison behavior | Several clinical modes expose comparison workflows with similar selection, empty-state and mobile-dock needs. Define one shared behavioral contract before another comparison surface is added; keep mode-specific clinical content separate. This is a design-system recommendation, not a current defect. | design audit reconciliation; session 2026-07-22 | 2026-07-22 | +| #039 | P3 | rec | Consolidate catalogue toolbar patterns | Catalogue/search pages have independently evolved filter, sort, result-count and mobile toolbar behavior. Inventory the existing implementations and converge only the repeated interaction contract; do not flatten mode-specific search semantics. | design audit reconciliation; session 2026-07-22 | 2026-07-22 | +| #040 | P3 | rec | Add targeted visual-regression baselines | Keep a small approved baseline set for high-value desktop/mobile surfaces and accessibility modes instead of screenshotting every route. Start with account/settings, document viewer, mode homes and bottom-composer interactions; define an intentional-update workflow before enabling blocking comparisons. | design audit reconciliation; session 2026-07-22 | 2026-07-22 | +| #075 | P2 | issue | Search-scope label enumeration can truncate after 1,000 rows | **Outcome:** every owner-visible source label can participate in scoped search without silently dropping rows at the Supabase response cap. **Next:** reproduce on current `main` with more than 1,000 distinct labels, then add bounded deterministic pagination and a focused multi-page regression. **Verify:** search-scope unit/API contracts, offline RAG contracts, `verify:cheap`, and production-readiness. **Stop:** do not replay mixed PR #1132, widen aliases, change ranking, or run a live canary unless the isolated fix demonstrably changes protected retrieval behaviour. | PR #1132 (`src/lib/search-scope.ts`, `tests/search-scope.test.ts`); primary reconciliation 2026-07-24 | 2026-07-24 | +| #077 | P2 | issue | Concurrent tasks can re-dirty the canonical primary checkout | **Outcome:** `C:\Dev\Apps\Database` remains a clean synchronization target while write work happens in task-owned worktrees. **Next:** add a cooperative owner/lease check to task-start and lifecycle transitions; before a primary write, branch switch, fast-forward, or cleanup, report owner, dirty state, and Git operation markers and fail closed on an active owner. Include stale-lease recovery. **Success:** a focused concurrency test refuses a second primary writer while read-only commands and separate worktrees continue normally. **Stop:** do not add an OS-wide lock, kill processes, discard existing dirty files, or serialize independent feature worktrees. | primary re-dirtied by another active task immediately after reconciliation proof; session 2026-07-24 | 2026-07-24 | +| #078 | P3 | task | Generate a deterministic reconciliation evidence pack | **Outcome:** one report-only command produces the final local evidence now assembled manually. **Next:** extend the reconciliation lifecycle with an explicit output path and include the frozen base/HEAD, per-worktree dispositions, operation markers resolved through Git, archive refs, bundle path/size/SHA-256/verify result, retained worktree count, and local/base tree equality. Accept remote PR state only as explicit approved input. **Success:** fixture tests prove deterministic output and redaction; an interrupted run leaves no false completion record. **Stop:** never fetch, call GitHub/providers, inspect secret values, mutate refs, or delete work implicitly. | `scripts/reconciliation-preflight.mjs`; `docs/reconciliation-playbook.md`; session 2026-07-24 | 2026-07-24 | +| #079 | P3 | task | Disposition retained worktrees in bounded cleanup batches | **Outcome:** the retained reconciliation tail is gradually classified without another disruptive all-worktree sweep. **Next:** process no more than ten worktrees per explicitly scheduled pass using current owner/process metadata, open-PR state, exact review-ledger coverage, ancestry, and cherry-pick-aware content proof. **Success:** remove only clean, inactive, bundled worktrees whose content is merged or explicitly rejected; record every disposition and retain recovery evidence. **Stop:** preserve dirty, active, secret-bearing, post-freeze, paused, or ambiguous work and never use reset, force deletion, broad clean, or process killing. | final reconciliation inventory retained 104 independent worktrees; session 2026-07-24 | 2026-07-24 | ## Resolved / archive @@ -148,13 +148,13 @@ Move resolved rows here with the resolution date and a one-line outcome. Keep th | ID | Type | Summary | Outcome | Resolved | | ---- | ----- | ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | -| #009 | rec | Confirm `/api/jobs` is intentionally server/ops-only | Kept as deliberate administrator/ops listing: no client `fetch("/api/jobs")` (UI uses `/api/ingestion/jobs`); documented in `docs/api-jobs-ops-surface.md` plus wiring/codebase-index/site-map notes. Not abandoned ΓÇö do not remove without updating API contract tests. | 2026-07-24 | -| #010 | task | Un-built "Coming soon" controls across forms/favourites | Audited forms/favourites/presentation placeholders: all use honest `disabled` or `aria-disabled` + coming-soon copy (or presentational `ToggleSwitch` without `onToggle`). No fake-interactive controls; leave unwired until features land. Recorded in `docs/wiring-conventions.md`. | 2026-07-24 | -| #032 | rec | Governance ranking weighting: REFUTED, not debt | Reinforced as guardrail only in `docs/rag-behaviour/refuted-approaches.md` (Refutation 3), README, and safeguards ΓÇö do **not** implement `review_due`/unknownCurrentness ranking penalties or boosts. No retrieval/ranking code changed. RC8 filter path remains the only revisit route behind canary gates. | 2026-07-24 | -| #041 | rec | Extend the existing Factsheets reading model | Brief recorded in `docs/factsheets-reading-model-brief.md`: extend Easy Read/Standard on existing Factsheets routes; reject a second patient-facing Factsheets mode unless concrete need + source-governance plan exist. | 2026-07-24 | -| #063 | rec | Define ΓÇ£Current Clinical WorkΓÇ¥ before implementation | Product/privacy/persistence brief recorded in `docs/current-clinical-work-brief.md`. Default v0 = no new storage (tab/URL resume); Class C free text needs privacy clearance. Stop without demand evidence. No UI/schema implemented. | 2026-07-24 | +| #009 | rec | Confirm `/api/jobs` is intentionally server/ops-only | Kept as deliberate administrator/ops listing: no client `fetch("/api/jobs")` (UI uses `/api/ingestion/jobs`); documented in `docs/api-jobs-ops-surface.md` plus wiring/codebase-index/site-map notes. Not abandoned ΓÇö do not remove without updating API contract tests. | 2026-07-24 | +| #010 | task | Un-built "Coming soon" controls across forms/favourites | Audited forms/favourites/presentation placeholders: all use honest `disabled` or `aria-disabled` + coming-soon copy (or presentational `ToggleSwitch` without `onToggle`). No fake-interactive controls; leave unwired until features land. Recorded in `docs/wiring-conventions.md`. | 2026-07-24 | +| #032 | rec | Governance ranking weighting: REFUTED, not debt | Reinforced as guardrail only in `docs/rag-behaviour/refuted-approaches.md` (Refutation 3), README, and safeguards ΓÇö do **not** implement `review_due`/unknownCurrentness ranking penalties or boosts. No retrieval/ranking code changed. RC8 filter path remains the only revisit route behind canary gates. | 2026-07-24 | +| #041 | rec | Extend the existing Factsheets reading model | Brief recorded in `docs/factsheets-reading-model-brief.md`: extend Easy Read/Standard on existing Factsheets routes; reject a second patient-facing Factsheets mode unless concrete need + source-governance plan exist. | 2026-07-24 | +| #063 | rec | Define ΓÇ£Current Clinical WorkΓÇ¥ before implementation | Product/privacy/persistence brief recorded in `docs/current-clinical-work-brief.md`. Default v0 = no new storage (tab/URL resume); Class C free text needs privacy clearance. Stop without demand evidence. No UI/schema implemented. | 2026-07-24 | | #076 | task | Reproduce malformed fallback PDF image/table crops | Reproduced truncated page-edge `table_crop`s on current-main with `worker/python/fixtures/malformed-table-crop-page-edge.pdf`. Root cause: `pymupdf_find_tables` stops at the last fully detected row; fix extends the candidate from contiguous cell drawings, recovers the on-page score-5 remnant, and emits `table_crop_edge_incomplete` / `crop_completeness=0.9` when content continues past the page. PR #1176. Broad PR #1129 retention/padding changes not merged. | 2026-07-24 | -| #070 | issue | Presentation mobile tabs misroute Overview/Map/Related | Fixed in PR #1135: Overview/Map/Related deep-link to diagnosis `?tab=` sections; Compare stays on the presentation page. Regression in `tests/mobile-interaction-regressions.test.ts`. (Provisional PR-branch IDs `#068`ΓÇô`#072` were renumbered after `main` claimed `#068`/`#069`.) | 2026-07-24 | +| #070 | issue | Presentation mobile tabs misroute Overview/Map/Related | Fixed in PR #1135: Overview/Map/Related deep-link to diagnosis `?tab=` sections; Compare stays on the presentation page. Regression in `tests/mobile-interaction-regressions.test.ts`. (Provisional PR-branch IDs `#068`ΓÇô`#072` were renumbered after `main` claimed `#068`/`#069`.) | 2026-07-24 | | #071 | issue | Evidence/Clinical Notes Add fakes success without persistence | Fixed in PR #1135: sticky Add controls use the focusable coming-soon placeholder pattern instead of optimistic `setAdded(true)`. | 2026-07-24 | | #072 | issue | Tools hub exposes false Sort/More affordances | Fixed in PR #1135: Sort is a status label, More filter targets coordination/saved without a fake menu chevron, and the favourites shortcut is labelled Saved/Favourites. | 2026-07-24 | | #073 | issue | Presentation compare dock CTA is a self-link no-op | Fixed in PR #1135: dock shows non-link "Comparing (N)" status while already comparing. | 2026-07-24 | @@ -171,9 +171,9 @@ Move resolved rows here with the resolution date and a one-line outcome. Keep th | #020 | task | Validate eval:quality cost readout post-fix | Confirmed on merged-main canary run `30018289898`: Answer Metrics reported 9 nonzero-cost cases and an estimated answer cost of `$0.234736`; the structured report retained the same value. The PR #1050 estimator fix is operationally proven. | 2026-07-23 | | #003 | task | Staging tenancy release evidence outstanding | Ran GitHub Action and validated isolation | 2026-07-21 | | #002 | task | Process-ownership fix not yet isolated on `main` | Fixed process isolation using child.pid termination | 2026-07-21 | -| #008 | rec | Dead href builders in `document-flow-routes.ts` | Not dead code (false positive): `documentReaderHref`/`documentEvidenceHref` are live via the mock wrappers in `src/components/document-search-mockups.tsx` + `src/components/master-document-flow-mockups.tsx` (rendered under `src/app/mockups/document-search/`) and covered by `tests/document-flow-routes.test.ts`; removing breaks the build. Only the production non-mock hrefs are unlinked from prod UI ΓÇö a wiring gap, not dead code. | 2026-07-22 | +| #008 | rec | Dead href builders in `document-flow-routes.ts` | Not dead code (false positive): `documentReaderHref`/`documentEvidenceHref` are live via the mock wrappers in `src/components/document-search-mockups.tsx` + `src/components/master-document-flow-mockups.tsx` (rendered under `src/app/mockups/document-search/`) and covered by `tests/document-flow-routes.test.ts`; removing breaks the build. Only the production non-mock hrefs are unlinked from prod UI ΓÇö a wiring gap, not dead code. | 2026-07-22 | | #015 | task | Content-first fallback regression tests | Added `tests/registry-record-loader.dom.test.tsx` (8) + `tests/medication-record-page.dom.test.tsx` (6) covering content-first fallback paint, live swap-in, spinner/skeleton, error + not-found/unauthorized states, and the invariant that no authoritative verification badge shows before live governance reconciles (registry fixture-flag neutralization + medication governance-drop-on-error). | 2026-07-22 | -| #004 | rec | Rescope provider-gated RAG safety ideas | Closed obsolete ΓÇö rescue source (754-line RAG-safety worktree) unrecoverable/pruned across all refs; answer-quality thresholds + deep-health already shipped on `main` (#585/#587); only cost-cap preflight was genuinely missing and, per session decision, dropped rather than re-filed. | 2026-07-22 | +| #004 | rec | Rescope provider-gated RAG safety ideas | Closed obsolete ΓÇö rescue source (754-line RAG-safety worktree) unrecoverable/pruned across all refs; answer-quality thresholds + deep-health already shipped on `main` (#585/#587); only cost-cap preflight was genuinely missing and, per session decision, dropped rather than re-filed. | 2026-07-22 | | #006 | issue | Globe "Language & region" button had no handler | Resolved on main with the repository's disabled "Coming soon" placeholder convention and button-wiring coverage. Future language/region work remains a feature request, not an inert-control defect. | 2026-07-22 | | #042 | issue | Invalid optional credentials fell into anonymous access | PRs #1078/#1079 introduced `absent \| valid \| invalid`, return 401 for presented invalid credentials, preserve authoritative header precedence and prefer the current-project session cookie. The archived anonymous-upload metadata patch was rejected as stale because uploads are already administrator-only before duplicate lookup. | 2026-07-22 | | #043 | issue | Readiness could report healthy or throw on Supabase errors | PR #1080 now fails readiness closed for returned and thrown dependency failures, preserves recognized actionable messages, and prevents raw dependency-error disclosure. | 2026-07-22 |