diff --git a/.claude/hooks/issues-surface.sh b/.claude/hooks/issues-surface.sh index dab08f83d..ac4c63dad 100755 --- a/.claude/hooks/issues-surface.sh +++ b/.claude/hooks/issues-surface.sh @@ -1,68 +1,58 @@ #!/usr/bin/env bash -# SessionStart hook — surface the outstanding-work memory into context. +# SessionStart hook — surface the universal task ledger into context. # -# Reads docs/outstanding-issues.md (the /issues ledger) and prints a compact, -# glanceable summary of the OPEN items so every session starts already aware of -# what is outstanding. When the trigger is a context reset (compact / resume / -# clear) it also emits a reminder to run `/issues capture` — that is the moment -# a session's in-flight follow-ups are most likely to be lost. +# Reads docs/outstanding-issues.md and prints a compact summary of the active Prioritised queue. +# On compact/resume/clear it also reminds the agent to capture new follow-ups. # -# Contract: READ-ONLY. Never writes, never commits, never fails a session — it -# always exits 0, and every step is guarded so a parse error just yields less -# output. SessionStart hook stdout is injected into the model's context. +# Contract: READ-ONLY. Never writes, never commits, never fails a session. set -uo pipefail -# --- locate the repo + ledger ------------------------------------------------- root="${CLAUDE_PROJECT_DIR:-}" [ -z "$root" ] && root="$(git rev-parse --show-toplevel 2>/dev/null || true)" [ -z "$root" ] && root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." 2>/dev/null && pwd || true)" ledger="$root/docs/outstanding-issues.md" [ -f "$ledger" ] || exit 0 -# --- read the hook payload (stdin JSON) to learn the trigger source ----------- payload="$(cat 2>/dev/null || true)" source_val="$(printf '%s' "$payload" \ | grep -o '"source"[[:space:]]*:[[:space:]]*"[^"]*"' \ | head -n1 | sed -E 's/.*"([^"]*)"$/\1/')" -# --- parse the "Open items" table only --------------------------------------- -# Emit "PRIIDTYPESUMMARY" per open row. Scoped between the -# "## Open items" heading and the next "## " heading so the Resolved/archive -# table (different columns) is never counted. +# Emit ACUITYORDERSOURCEOUTCOME for active rows only. rows="$(awk ' - /^## Open items/ { inopen=1; next } - /^## / { if (inopen) inopen=0 } - inopen && /^\| #[0-9]/ { + /^## Prioritised queue/ { inqueue=1; next } + /^## / { if (inqueue) inqueue=0 } + inqueue && /^\|[[:space:]]*[0-9]+[[:space:]]*\|/ { n=split($0, c, "|") - id=c[2]; pri=c[3]; typ=c[4]; sum=c[5] - gsub(/^[ \t]+|[ \t]+$/, "", id) - gsub(/^[ \t]+|[ \t]+$/, "", pri) - gsub(/^[ \t]+|[ \t]+$/, "", typ) - gsub(/^[ \t]+|[ \t]+$/, "", sum) - printf "%s\t%s\t%s\t%s\n", pri, id, typ, sum + ord=c[2]; src=c[3]; outcome=c[4]; acuity=c[5] + gsub(/^[ \t]+|[ \t]+$/, "", ord) + gsub(/^[ \t]+|[ \t]+$/, "", src) + gsub(/^[ \t]+|[ \t]+$/, "", outcome) + gsub(/^[ \t]+|[ \t]+$/, "", acuity) + printf "%s\t%s\t%s\t%s\n", acuity, ord, src, outcome } ' "$ledger" 2>/dev/null || true)" total="$(printf '%s' "$rows" | grep -c . || true)" if [ "${total:-0}" -eq 0 ]; then - echo "[issues] Outstanding-work memory (docs/outstanding-issues.md): no open items. Record one with /issues add …" + echo "[issues] Universal task ledger (docs/outstanding-issues.md): no active recommended work. Record one with /issues add …" exit 0 fi group() { printf '%s\n' "$rows" | awk -F'\t' -v p="$1" '$1==p'; } count() { printf '%s' "$1" | grep -c . || true; } -p1="$(group P1)"; p2="$(group P2)"; p3="$(group P3)" -c1="$(count "$p1")"; c2="$(count "$p2")"; c3="$(count "$p3")" +a1="$(group A1)"; a2="$(group A2)"; a3="$(group A3)"; optional="$(group Optional)" +c1="$(count "$a1")"; c2="$(count "$a2")"; c3="$(count "$a3")"; co="$(count "$optional")" -echo "[issues] Outstanding-work memory — ${total} open (${c1}×P1, ${c2}×P2, ${c3}×P3). Source of truth: docs/outstanding-issues.md · read the full list back with /issues." +echo "[issues] Universal task ledger — ${total} active (${c1}×A1, ${c2}×A2, ${c3}×A3, ${co} optional). Source of truth: docs/outstanding-issues.md · read the full queue with /issues." -print_group() { # $1=rows $2=max-to-list - local data="$1" limit="$2" shown=0 more=0 pri id typ sum +print_group() { + local data="$1" limit="$2" shown=0 more=0 acuity ord src outcome [ -z "$data" ] && return 0 - while IFS=$'\t' read -r pri id typ sum; do - [ -z "$pri" ] && continue + while IFS=$'\t' read -r acuity ord src outcome; do + [ -z "$acuity" ] && continue if [ "$shown" -lt "$limit" ]; then - echo " ${pri} ${id} ${typ} — ${sum}" + echo " ${ord}. ${acuity} ${src} — ${outcome}" shown=$((shown + 1)) else more=$((more + 1)) @@ -70,22 +60,21 @@ print_group() { # $1=rows $2=max-to-list done <` (summary/detail substring match). +If a filter is given, narrow step 2: `/issues A2`, `/issues Optional`, `/issues `, or +`/issues ` (queue outcome/evidence substring match). ## Mutating subcommands Parse the intent from natural language too — the exact syntax is a convenience, not a requirement. -- **`/issues add `** — append a row to **Open items**. Infer `Pri`/`Type` from the text - (ask only if genuinely ambiguous; default `P2`/`task`). Allocate the ID from the - `` marker, then bump that marker. Fill `Source` with - `session ` unless the user names one; `Added` is today's date. -- **`/issues done [outcome]`** — move that row from **Open items** to **Resolved / archive** - with today's date and a one-line outcome. Archive, never delete. -- **`/issues update `** — edit an open row's summary or next action in place. +- **`/issues add `** — add one row to the **Prioritised queue** with order, source/ID, + outcome, acuity, capability, timing, effort, dependencies/approvals, and success/stop rule. Add a + supporting evidence-register row when the task needs a durable issue ID. Allocate that ID from + ``, bump the marker, and use `session ` as the source when none + is supplied. +- **`/issues done [outcome]`** — remove the active queue row and move/update its + evidence row under **Resolved / archive** with today's date and a one-line outcome. Archive, + never erase evidence. +- **`/issues update `** — update the queue row and its evidence row together. - **`/issues capture`** — scan the current session for recommendations, follow-ups, deferrals, and unfixed problems that surfaced but were not recorded. Propose them as a numbered list and add the confirmed ones (dedupe against existing rows first — do not re-add something already tracked). @@ -52,7 +54,10 @@ paragraph; put the smallest next action in **Detail / next action**. ## Writing rules -- Keep the table format and column order exactly as in `docs/outstanding-issues.md`. One row per item. +- Keep the queue and evidence table formats exactly as in `docs/outstanding-issues.md`. One queue + row per active work order. +- Renumber the active queue when sequencing changes; evidence IDs remain monotonic and never change. +- An evidence-register row is not active work unless it also appears in the Prioritised queue. - IDs are monotonic and never reused — always allocate from the `issues:next-id` marker and bump it. - Escape `|` inside cell text (write `\|`) so the markdown table stays intact. - Respect the repo's RAG/clinical/privacy flagging rules if an item _itself_ touches a protected @@ -60,8 +65,8 @@ paragraph; put the smallest next action in **Detail / next action**. ## Persist the memory (commit) -After any mutation, stage and commit **only** `docs/outstanding-issues.md` so the memory survives the -ephemeral container and other worktrees: +After a ledger-only mutation, stage and commit **only** `docs/outstanding-issues.md` so the memory +survives the ephemeral container and other worktrees: ``` git add docs/outstanding-issues.md diff --git a/AGENTS.md b/AGENTS.md index 32d9bc6c0..cd5227f6a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -454,9 +454,19 @@ Run the matching planner command in `docs/productivity-workflows.md` without sid **recommendation**, and **issue** for this repo. Chat context resets between sessions; that file does not, so anything worth remembering after a session ends belongs there. +`docs/outstanding-issues.md` is the single universal task ledger. Its active queue owns dependency +order, acuity, required capability, timing, effort, approvals, success criteria, verification, and +stop rules; the same file preserves evidence, decisions, and resolution history. Detailed provider +runbooks may remain in `docs/operator-backlog.md`, but every provider action still recommended must +also appear in the active queue. Update the affected sections together when work is completed, +dropped, superseded, or materially re-scoped. Never copy completed, stale, duplicate, speculative, +or rejected work back into the active queue. + - When the user types `/issues`, invoke the `issues` skill (`.claude/skills/issues/SKILL.md`): read - `docs/outstanding-issues.md` and state the open items back, grouped by priority. A plain `/issues` - is read-only — it mutates and commits nothing. + `docs/outstanding-issues.md` and state the **Prioritised queue** back in execution order, including + source/ID, acuity, timing, dependencies/approvals, and stop rule. Evidence-register rows are not + active work unless they also appear in that queue. A plain `/issues` is read-only — it mutates + and commits nothing. - `/issues add|done|update|capture …` mutate the ledger; each mutation commits **only** `docs/outstanding-issues.md` (no push unless the user asks or you are already handing off). - Proactively offer to `capture` unresolved follow-ups, deferrals, and known risks into the ledger diff --git a/docs/README.md b/docs/README.md index 0b743e80c..8099c35ec 100644 --- a/docs/README.md +++ b/docs/README.md @@ -71,6 +71,7 @@ npm run docs:check-links ## Plans and workstreams (living) +- [outstanding-issues.md](outstanding-issues.md) — single universal task ledger, prioritised execution queue, evidence and resolution memory - [maturity-backlog-workorders.md](maturity-backlog-workorders.md) — actionable work orders tracking the repository-maturity audit backlog - [framework-dependency-modernization-checklist.md](framework-dependency-modernization-checklist.md) — ordered Next.js 16, runtime, dependency, Turbopack, and verification migration program - [search-rag-master-plan.md](search-rag-master-plan.md) / [search-rag-master-context.md](search-rag-master-context.md) — search/RAG roadmap and shared context diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md index b9b2a8b96..09735f14f 100644 --- a/docs/branch-review-ledger.md +++ b/docs/branch-review-ledger.md @@ -20,7 +20,8 @@ Use this ledger to prevent repeated branch and PR reviews when the reviewed HEAD | Date | Branch or ref | Reviewed HEAD | Scope | Outcome | Checks | | ---------- | -------------------------------------------------------- | ---------------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 2026-07-24 | `codex/supabase-document-change-trigger` | `9c7d9edf509a51478f5bebbabcca64e3926dc877` + reviewed working diff | Document-change ingestion trigger migration, schema mirror, grants, privacy and fail-safe delivery | APPROVE. No P0-P2 finding. The trigger is update-only, acts solely on a strict JSON boolean false/absent-to-true transition, sends only the receiver's allowlisted owner-scoped fields, fails open for document writes when Vault/GUC/pg_net is unavailable, and revokes execution from public/anon/authenticated. No production URL fallback exists. Highest residual risk is deliberate pg_net at-most-once delivery; the clear-then-flip recovery and data-preserving rollback are documented, and the trigger remains inert until both the Vault secret and environment base-URL GUC are configured. | Disposable `supabase/postgres:17.6.1.127` schema replay and drift-manifest regeneration passed (16s; scratch container removed); focused schema/drift/receiver Vitest 89/89; migration-role, function-grant (30 SECURITY DEFINER functions) and owner-scope guards; production-readiness CI mode READY with expected secretless-worktree warnings; offline RAG 21 suites/307 tests; `verify:cheap` 365 files, 3,241 passed/1 skipped; static trace of receiver payload, authoritative owner-scoped reload and idempotent enqueue path. No live provider mutation or migration apply. | +| 2026-07-24 | `codex/task-ledger-authoritative-1c2750` | `60b1e2ffb551dc3ae1b958da480e6e1c469fc4d7` + reviewed working diff | Universal task-ledger consolidation, repository-memory hook and `/issues` workflow | APPROVE after three review fixes: removed a stray Markdown `+`, used the reviewed-working-diff convention, and aligned root `/issues` guidance with the authoritative prioritised queue. `docs/outstanding-issues.md` is the only active task ledger, retains evidence and resolution history, and exposes 30 recommended rows with explicit order, acuity, capability, timing, effort, approvals and stopping conditions. The read-only session hook parses only that active queue; legacy evidence rows cannot become executable accidentally. No secondary ledger reference remains, and Supabase actions in the active queue target only Clinical KB Database. | Exact branch diff review; `verify:pr-local` passed runtime, changed-file formatting, lint, typecheck, 365 Vitest files / 3,241 passed / 1 skipped, and 36-case/21-suite offline RAG fixtures; hook syntax/runtime reported 30 active (0 A1, 14 A2, 10 A3, 6 optional); docs link check 1,124 references; codebase index 42 modules/routes plus all schema tables; focused post-review docs link/index and `git diff --check` passed. No live Supabase/OpenAI/deployment workflow ran. | +| 2026-07-24 | `codex/supabase-document-change-trigger` | `9c7d9edf509a51478f5bebbabcca64e3926dc877` + reviewed working diff | Document-change ingestion trigger migration, schema mirror, grants, privacy and fail-safe delivery | APPROVE. No P0-P2 finding. The trigger is update-only, acts solely on a strict JSON boolean false/absent-to-true transition, sends only the receiver's allowlisted owner-scoped fields, fails open for document writes when Vault/GUC/pg_net is unavailable, and revokes execution from public/anon/authenticated. No production URL fallback exists. Highest residual risk is deliberate pg_net at-most-once delivery; the clear-then-flip recovery and data-preserving rollback are documented, and the trigger remains inert until both the Vault secret and environment base-URL GUC are configured. | Disposable Supabase Postgres image 17.6.1.127 schema replay and drift-manifest regeneration passed (16s; scratch container removed); focused schema/drift/receiver Vitest 89/89; migration-role, function-grant (30 SECURITY DEFINER functions) and owner-scope guards; production-readiness CI mode READY with expected secretless-worktree warnings; offline RAG 21 suites/307 tests; `verify:cheap` 365 files, 3,241 passed/1 skipped; static trace of receiver payload, authoritative owner-scoped reload and idempotent enqueue path. No live provider mutation or migration apply. | | 2026-07-23 | PR #1090 / `cursor/fix-phone-dock-edge-1b1d` | `761de7e9ad623b6bd8d634d849a9eb465d622e48` (merged as `09028ef217209fceb53f1122ac7738b509bce323`) | Phone safe-area and edge-to-edge search-dock UI review | MERGED. No P0-P2 finding. The branch was three commits behind, so current `origin/main` was merged before landing; the actual merge tree matched the reviewed synthetic tree. The dock remains flush to the viewport with safe-area padding inside the form, and the phone shell no longer retains the `dvh` clamp that created the Safari toolbar band. Zero actionable review threads. | `npm run ensure`; focused `ui-tools.spec.ts` phone-home and edge-to-edge scenarios: Chromium 2/2 and WebKit 2/2; refreshed hosted policy, security, unit, build, advisory UI, Production UI and required aggregate checks green; exact-head ancestry and local-main tree equality proved after merge. | | 2026-07-22 | PR #1087 / `codex/reconcile-product-truth` | `edbc2260fef59ca2fa7c6973dffb85e32354bce1` (merged as `05dc52fd8408a65117e22a6236e43252203bea92`) | Product-truth copy, account persistence and unavailable-SSO presentation | MERGED. Cross-device claims now match favourites/preferences persistence; recent searches are identified as browser-session data; the contradictory “never shared” statement is removed. All unavailable setup providers and Apple elsewhere use the connected accessible “coming soon” placeholder pattern. The single review finding was fixed, replied to and resolved. | Red DOM proof; focused 19/19; `verify:cheap` 3,220 passed / 1 skipped; `verify:ui` 265/265; PR-local build/secret scan/offline RAG; final hosted required, Production UI, policy and security checks green. No provider calls or RAG spend. | | 2026-07-22 | PR #1086 / `codex/reconcile-xlsx-budgets` | `5376880a40749b6526fd7e4603a7be9d04bc9624` (merged as `2963fba46eacd644618a588fa283f7597faa2644`) | XLSX resource-boundary review | MERGED. Enforces worksheet, non-empty-row, rendered-cell and UTF-8 output ceilings before result fragments are appended; sparse-column output is preserved. No actionable review threads. | Red 257-sheet reproducer; focused 4/4; `verify:cheap` 3,218 passed / 1 skipped; PR-local build/scan/offline RAG; hosted required/security/policy green. | diff --git a/docs/codebase-index.md b/docs/codebase-index.md index c7d597ed5..aa92ad7ad 100644 --- a/docs/codebase-index.md +++ b/docs/codebase-index.md @@ -334,6 +334,7 @@ One shared composer (`master-search-header.tsx`) serves every mode. Placement: | Full documentation index | `docs/README.md` | | Routes and modes | `docs/site-map.md` | | Search/RAG roadmap | `docs/search-rag-master-plan.md` | +| Universal task ledger | `docs/outstanding-issues.md` | | Reindex operations | `docs/reindex-runbook.md` | | Production readiness | `docs/production-readiness-checklist.md` | | Capacity / scale-up | `docs/capacity-review.md`, `docs/auth-connection-cap-runbook.md` | diff --git a/docs/operator-backlog.md b/docs/operator-backlog.md index eb749675b..61475db57 100644 --- a/docs/operator-backlog.md +++ b/docs/operator-backlog.md @@ -1,8 +1,12 @@ # Operator backlog -Single source of truth for **human-only / provider-gated actions** that cannot be done from a coding +Detailed register for **human-only / provider-gated actions** that cannot be done from a coding session (they touch Supabase, Railway, OpenAI, or GitHub settings, per the AGENTS.md provider boundary). -This exists so that launch-blocking state lives in the repo instead of chat memory. +The universal task ledger remains `outstanding-issues.md`. + +The deduplicated execution order is in [`outstanding-issues.md`](outstanding-issues.md). Supabase work +in its active queue targets only `Clinical KB Database` (`sjrfecxgysukkwxsowpy`); this register must +not reintroduce work for another Supabase project. **How to use:** work top to bottom; each row links to the detailed runbook. `Status` values are `⏳ pending`, `🔎 verify` (may already be done — confirm before repeating), `✅ done`, `—` (n/a). @@ -17,15 +21,13 @@ Findings inventory for handover: [audit-handover-2026-07-14.md](audit-handover-2 ## Launch-gating actions -| Action | Status | Blocked by | Verify command | Runbook | -| -------------------------------------------------------------------------- | ---------- | -------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Apply July-8 migration batch (a–g) to live | ✅ done | — | `SUPABASE_ENVIRONMENT=production npm run check:july8-live-batch` (2026-07-13: 6 live, apply=no-op) | [operator-apply-july8-batch.md](operator-apply-july8-batch.md) | -| Apply drift-codify forward migration (step 1h) | ✅ done | — | Applied and drift/readiness verified 2026-07-13; verify only unless new reviewed drift is found | [database-drift-detection.md](database-drift-detection.md) | -| Apply repo-ahead migrations to live (post-2026-07-13) | ✅ done | — | Zero unsafe title-word rows; `npm run check:drift`; then `eval:retrieval:quality` (36/36) for the corrector | [deploy-corrector-public-titles.md](deploy-corrector-public-titles.md) · [operator-apply-performance-latency-remediation.md](operator-apply-performance-latency-remediation.md) | -| Full release gate (bounded OpenAI spend) | ⏳ pending | migrations 1 applied | `npm run verify:release`; `npm run eval:quality -- --rag-only` | [launch-operator-runbook.md §2](launch-operator-runbook.md) | -| Provision staging Supabase project (`Clinical KB Staging`, ap-southeast-2) | ⏳ pending | — | `npm run check:indexing` after `db push` | [staging-setup.md](staging-setup.md) | -| Staging soak + rollback rehearsal on Railway | ⏳ pending | staging provisioned | `scripts/soak-test.ts --confirm-staging` (answer p95 ≤ 25 s) | [launch-operator-runbook.md §4](launch-operator-runbook.md) · [capacity-review.md](capacity-review.md) | -| Production deploy to Railway | ✅ done | — | App deployment recorded live 2026-07-14; re-verify with `GET /api/health` and deployment readiness | [deployment-architecture.md](deployment-architecture.md) | +| Action | Status | Blocked by | Verify command | Runbook | +| ----------------------------------------------------- | ---------- | -------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Apply July-8 migration batch (a–g) to live | ✅ done | — | `SUPABASE_ENVIRONMENT=production npm run check:july8-live-batch` (2026-07-13: 6 live, apply=no-op) | [operator-apply-july8-batch.md](operator-apply-july8-batch.md) | +| Apply drift-codify forward migration (step 1h) | ✅ done | — | Applied and drift/readiness verified 2026-07-13; verify only unless new reviewed drift is found | [database-drift-detection.md](database-drift-detection.md) | +| Apply repo-ahead migrations to live (post-2026-07-13) | ✅ done | — | Zero unsafe title-word rows; `npm run check:drift`; then `eval:retrieval:quality` (36/36) for the corrector | [deploy-corrector-public-titles.md](deploy-corrector-public-titles.md) · [operator-apply-performance-latency-remediation.md](operator-apply-performance-latency-remediation.md) | +| Full release gate (bounded OpenAI spend) | ⏳ pending | migrations 1 applied | `npm run verify:release`; `npm run eval:quality -- --rag-only` | [launch-operator-runbook.md §2](launch-operator-runbook.md) | +| Production deploy to Railway | ✅ done | — | App deployment recorded live 2026-07-14; re-verify with `GET /api/health` and deployment readiness | [deployment-architecture.md](deployment-architecture.md) | ## Post-deploy actions diff --git a/docs/outstanding-issues.md b/docs/outstanding-issues.md index e31b22152..a3b38aa22 100644 --- a/docs/outstanding-issues.md +++ b/docs/outstanding-issues.md @@ -7,19 +7,34 @@ Durable, cross-session memory of everything still outstanding for this repo: ope **Rule of thumb:** if it is worth remembering after this session ends, it belongs here. +This file is the repository's **single universal task ledger**. It owns the active recommended +execution queue, order, acuity, capability, timing, effort, dependencies, approvals, success and +stop rules, detailed evidence, decisions, and resolution history. Provider-specific runbook detail +may remain in `operator-backlog.md`, but every provider action that is still recommended must also +appear in the active queue here. + ## How this is used - Say `/issues` in Claude Code → the skill reads this file and states the open items back, - grouped by priority with a one-line summary count. Nothing is mutated on a plain read. -- `/issues add …`, `/issues done `, `/issues capture`, and friends mutate the tables below. - The full command surface lives in the skill file. + in **Prioritised queue** execution order with counts by acuity. Nothing is mutated on a plain + read, and evidence-register rows are not reported as active work unless they also appear in the + queue. +- `/issues add …`, `/issues done `, `/issues capture`, and friends update the queue, + supporting evidence register, and resolved archive as defined by the skill. The full command + surface lives in the skill file. - Every mutation keeps this file committed so the memory survives across sessions and worktrees. ## Conventions -- **ID** is a monotonic `#NNN`, never reused. Allocate the next number above the current max - across _both_ tables (open + resolved). -- **Pri**: `P1` (do next / blocking), `P2` (should do), `P3` (nice-to-have / revisit-when). +- **Order** is the active execution sequence. Renumber it when dependencies change; gaps may remain + when work completes so older handoffs keep their meaning. +- **Acuity**: `A1` (immediate/highest impact), `A2` (important), `A3` (lower urgency), or + `Optional`. Order also accounts for dependencies, timing, approvals, cost, risk, and stop rules. +- **ID** is a monotonic evidence reference (`#NNN`), never reused. Allocate it from the + `issues:next-id` marker when a task needs a durable evidence row; queue rows may instead use a + descriptive source. +- The evidence register's legacy **Pri** field preserves historical triage only; it does not set + active execution order. - **Type**: `task` (a concrete unit of work), `rec` (a recommendation to weigh), or `issue` (a defect / risk / gap). - **Detail / next action** is the smallest thing that would move the item forward. @@ -27,9 +42,77 @@ Durable, cross-session memory of everything still outstanding for this repo: ope - Resolving an item moves its row to **Resolved / archive** with the date and a one-line outcome — rows are archived, not deleted, so the history stays auditable. - + + +## Supabase scope + +Every Supabase task here targets **Clinical KB Database** (`sjrfecxgysukkwxsowpy`). No task +provisions, populates, migrates, verifies, or depends on another Supabase project. Stop whenever a +command, environment, dashboard, or URL identifies a different project. + +## Scales + +- **A1:** urgent active safety, privacy, data-loss, or release blocker. No current task qualifies. +- **A2:** important confirmed correctness, clinical, privacy, reliability, or evaluation work. +- **A3:** worthwhile work gated by timing, evidence, or a decision. +- **Optional:** act only with the named need, owner, and acceptable cost. +- **Standard:** experienced generalist. **High:** senior cross-module reasoning. **Specialist:** + database, RAG, clinical-safety, privacy, or evaluation expertise. **Operator:** authorised human + with the named provider, product, legal, or clinical authority. +- Effort is focused active work and excludes approval, CI, provider, schedule, soak, and review wait. + +## Prioritised queue + +Order numbers are stable cross-session references. A gap remains when an active row completes so +older handoffs keep their meaning; new tasks receive an explicit order during triage. + +| Order | Source | Outcome / smallest next action | Acuity | Intelligence required | When | Active effort | Dependencies / approvals | Success, verification, and stop rule | +| ----: | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------- | -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | `#052` | Prevent full/retry reindex from overlapping a fresh agent-enrichment lease. Add red single/bulk tests, then reuse `hasActiveAgentEnrichmentJob` before mutation. | A2 | High — ingestion concurrency | **Ready; do first.** | 0.5–1 day | Local/offline. | Fresh leases block; stale/absent leases and enrichment mode retain behaviour. Run focused mutation tests, `verify:cheap`, and production-readiness. Stop before live DB use. | +| 2 | Queue reliability prerequisite | Detect aged `queued` documents with no open ingestion job and add one idempotent, owner-scoped recovery path with grace period and dry-run visibility. | A2 | Specialist — queue/database reliability | **After order 1; before ingestion webhook activation.** | 0.5–1 day | Local replay if schema/scheduling changes; approval only for later deployment. | A controlled orphan receives exactly one job and active jobs never duplicate. Run focused recovery/autopilot tests and production-readiness. Stop before live mutation. | +| 3 | `#030` | Require distinct source identities for distinct expected comparison slots; start with a shared-title/two-expectation red test. | A2 | High — evaluation semantics | **Ready; may run with order 1.** | 2–4 hours | Local/offline; protected eval review. | One source cannot satisfy both slots and valid cases remain green. Run focused eval tests, typecheck, and `verify:cheap`. Stop without changing aliases, retrieval, or ranking. | +| 4 | `#022` | Decide an auditable BMJ published-reference policy, then review the ten highest-impact local WA documents. | A2 | Operator — clinical governance with specialist review | **Decision-ready.** | 1–2 hours policy; 0.5–1 day review | Clinical decision; approval for live metadata writes or canary. | Record reviewer, evidence, time, and rationale without erasing third-party/unverified provenance. Stop after ten and remeasure. | +| 5 | `#051` + `#023` | Compare run `30018289898` with the scheduled structured canary, browser, and irrelevant-at-10 artifacts; decide whether protected RAG work may resume. | A2 | Specialist — RAG diagnostics/evaluation | **After scheduled run, about 2026-07-27 02:00 AWST plus runtime.** | 2–4 hours | Approval to read hosted GitHub artifacts; do not dispatch or rerun. | Record run identity, deterministic/provider/latency deltas, browser outcomes, and labels; close or rewrite source issues. Stop without spend or restoring the archived lithium guard. | +| 6 | `#019` | Prove the admission source is lost in the comparison fallback layer using PR #1096’s pinned source shape, then scope the smallest correction. | A2 | Specialist — RAG answer pipeline | **After order 5.** | 0.5–1 day reproducer | Stable canary decision; protected review and approved post-change canary. | Unit reproducer fails for the omission while deterministic packing retains both sources. Stop if not reproducible. | +| 7 | `#018` | Diagnose lithium, ADHD, and metabolic residuals separately: unrelated-table fast path, extractive budget exhaustion, and schedule-free prose selection. | A2 | Specialist — clinical RAG/retrieval | **After order 5; one mechanism at a time.** | 1–2 days diagnosis; fixes separate | Stable canary; protected review and approval for behaviour canaries. | Each mechanism gets its own current-main failing fixture and scoped candidate. Stop without a deterministic reproducer or on individual canary regression. | +| 8 | `#029` | Re-enumerate current fallback-stub cases and improve one demonstrated causal cluster at a time without weakening fail-closed behaviour. | A2 | Specialist — RAG/clinical safety | **After orders 5–7 clarify overlap.** | 0.5–1 day inventory; 1–3 days per fix | Provider-backed answer validation needs approval. | Retain grounding/citation gates; do not reuse historical 12/30 or keyword-only targeting. Stop after each validated cluster or if a change only makes the metric easier. | +| 9 | `#001` | Reassess semantic reranking without changing the default; enable only after an accepted ambiguity-specific comparison. | A2 | Specialist — retrieval/ranking | **After order 5 and explicit rollout approval.** | 0.5–1 day plus canary review | Provider approval and budget. | Keep the flag false unless retrieval stays 36/36, recall stays 1.0, no case regresses, and measured gain exists. Otherwise record “remain off” and stop. | +| 10 | `#024` | Distinguish Playwright `_rsc` interception failure from a real Safari defect so WebKit release evidence is trustworthy. | A3 | High — Next.js/Playwright/WebKit | **After order 5’s matrix datapoint, or on a real Safari reproduction.** | 0.5–1 day | Device/provider check only if local evidence remains ambiguous. | A test-only correction has a discriminating reproducer; access/navigation assertions stay meaningful and Chromium stays green. Stop when signal is trustworthy. | +| 11 | `#007` | Choose one canonical Tools experience and align navigation, redirects, sitemap, and reachability. | A3 | Operator product decision, then Standard frontend | **When owner chooses dashboard mode or standalone page.** | 15–30 minute decision; 0.5 day code | Product decision. | One canonical path and intentional compatibility redirect with green route/UI tests. Stop while standalone requirements remain unknown. | +| 12 | `#009` | Decide whether `/api/jobs` is intentional server/ops-only. Document and test it if retained; remove it if abandoned. | A3 | Standard — API ownership | **Next API maintenance batch.** | 1–2 hours | Product/operations owner and consumer check. | One owner/contract is recorded or unused route/tests are removed; focused tests and `verify:cheap` pass. Stop if external consumers cannot be ruled out. | +| 13 | `#010` | Wire a disabled Forms/Favourites placeholder only when its underlying feature is selected; retain the accessible placeholder otherwise. | Optional | Standard — frontend/product | **Per approved feature; no work now.** | 0.5–2 days per feature | Product scope and data contract. | Selected control performs its action with UI/accessibility coverage. Do not batch-build unrequested placeholders. | +| 14 | `#025` | Configure only the owned deployment, CI, chat, ingestion, and SLO alert channels. For document-change delivery, set the matching Railway secret, Supabase Vault secret, and base-URL GUC documented by PR #1101. | A2 | Operator — Railway/GitHub/chat/Supabase | **Next approved observability window; document-change delivery after order 2.** | 1–3 hours per channel | Provider approval, environment secrets, destination owner, exact project identity. | One controlled non-PHI event reaches each selected destination after mocked tests; a document change queues exactly once. Stop on missing ownership, target ambiguity, or unsafe delivery. | +| 16 | Production secret/config register | Verify presence/status before setting safety-identifier, query-hash, deep-probe, Supabase service-role and OpenAI secrets, project identity, or schedules. Use distinct per-environment secrets and never record values. | A2 | Standard locally; Operator hosted | **Local safety identifier now; hosted settings in an approved readiness window.** | 15–30 minutes local; 1–2 hours hosted | Secure secret manager, owners, provider approval for hosted reads/writes. | Presence-only checks and production-readiness pass; identifiers stay HMAC-pseudonymous and secret scans clean. Stop on target ambiguity. | +| 17 | Privacy/legal package | Execute OpenAI/Railway DPAs; decide ZDR and Australian residency; obtain prompt-cache/subprocessor answers; secure APP 8 and APP 5/1 counsel decisions. | A2 | Operator — legal/privacy with specialist support | **Start now; finish before real patient use or a privacy-approved release claim.** | 1–3 operator days plus external wait | Legal authority and provider engagement approval. | Signed/recorded decisions cover transfer, retention, cache, subprocessors, notice, and consent. Stop release claims while any basis remains unresolved. | +| 18 | Full release gate | Run full release and clinical-quality gates once against an exact recorded release candidate, never a moving branch. | A2 | Specialist release owner plus Operator | **Before the next release/handoff needing full confidence.** | 0.5 day plus hosted wait | Explicit OpenAI/Supabase/GitHub approval, bounded spend, exact SHA. | All required gates are recorded against one SHA. Stop and classify the first failure; do not repeat an unchanged pass. | +| 19 | Production content verification | In Clinical KB Database (`sjrfecxgysukkwxsowpy`), verify registry, differentials, and medications surfaces are non-empty before any write; seed only confirmed gaps. | A2 | Operator — data operations with domain specialist | **Next approved production verification window.** | 1–3 hours plus seed time if needed | Provider approval, verified project/owner identity, confirmation flags, rollback path. | Read-only proof precedes writes; only confirmed gaps are seeded and verified. Stop if already populated or target/owner is unclear. | +| 20 | `#011` | Change Supabase Auth from absolute connection cap to percentage allocation immediately before first compute scale-up in Clinical KB Database (`sjrfecxgysukkwxsowpy`). | A3 | Operator — Supabase capacity | **Trigger-gated; add to resize checklist.** | 30–60 minutes plus observation | Planned scale-up and provider approval. | Record before/after plus approved advisor and health rechecks against the named project. Stop if no scale-up is planned or identity differs. | +| 21 | `#017` | Capture one reproducible mobile and desktop production Lighthouse/Web-Vitals baseline before payload work. | A3 | High — web performance/browser | **Before order 22 in an approved live-site window.** | 1–2 hours | Live-site approval; record route, build, throttling, raw report. | Record representative LCP/INP/CLS and accept/reject payload work. Stop if acceptable or too noisy for a decision. | +| 22 | `#012` + `#013` + `#016` | Measure before selecting one payload, rendering, or motion lever; improve only a production route with a demonstrated budget or interaction problem. | A3 | High — Next.js bundle/runtime/UI performance | **After order 21; one target at a time.** | 0.5–3 days per target | Measured target, relevant Next.js guide, UI verification. | Define and meet a material transfer, parse, LCP, or interaction target while preserving behaviour/accessibility. Run analysis, focused tests, `verify:cheap`, browser smoke. Stop if gain is small. | +| 23 | `#033` | Decide whether governance metadata enters the LLM source block, using wording that distinguishes unknown from adverse status. | A3 | Specialist — prompt/source governance | **After orders 4–5.** | 1–2 days plus eval | Better metadata coverage, stable canary, provider approval. | Prompt/serialization tests pass; approved evidence shows no grounded-supported drop and zero citation failures. Stop on broad over-caveating or degradation. | +| 24 | `#035` | Expand threshold-conflict detection only for a concrete, clinically reviewed missed-conflict class with positive and false-positive fixtures. | A3 | Specialist — clinical evidence rules | **Only when a real missed conflict is demonstrated.** | 0.5–1 day design; implementation separate | Clinical review; provider approval only for live validation. | Fixtures discriminate the class and unrelated answers gain no warnings. Stop without code if no bounded class is supported. | +| 25 | `#036` | Decide whether explicit public visibility is worth an RLS/retrieval migration over `owner_id IS NULL` plus the visible unverified-source warning. | A3 | Specialist — tenancy/RLS/clinical search | **Before any visibility/public-corpus migration.** | 2–4 hours decision; implementation separate | Security/clinical review; migration/provider approval if adopted. | Compare threat model, migration, and rollback. Stop without schema work if the compensating control remains preferred. | +| 26 | `#037` | Decide whether routine supported claims should be capped at medium trust. | A3 | Operator — clinical/product, then Standard frontend | **Next trust/authority policy review.** | 30–60 minute decision; up to 0.5 day code | Clinical/product authority. | Record policy; if accepted, change only flag/render expectations and run focused tests. Stop without code if no owner accepts the trade-off. | +| 27 | `#027` | Decide whether independent uptime monitoring justifies vendor/operating cost; if yes, monitor `/api/health` outside GitHub/Railway. | Optional | Operator — SRE/provider | **When an owned external outage path is wanted.** | 1–2 hours | Vendor, cost, privacy, owner, provider approval. | Controlled failure produces one non-PHI alert and recovery notice. Stop if no responder or existing monitoring is sufficient. | +| 28 | `#028` | Define vendor, region, retention, redaction, sampling, source-map, and alert-ownership boundaries before runtime error tracking. | Optional | Specialist — privacy/observability plus Operator | **Only after privacy, ownership, dependency, and cost approval.** | 1–3 days | Privacy review and provider approval. | Tests prove clinical text, identifiers, and secrets stay out; one approved non-sensitive event arrives. Stop if processing envelope is unacceptable. | +| 29 | `#038` | Define a shared comparison interaction contract before adding another comparison surface; retain mode-specific clinical content. | Optional | High — product/design-system architecture | **Only when a new comparison surface is approved.** | 0.5–1 day | Concrete surface and product/design owner. | Inventory patterns and make shared behaviour testable. Stop if no new surface is planned. | +| 30 | `#039` | Inventory catalogue toolbars and converge only repeated filter, sort, result-count, and mobile behaviour when the next toolbar changes. | Optional | High — frontend architecture/UX | **With a concrete catalogue/search toolbar project.** | 0.5–1 day inventory; 1–3 days code | Product/design owner and UI verification. | Prove shared behaviour without flattening search semantics. Stop after the bounded repeated contract. | +| 31 | `#040` | Add a small approved visual-regression baseline set for stable high-value desktop/mobile and accessibility surfaces. | Optional | High — visual QA/accessibility | **When an owner and intentional-update process exist.** | 1–2 days | Owner, CI budget, stable environment, hosted-storage approval if used. | Baselines are deterministic, documented, and catch a controlled change without flaky churn. Stop if stable screenshots cannot be produced. | + +## Recommended sequence + +1. Do orders 1 and 3 now; complete order 2 before activating document-change ingestion. +2. Run clinical/operator order 4 independently and wait for the scheduled evidence before orders + 5–9. +3. Activate provider work only in approved batches: orders 14–20. +4. Start planned and optional work only when its row’s trigger is met; do not manufacture work to + fill the queue. + +## Evidence and source register -## Open items +The active queue above is authoritative for what should be done. The register below preserves +detailed evidence, historical wording, guarded decisions, and source references. A row in this +register is not executable unless it is represented in the active queue. > **Merged-main canary update (2026-07-23, run `30018289898`):** the new structured report correctly recorded evaluated tree `c24f2e8f2d30d0c59fc1eba025d3dcd63478137e`, run/attempt identity and `cross-region-runner` latency context. Golden retrieval remained 36/36 with document/content recall 1.0 and no failed cases. The 44-case answer gate had grounded-supported and unsupported-correct rates of 1.0, but failed because `neuroleptic-side-effect-escalation` again returned one citation where two are required (citation-failure rate 0.0227). `admission-discharge-comparison` again omitted the specific AKG admission document after `comparison_source_extractive_fallback`; `admission-discharge-coverage-paraphrase` was advisory-only at 24,870 ms. Answer cost was reported as `$0.234736`. Do not retry immediately: retain this as the first structured datapoint, compare it with the scheduled 2026-07-26 report, and keep retrieval/ranking unchanged. @@ -39,14 +122,14 @@ Durable, cross-session memory of everything still outstanding for this repo: ope | ---- | --- | ----- | --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ---------- | | #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 | +| #052 | P2 | issue | Reindex can overlap a fresh agent-enrichment pass | The shared ingestion preflight checks `ingestion_jobs`, but full/retry reindex routes do not consult the existing `hasActiveAgentEnrichmentJob` check. A fresh `indexing_v3_agent_jobs.status='processing'` lease can overlap destructive artifact work. Extend single and bulk full/retry preflights before mutation; keep stale leases non-blocking and preserve enrichment-mode behaviour. | `src/lib/ingestion-mutation-safety.ts:116-159`; single/bulk reindex routes; ingestion audit 2026-07-24 | 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). Correctly flagged (`aria-disabled` + "Coming soon"), not defects — wire when the underlying features land. | `forms-search-results-page.tsx`; `favourites-hub.tsx`; `favourites-command-library-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 | +| #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** immediately before the first compute scale-up — **not settable via SQL/MCP** (operator-owned). Target only `Clinical KB Database` (`sjrfecxgysukkwxsowpy`) and verify through approval-gated advisor and health re-checks; do not create or use another project for this task. | `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 | -| #014 | P3 | rec | Realize the `next/image` win on signed previews | `next.config` `images` (AVIF + `*.supabase.co` `remotePatterns` pinned to the project host, from #1024) is currently inert — signed document/image previews still render as raw ``. Route them through `next/image` to actually get AVIF + lazy optimization. | #1024; `src/components/clinical-dashboard/signed-image.tsx`; session 2026-07-21 | 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 | @@ -55,7 +138,7 @@ Durable, cross-session memory of everything still outstanding for this repo: ope | #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 | P3 | 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 | +| #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/#1101; 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 | @@ -78,6 +161,7 @@ Move resolved rows here with the resolution date and a one-line outcome. Keep th | ID | Type | Summary | Outcome | Resolved | | ---- | ----- | ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | | #026 | task | Wire the Supabase document-change trigger | PR #1100 merged after disposable PostgreSQL replay and hosted migration replay. Production migration history and read-only catalog proof confirm the enabled metadata trigger, security-definer function, pinned search path and denied anonymous/authenticated execution; `npm run check:drift` reports no unexpected live drift. Delivery remains intentionally inert until the operator inputs tracked in #025 are configured. | 2026-07-24 | +| #014 | rec | Realize the `next/image` win on signed previews | Superseded by the privacy-safe implementation: `SignedImage` now uses `next/image` for layout and responsive sizing but deliberately sets `unoptimized`, preventing bearer signed URLs from entering the unauthenticated optimizer cache where cached content could outlive the token. No optimization task remains unless the private-image delivery architecture changes. | 2026-07-24 | | #031 | issue | Populate canary Source Governance table | The answer-quality step now consumes the preceding `golden-retrieval.json` only for source-governance reporting. Offline replay of run `30018289898` populated 338 top results, including 202 review-required entries, while retaining zero retrieval cases and no additional threshold failures. Retrieval and ranking behavior are unchanged. | 2026-07-24 | | #020 | task | Validate eval:quality cost readout post-fix | Confirmed on merged-main canary run `30018289898`: Answer Metrics reported 9 nonzero-cost cases and an estimated answer cost of `$0.234736`; the structured report retained the same value. The PR #1050 estimator fix is operationally proven. | 2026-07-23 | | #003 | task | Staging tenancy release evidence outstanding | Ran GitHub Action and validated isolation | 2026-07-21 |