Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 153 additions & 0 deletions tests/docs-status-updates.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import { existsSync, readFileSync, readdirSync } from "node:fs";
import path from "node:path";
import { describe, expect, it } from "vitest";

// Guards the 2026-07-17 status-refresh edits to three operator/audit-tracking
// docs. These docs are read by operators and future agents as the source of
// truth for what is done vs. still open, so a wrong status or a dangling file
// reference is a real regression, not just prose drift.

const repoRoot = process.cwd();
const docsDir = path.join(repoRoot, "docs");
const migrationsDir = path.join(repoRoot, "supabase", "migrations");

function readDoc(name: string) {
return readFileSync(path.join(docsDir, name), "utf8");
}

function migrationExists(timestampPrefix: string) {
return readdirSync(migrationsDir).some((file) => file.startsWith(timestampPrefix));
}

/** Returns the single line of `doc` that contains `needle`, or undefined. */
function lineContaining(doc: string, needle: string) {
return doc.split("\n").find((line) => line.includes(needle));
}

describe("docs/audit-remediation-plan-2026-07-14.md — 2026-07-17 reconciliation", () => {
const doc = readDoc("audit-remediation-plan-2026-07-14.md");

it("adds the reconciliation section for the memory-tasks review pass", () => {
expect(doc).toContain("Reconciliation");

Check failure on line 31 in tests/docs-status-updates.test.ts

View workflow job for this annotation

GitHub Actions / Unit coverage

[node] tests/docs-status-updates.test.ts > docs/audit-remediation-plan-2026-07-14.md — 2026-07-17 reconciliation > adds the reconciliation section for the memory-tasks review pass

AssertionError: expected '# Audit remediation plan — 2026-07-14…' to contain 'Reconciliation' - Expected + Received - Reconciliation + # Audit remediation plan — 2026-07-14 + + Plan derived from the multi-skill repository audit of `main` @ `570e6ba` (ledger rows in + [`branch-review-ledger.md`](branch-review-ledger.md)). This document is the sequenced address plan for + every finding: major blockers first, then P2 sub-issues, then P3 cleanup. + + **Findings handover (inventory + status):** [`audit-handover-2026-07-14.md`](audit-handover-2026-07-14.md). + + **Rules for executing this plan** + + - Prefer the smallest safe change per finding; do not bundle unrelated domains in one PR. + - Code fixes use `npm run verify:cheap` first, then the smallest domain check, then + `npm run verify:pr-local` before handoff. + - Provider/live actions are **operator-gated** (`⏸`). Do not run them without explicit confirmation. + - Reconcile [`operator-backlog.md`](operator-backlog.md) against + [`launch-operator-runbook.md`](launch-operator-runbook.md) before repeating any historical apply. + + **Legend** + + | Tag | Meaning | + | --------------- | ----------------------------------------------------- | + | **OWNER:CODE** | Implementable in-repo | + | **OWNER:OPS** | Railway / Supabase / GitHub / OpenAI dashboard or CLI | + | **OWNER:LEGAL** | Privacy officer / counsel | + | **⏸** | Provider or legal confirmation required | + | **Prove** | Smallest acceptance check | + + --- + + ## 0. Recommended delivery waves + + Work top-down. Later waves assume earlier majors are either done or consciously deferred. + + ```text + Wave A Confirm live/ops truth (doc sync) OWNER:OPS ⏸ + Wave B Launch / privacy blockers OWNER:LEGAL+OPS ⏸ + Wave C Code P1 availability (catalog rate limits) OWNER:CODE + Wave D Security & tenancy P2 OWNER:CODE (+OPS for live A/B) + Wave E Ingestion / recovery P2 OWNER:CODE + Wave F CI / testing / config P2 OWNER:CODE + Wave G Frontend a11y P2 OWNER:CODE + Wave H API contract hygiene P2 OWNER:CODE + Wave I P3 backlog + structure debt OWNER:CODE/OPS + Wave J Release confidence close-out OWNER:OPS ⏸ + ``` + + Suggested PR granularity (one theme per PR): + + 1. Catalog rate-limit + public DTO redaction + 2. Ingestion recovery + commit fallback + 3. CI scope + critical safety assert + flake hygiene + 4. A11y (describedby / icons / Tab / live region) + 5. JSON error taxonomy + admin rate limits + 6. Env example / bundle budget / summarize public scope + 7. Operator backlog status reconciliation (docs-only) + + --- + + ## Wave A — Confirm live truth before acting + + ### A1. Reconcile operator backlog vs launch runbook + + | | | + | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | + | **Finding** | M5 — backlog still `⏳` for drift-codify / prod deploy / worker while runbook says more is already live | + | **Owner** | OWNER:OPS (+ docs edit) | + | **Address** | Diff each backlog row against `launch-operator-runbook.md`, July-8 apply notes, empty `supabase/drift-allowlist
expect(doc).toContain("2026-07-17");
expect(doc).toContain("claude/memory-tasks-review-glmntq");
});

it("records F5 (.env.example weak-OR default) as done in code, matching src/lib/env.ts", () => {
expect(doc).toMatch(/F5[\s\S]{0,80}weak-OR[\s\S]{0,80}default corrected to `false`/);

Check failure on line 37 in tests/docs-status-updates.test.ts

View workflow job for this annotation

GitHub Actions / Unit coverage

[node] tests/docs-status-updates.test.ts > docs/audit-remediation-plan-2026-07-14.md — 2026-07-17 reconciliation > records F5 (.env.example weak-OR default) as done in code, matching src/lib/env.ts

AssertionError: expected '# Audit remediation plan — 2026-07-14…' to match /F5[\s\S]{0,80}weak-OR[\s\S]{0,80}defa…/ - Expected: /F5[\s\S]{0,80}weak-OR[\s\S]{0,80}default corrected to `false`/ + Received: "# Audit remediation plan — 2026-07-14 Plan derived from the multi-skill repository audit of `main` @ `570e6ba` (ledger rows in [`branch-review-ledger.md`](branch-review-ledger.md)). This document is the sequenced address plan for every finding: major blockers first, then P2 sub-issues, then P3 cleanup. **Findings handover (inventory + status):** [`audit-handover-2026-07-14.md`](audit-handover-2026-07-14.md). **Rules for executing this plan** - Prefer the smallest safe change per finding; do not bundle unrelated domains in one PR. - Code fixes use `npm run verify:cheap` first, then the smallest domain check, then `npm run verify:pr-local` before handoff. - Provider/live actions are **operator-gated** (`⏸`). Do not run them without explicit confirmation. - Reconcile [`operator-backlog.md`](operator-backlog.md) against [`launch-operator-runbook.md`](launch-operator-runbook.md) before repeating any historical apply. **Legend** | Tag | Meaning | | --------------- | ----------------------------------------------------- | | **OWNER:CODE** | Implementable in-repo | | **OWNER:OPS** | Railway / Supabase / GitHub / OpenAI dashboard or CLI | | **OWNER:LEGAL** | Privacy officer / counsel | | **⏸** | Provider or legal confirmation required | | **Prove** | Smallest acceptance check | --- ## 0. Recommended delivery waves Work top-down. Later waves assume earlier majors are either done or consciously deferred. ```text Wave A Confirm live/ops truth (doc sync) OWNER:OPS ⏸ Wave B Launch / privacy blockers OWNER:LEGAL+OPS ⏸ Wave C Code P1 availability (catalog rate limits) OWNER:CODE Wave D Security & tenancy P2 OWNER:CODE (+OPS for live A/B) Wave E Ingestion / recovery P2 OWNER:CODE Wave F CI / testing / config P2 OWNER:CODE Wave G Frontend a11y P2 OWNER:CODE Wave H API contract hygiene P2 OWNER:CODE Wave I P3 backlog + structure debt OWNER:CODE/OPS Wave J Release confidence close-out OWNER:OPS ⏸ ``` Suggested PR granularity (one theme per PR): 1. Catalog rate-limit + public DTO redaction 2. Ingestion recovery + commit fallback 3. CI scope + critical safety assert + flake hygiene 4. A11y (describedby / icons / Tab / live region) 5. JSON error taxonomy + admin rate limits 6. Env example / bundle budget / summarize public scope 7. Operator backlog status reconciliation (docs-only) --- ## Wave A — Confirm live truth before acting ### A1. Reconcile operator backlog vs launch runbook | | | | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Finding** | M5 — backlog still `⏳` for drift-codify / prod deploy / worker while runbook says more is already live | | **Owner** | OWNER:OPS (+ docs edit) | | **Address** | Diff each backlog row against `launch-operator-runbook.md`, July-8 apply notes, empty `supabase/drift-allowlist.json`, and linked migration list. Flip rows
expect(doc).toContain("src/lib/env.ts");
});

it("references the in-flight draft PRs by number", () => {
expect(doc).toContain("#708");

Check failure on line 42 in tests/docs-status-updates.test.ts

View workflow job for this annotation

GitHub Actions / Unit coverage

[node] tests/docs-status-updates.test.ts > docs/audit-remediation-plan-2026-07-14.md — 2026-07-17 reconciliation > references the in-flight draft PRs by number

AssertionError: expected '# Audit remediation plan — 2026-07-14…' to contain '#708' - Expected + Received - #708 + # Audit remediation plan — 2026-07-14 + + Plan derived from the multi-skill repository audit of `main` @ `570e6ba` (ledger rows in + [`branch-review-ledger.md`](branch-review-ledger.md)). This document is the sequenced address plan for + every finding: major blockers first, then P2 sub-issues, then P3 cleanup. + + **Findings handover (inventory + status):** [`audit-handover-2026-07-14.md`](audit-handover-2026-07-14.md). + + **Rules for executing this plan** + + - Prefer the smallest safe change per finding; do not bundle unrelated domains in one PR. + - Code fixes use `npm run verify:cheap` first, then the smallest domain check, then + `npm run verify:pr-local` before handoff. + - Provider/live actions are **operator-gated** (`⏸`). Do not run them without explicit confirmation. + - Reconcile [`operator-backlog.md`](operator-backlog.md) against + [`launch-operator-runbook.md`](launch-operator-runbook.md) before repeating any historical apply. + + **Legend** + + | Tag | Meaning | + | --------------- | ----------------------------------------------------- | + | **OWNER:CODE** | Implementable in-repo | + | **OWNER:OPS** | Railway / Supabase / GitHub / OpenAI dashboard or CLI | + | **OWNER:LEGAL** | Privacy officer / counsel | + | **⏸** | Provider or legal confirmation required | + | **Prove** | Smallest acceptance check | + + --- + + ## 0. Recommended delivery waves + + Work top-down. Later waves assume earlier majors are either done or consciously deferred. + + ```text + Wave A Confirm live/ops truth (doc sync) OWNER:OPS ⏸ + Wave B Launch / privacy blockers OWNER:LEGAL+OPS ⏸ + Wave C Code P1 availability (catalog rate limits) OWNER:CODE + Wave D Security & tenancy P2 OWNER:CODE (+OPS for live A/B) + Wave E Ingestion / recovery P2 OWNER:CODE + Wave F CI / testing / config P2 OWNER:CODE + Wave G Frontend a11y P2 OWNER:CODE + Wave H API contract hygiene P2 OWNER:CODE + Wave I P3 backlog + structure debt OWNER:CODE/OPS + Wave J Release confidence close-out OWNER:OPS ⏸ + ``` + + Suggested PR granularity (one theme per PR): + + 1. Catalog rate-limit + public DTO redaction + 2. Ingestion recovery + commit fallback + 3. CI scope + critical safety assert + flake hygiene + 4. A11y (describedby / icons / Tab / live region) + 5. JSON error taxonomy + admin rate limits + 6. Env example / bundle budget / summarize public scope + 7. Operator backlog status reconciliation (docs-only) + + --- + + ## Wave A — Confirm live truth before acting + + ### A1. Reconcile operator backlog vs launch runbook + + | | | + | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | + | **Finding** | M5 — backlog still `⏳` for drift-codify / prod deploy / worker while runbook says more is already live | + | **Owner** | OWNER:OPS (+ docs edit) | + | **Address** | Diff each backlog row against `launch-operator-runbook.md`, July-8 apply notes, empty `supabase/drift-allowlist.json`, and linked m
expect(doc).toContain("#710");
});

it("links to a findings-handover doc that actually exists on disk", () => {
expect(doc).toContain("audit-handover-2026-07-14.md");
expect(existsSync(path.join(docsDir, "audit-handover-2026-07-14.md"))).toBe(true);
});

it("still lists the OWNER:CODE cluster (D2, D3, E3, F1, F3, F6, H1-H5) as open", () => {
expect(doc).toContain("OWNER:CODE:");

Check failure on line 52 in tests/docs-status-updates.test.ts

View workflow job for this annotation

GitHub Actions / Unit coverage

[node] tests/docs-status-updates.test.ts > docs/audit-remediation-plan-2026-07-14.md — 2026-07-17 reconciliation > still lists the OWNER:CODE cluster (D2, D3, E3, F1, F3, F6, H1-H5) as open

AssertionError: expected '# Audit remediation plan — 2026-07-14…' to contain 'OWNER:CODE:' - Expected + Received - OWNER:CODE: + # Audit remediation plan — 2026-07-14 + + Plan derived from the multi-skill repository audit of `main` @ `570e6ba` (ledger rows in + [`branch-review-ledger.md`](branch-review-ledger.md)). This document is the sequenced address plan for + every finding: major blockers first, then P2 sub-issues, then P3 cleanup. + + **Findings handover (inventory + status):** [`audit-handover-2026-07-14.md`](audit-handover-2026-07-14.md). + + **Rules for executing this plan** + + - Prefer the smallest safe change per finding; do not bundle unrelated domains in one PR. + - Code fixes use `npm run verify:cheap` first, then the smallest domain check, then + `npm run verify:pr-local` before handoff. + - Provider/live actions are **operator-gated** (`⏸`). Do not run them without explicit confirmation. + - Reconcile [`operator-backlog.md`](operator-backlog.md) against + [`launch-operator-runbook.md`](launch-operator-runbook.md) before repeating any historical apply. + + **Legend** + + | Tag | Meaning | + | --------------- | ----------------------------------------------------- | + | **OWNER:CODE** | Implementable in-repo | + | **OWNER:OPS** | Railway / Supabase / GitHub / OpenAI dashboard or CLI | + | **OWNER:LEGAL** | Privacy officer / counsel | + | **⏸** | Provider or legal confirmation required | + | **Prove** | Smallest acceptance check | + + --- + + ## 0. Recommended delivery waves + + Work top-down. Later waves assume earlier majors are either done or consciously deferred. + + ```text + Wave A Confirm live/ops truth (doc sync) OWNER:OPS ⏸ + Wave B Launch / privacy blockers OWNER:LEGAL+OPS ⏸ + Wave C Code P1 availability (catalog rate limits) OWNER:CODE + Wave D Security & tenancy P2 OWNER:CODE (+OPS for live A/B) + Wave E Ingestion / recovery P2 OWNER:CODE + Wave F CI / testing / config P2 OWNER:CODE + Wave G Frontend a11y P2 OWNER:CODE + Wave H API contract hygiene P2 OWNER:CODE + Wave I P3 backlog + structure debt OWNER:CODE/OPS + Wave J Release confidence close-out OWNER:OPS ⏸ + ``` + + Suggested PR granularity (one theme per PR): + + 1. Catalog rate-limit + public DTO redaction + 2. Ingestion recovery + commit fallback + 3. CI scope + critical safety assert + flake hygiene + 4. A11y (describedby / icons / Tab / live region) + 5. JSON error taxonomy + admin rate limits + 6. Env example / bundle budget / summarize public scope + 7. Operator backlog status reconciliation (docs-only) + + --- + + ## Wave A — Confirm live truth before acting + + ### A1. Reconcile operator backlog vs launch runbook + + | | | + | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | + | **Finding** | M5 — backlog still `⏳` for drift-codify / prod deploy / worker while runbook says more is already live | + | **Owner** | OWNER:OPS (+ docs edit) | + | **Address** | Diff each backlog row against `launch-operator-runbook.md`, July-8 apply notes, empty `supabase/drift-allowlist.json`
expect(doc).toContain("D2 (tenancy CI guard");
expect(doc).toContain("E3 (wire `decideReindexGate`");
expect(doc).toContain("API-contract hygiene");
});

it("marks wave F2 as superseded rather than done or open", () => {
expect(doc).toContain("Superseded:");

Check failure on line 59 in tests/docs-status-updates.test.ts

View workflow job for this annotation

GitHub Actions / Unit coverage

[node] tests/docs-status-updates.test.ts > docs/audit-remediation-plan-2026-07-14.md — 2026-07-17 reconciliation > marks wave F2 as superseded rather than done or open

AssertionError: expected '# Audit remediation plan — 2026-07-14…' to contain 'Superseded:' - Expected + Received - Superseded: + # Audit remediation plan — 2026-07-14 + + Plan derived from the multi-skill repository audit of `main` @ `570e6ba` (ledger rows in + [`branch-review-ledger.md`](branch-review-ledger.md)). This document is the sequenced address plan for + every finding: major blockers first, then P2 sub-issues, then P3 cleanup. + + **Findings handover (inventory + status):** [`audit-handover-2026-07-14.md`](audit-handover-2026-07-14.md). + + **Rules for executing this plan** + + - Prefer the smallest safe change per finding; do not bundle unrelated domains in one PR. + - Code fixes use `npm run verify:cheap` first, then the smallest domain check, then + `npm run verify:pr-local` before handoff. + - Provider/live actions are **operator-gated** (`⏸`). Do not run them without explicit confirmation. + - Reconcile [`operator-backlog.md`](operator-backlog.md) against + [`launch-operator-runbook.md`](launch-operator-runbook.md) before repeating any historical apply. + + **Legend** + + | Tag | Meaning | + | --------------- | ----------------------------------------------------- | + | **OWNER:CODE** | Implementable in-repo | + | **OWNER:OPS** | Railway / Supabase / GitHub / OpenAI dashboard or CLI | + | **OWNER:LEGAL** | Privacy officer / counsel | + | **⏸** | Provider or legal confirmation required | + | **Prove** | Smallest acceptance check | + + --- + + ## 0. Recommended delivery waves + + Work top-down. Later waves assume earlier majors are either done or consciously deferred. + + ```text + Wave A Confirm live/ops truth (doc sync) OWNER:OPS ⏸ + Wave B Launch / privacy blockers OWNER:LEGAL+OPS ⏸ + Wave C Code P1 availability (catalog rate limits) OWNER:CODE + Wave D Security & tenancy P2 OWNER:CODE (+OPS for live A/B) + Wave E Ingestion / recovery P2 OWNER:CODE + Wave F CI / testing / config P2 OWNER:CODE + Wave G Frontend a11y P2 OWNER:CODE + Wave H API contract hygiene P2 OWNER:CODE + Wave I P3 backlog + structure debt OWNER:CODE/OPS + Wave J Release confidence close-out OWNER:OPS ⏸ + ``` + + Suggested PR granularity (one theme per PR): + + 1. Catalog rate-limit + public DTO redaction + 2. Ingestion recovery + commit fallback + 3. CI scope + critical safety assert + flake hygiene + 4. A11y (describedby / icons / Tab / live region) + 5. JSON error taxonomy + admin rate limits + 6. Env example / bundle budget / summarize public scope + 7. Operator backlog status reconciliation (docs-only) + + --- + + ## Wave A — Confirm live truth before acting + + ### A1. Reconcile operator backlog vs launch runbook + + | | | + | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | + | **Finding** | M5 — backlog still `⏳` for drift-codify / prod deploy / worker while runbook says more is already live | + | **Owner** | OWNER:OPS (+ docs edit) | + | **Address** | Diff each backlog row against `launch-operator-runbook.md`, July-8 apply notes, empty `supabase/drift-allowlist.json`
expect(doc).toContain("F2 (CI RAG-eval scope)");
});
});

describe("docs/ingestion-concurrency-fix-workorder.md — deep-memory scoping closed", () => {
const doc = readDoc("ingestion-concurrency-fix-workorder.md");

it("adds a 2026-07-17 status refresh declaring no open repository items", () => {
expect(doc).toContain("Status refresh 2026-07-17");

Check failure on line 68 in tests/docs-status-updates.test.ts

View workflow job for this annotation

GitHub Actions / Unit coverage

[node] tests/docs-status-updates.test.ts > docs/ingestion-concurrency-fix-workorder.md — deep-memory scoping closed > adds a 2026-07-17 status refresh declaring no open repository items

AssertionError: expected '# Ingestion-concurrency phase-3 — fix…' to contain 'Status refresh 2026-07-17' - Expected + Received - Status refresh 2026-07-17 + # Ingestion-concurrency phase-3 — fix work-order + + **Status refresh 2026-07-15:** the July-8 migration batch is applied and verified live. The only + remaining repository design item in this document is deep-memory section ownership/delete scoping + (see the final section); it is intentionally blocked on an explicit ownership model and a + retrieval/eval-gated implementation. Worker redeploy and other live operations are tracked in + [`operator-backlog.md`](operator-backlog.md). Historical author-time status below is retained as + provenance and must not be read as current live state. + + Sequenced, operator-applied plan for the state-machine violations that could + **not** be safely landed from a chat session. Companion to + `docs/ingestion-state-machine.md` (§6 findings, §8 backlog) and + `docs/scale-readiness-review.md`. + + Author date: 2026-07-08. All facts below were read from the **live** project + `Clinical KB Database` (`sjrfecxgysukkwxsowpy`) via read-only `execute_sql`; + nothing here was applied to live at author time. **Historical status (2026-07-09):** July 8 migrations were merged to `main` but pending live apply — see [`docs/operator-apply-july8-batch.md`](operator-apply-july8-batch.md). Function bodies are quoted from + `pg_get_functiondef` so migrations are derived from live truth, not `schema.sql` + (which is known-drifted — see R24e and `docs/database-drift-detection.md`). + + ## Already landed on `main` (do not redo) + + - **R11, R15/R16, R22, R24d-gate** — merged (PR #346). + - **R11 janitor-side guard** (`scripts/cleanup-storage.ts` + + `src/lib/storage-cleanup-safety.ts`) and **R1 lease heartbeat** + (`shouldPersistJobProgress` in `src/lib/ingestion.ts`, worker refresh of + `locked_at`) — merged (PR #369). + - **R1/R2/R7/R9/R23 RPC hardening** — migration `20260708130000` merged (PR #380) and applied live. + - **R24e** — phantom `ingestion_job_stages.job_id` FK dropped from `schema.sql` (PR #380 batch); live apply was a no-op as expected. + - **R17** — partial unique index + reindex-route 409 handling merged (PR #405); migration `20260708170000` applied live. + - **R5** — metadata deep-merge RPC + worker merged (PR #408); migration applied live; worker redeploy remains an operator action. + + ## Still open (not merged or needs design) + + - **deep-memory delete-scoping** — design required (see bottom of this doc). + + ## Global rules for this release + + 1. **Never raw-SQL against live.** Every DB change is a committed migration + (`supabase/migrations/<ts>_*.sql`) + a matching `supabase/schema.sql` edit + + `npm run drift:manifest` (Docker) in the same PR, per + `docs/database-drift-detection.md`. Operator applies with `supabase db push` + after review. + 2. **Expand/contract for RPC signature changes.** New params are added with + defaults so existing callers keep resolving; the fence/behavior only engages + once the new param is passed. This lets the **DB migration ship first** and + the worker/edge deploy follow, with no broken window. + 3. **Deploy order per item is explicit below.** Items marked + _coordinated_ must not have their DB half applied without the paired + app/worker/edge deploy reaching a state where the old callers are still + safe (guaranteed by rule 2). + 4. **Eval gate.** Any item marked _retrieval-affecting_ must show + `npm run eval:retrieval:quality` unchanged (currently **36/36**, + content_mrr@10 = 0.924, live 2026-07-08) before defaults change. + 5. **Drift-backlog coordination.** Items touching `ingestion_jobs` indexes + (R17) or the `ingestion_job_stages` FK (R24e) overlap the open reconciliation + backlog in `docs/database-drift-detection.md` (§ "Reconciliation backlog" + items #7 and #8). Land them **through that backlog**, not as a competing PR. + + --- + + ## R2 — lease fences on complete / fail (root fix, expand/contract) + +
expect(doc).toContain("no open repository items");
});

it("replaces the 'Still open' entry with a resolved marker instead of the design-required line", () => {
const idx = doc.indexOf("## Still open (not merged or needs design)");
expect(idx).toBeGreaterThan(-1);
const section = doc.slice(idx, idx + 400);
expect(section).toContain("_None._");

Check failure on line 76 in tests/docs-status-updates.test.ts

View workflow job for this annotation

GitHub Actions / Unit coverage

[node] tests/docs-status-updates.test.ts > docs/ingestion-concurrency-fix-workorder.md — deep-memory scoping closed > replaces the 'Still open' entry with a resolved marker instead of the design-required line

AssertionError: expected '## Still open (not merged or needs de…' to contain '_None._' - Expected + Received - _None._ + ## Still open (not merged or needs design) + + - **deep-memory delete-scoping** — design required (see bottom of this doc). + + ## Global rules for this release + + 1. **Never raw-SQL against live.** Every DB change is a committed migration + (`supabase/migrations/<ts>_*.sql`) + a matching `supabase/schema.sql` edit + + `npm run drift:manifest` (Docker) in the same PR, per + `docs/database-drift-detecti ❯ tests/docs-status-updates.test.ts:76:21
expect(section).not.toContain("design required");
});

it("strikes through the remaining-repo-work deep-memory scoping item as done", () => {
expect(doc).toContain("~~**deep-memory scoping**~~");

Check failure on line 81 in tests/docs-status-updates.test.ts

View workflow job for this annotation

GitHub Actions / Unit coverage

[node] tests/docs-status-updates.test.ts > docs/ingestion-concurrency-fix-workorder.md — deep-memory scoping closed > strikes through the remaining-repo-work deep-memory scoping item as done

AssertionError: expected '# Ingestion-concurrency phase-3 — fix…' to contain '~~**deep-memory scoping**~~' - Expected + Received - ~~**deep-memory scoping**~~ + # Ingestion-concurrency phase-3 — fix work-order + + **Status refresh 2026-07-15:** the July-8 migration batch is applied and verified live. The only + remaining repository design item in this document is deep-memory section ownership/delete scoping + (see the final section); it is intentionally blocked on an explicit ownership model and a + retrieval/eval-gated implementation. Worker redeploy and other live operations are tracked in + [`operator-backlog.md`](operator-backlog.md). Historical author-time status below is retained as + provenance and must not be read as current live state. + + Sequenced, operator-applied plan for the state-machine violations that could + **not** be safely landed from a chat session. Companion to + `docs/ingestion-state-machine.md` (§6 findings, §8 backlog) and + `docs/scale-readiness-review.md`. + + Author date: 2026-07-08. All facts below were read from the **live** project + `Clinical KB Database` (`sjrfecxgysukkwxsowpy`) via read-only `execute_sql`; + nothing here was applied to live at author time. **Historical status (2026-07-09):** July 8 migrations were merged to `main` but pending live apply — see [`docs/operator-apply-july8-batch.md`](operator-apply-july8-batch.md). Function bodies are quoted from + `pg_get_functiondef` so migrations are derived from live truth, not `schema.sql` + (which is known-drifted — see R24e and `docs/database-drift-detection.md`). + + ## Already landed on `main` (do not redo) + + - **R11, R15/R16, R22, R24d-gate** — merged (PR #346). + - **R11 janitor-side guard** (`scripts/cleanup-storage.ts` + + `src/lib/storage-cleanup-safety.ts`) and **R1 lease heartbeat** + (`shouldPersistJobProgress` in `src/lib/ingestion.ts`, worker refresh of + `locked_at`) — merged (PR #369). + - **R1/R2/R7/R9/R23 RPC hardening** — migration `20260708130000` merged (PR #380) and applied live. + - **R24e** — phantom `ingestion_job_stages.job_id` FK dropped from `schema.sql` (PR #380 batch); live apply was a no-op as expected. + - **R17** — partial unique index + reindex-route 409 handling merged (PR #405); migration `20260708170000` applied live. + - **R5** — metadata deep-merge RPC + worker merged (PR #408); migration applied live; worker redeploy remains an operator action. + + ## Still open (not merged or needs design) + + - **deep-memory delete-scoping** — design required (see bottom of this doc). + + ## Global rules for this release + + 1. **Never raw-SQL against live.** Every DB change is a committed migration + (`supabase/migrations/<ts>_*.sql`) + a matching `supabase/schema.sql` edit + + `npm run drift:manifest` (Docker) in the same PR, per + `docs/database-drift-detection.md`. Operator applies with `supabase db push` + after review. + 2. **Expand/contract for RPC signature changes.** New params are added with + defaults so existing callers keep resolving; the fence/behavior only engages + once the new param is passed. This lets the **DB migration ship first** and + the worker/edge deploy follow, with no broken window. + 3. **Deploy order per item is explicit below.** Items marked + _coordinated_ must not have their DB half applied without the paired + app/worker/edge deploy reaching a state where the old callers are still + safe (guaranteed by rule 2). + 4. **Eval gate.** Any item marked _retrieval-affecting_ must show + `npm run eval:retrieval:quality` unchanged (currently **36/36**, + content_mrr@10 = 0.924, live 2026-07-08) before defaults change. + 5. **Drift-backlog coordination.** Items touching `ingestion_jobs` indexes + (R17) or the `ingestion_job_stages` FK (R24e) overlap the open reconciliation + backlog in `docs/database-drift-detection.md` (§ "Reconciliation backlog" + items #7 and #8). Land them **through that backlog**, not as a competing PR. + + --- + + ## R2 — lease fences on complete / fail (root fix, expand/contract)
expect(doc).toContain("DONE (2026-07-17)");
});

it("references a producer-scoped migration that exists in supabase/migrations", () => {
const migrationName = "20260713030000_producer_scoped_deep_memory.sql";
expect(doc).toContain(migrationName);

Check failure on line 87 in tests/docs-status-updates.test.ts

View workflow job for this annotation

GitHub Actions / Unit coverage

[node] tests/docs-status-updates.test.ts > docs/ingestion-concurrency-fix-workorder.md — deep-memory scoping closed > references a producer-scoped migration that exists in supabase/migrations

AssertionError: expected '# Ingestion-concurrency phase-3 — fix…' to contain '20260713030000_producer_scoped_deep_m…' - Expected + Received - 20260713030000_producer_scoped_deep_memory.sql + # Ingestion-concurrency phase-3 — fix work-order + + **Status refresh 2026-07-15:** the July-8 migration batch is applied and verified live. The only + remaining repository design item in this document is deep-memory section ownership/delete scoping + (see the final section); it is intentionally blocked on an explicit ownership model and a + retrieval/eval-gated implementation. Worker redeploy and other live operations are tracked in + [`operator-backlog.md`](operator-backlog.md). Historical author-time status below is retained as + provenance and must not be read as current live state. + + Sequenced, operator-applied plan for the state-machine violations that could + **not** be safely landed from a chat session. Companion to + `docs/ingestion-state-machine.md` (§6 findings, §8 backlog) and + `docs/scale-readiness-review.md`. + + Author date: 2026-07-08. All facts below were read from the **live** project + `Clinical KB Database` (`sjrfecxgysukkwxsowpy`) via read-only `execute_sql`; + nothing here was applied to live at author time. **Historical status (2026-07-09):** July 8 migrations were merged to `main` but pending live apply — see [`docs/operator-apply-july8-batch.md`](operator-apply-july8-batch.md). Function bodies are quoted from + `pg_get_functiondef` so migrations are derived from live truth, not `schema.sql` + (which is known-drifted — see R24e and `docs/database-drift-detection.md`). + + ## Already landed on `main` (do not redo) + + - **R11, R15/R16, R22, R24d-gate** — merged (PR #346). + - **R11 janitor-side guard** (`scripts/cleanup-storage.ts` + + `src/lib/storage-cleanup-safety.ts`) and **R1 lease heartbeat** + (`shouldPersistJobProgress` in `src/lib/ingestion.ts`, worker refresh of + `locked_at`) — merged (PR #369). + - **R1/R2/R7/R9/R23 RPC hardening** — migration `20260708130000` merged (PR #380) and applied live. + - **R24e** — phantom `ingestion_job_stages.job_id` FK dropped from `schema.sql` (PR #380 batch); live apply was a no-op as expected. + - **R17** — partial unique index + reindex-route 409 handling merged (PR #405); migration `20260708170000` applied live. + - **R5** — metadata deep-merge RPC + worker merged (PR #408); migration applied live; worker redeploy remains an operator action. + + ## Still open (not merged or needs design) + + - **deep-memory delete-scoping** — design required (see bottom of this doc). + + ## Global rules for this release + + 1. **Never raw-SQL against live.** Every DB change is a committed migration + (`supabase/migrations/<ts>_*.sql`) + a matching `supabase/schema.sql` edit + + `npm run drift:manifest` (Docker) in the same PR, per + `docs/database-drift-detection.md`. Operator applies with `supabase db push` + after review. + 2. **Expand/contract for RPC signature changes.** New params are added with + defaults so existing callers keep resolving; the fence/behavior only engages + once the new param is passed. This lets the **DB migration ship first** and + the worker/edge deploy follow, with no broken window. + 3. **Deploy order per item is explicit below.** Items marked + _coordinated_ must not have their DB half applied without the paired + app/worker/edge deploy reaching a state where the old callers are still + safe (guaranteed by rule 2). + 4. **Eval gate.** Any item marked _retrieval-affecting_ must show + `npm run eval:retrieval:quality` unchanged (currently **36/36**, + content_mrr@10 = 0.924, live 2026-07-08) before defaults change. + 5. **Drift-backlog coordination.** Items touching `ingestion_jobs` indexes + (R17) or the `ingestion_job_stages` FK (R24e) overlap the open reconciliation + backlog in `docs/database-drift-detection.md` (§ "Reconciliation backlog" + items #7 and #8). Land them **through that backlog**, not as a competing PR. + + --- + + ## R2 — lease fences on complete / f
expect(existsSync(path.join(migrationsDir, migrationName))).toBe(true);
});

it("references the commit that reconciled the commit body", () => {
expect(doc).toContain("#569");

Check failure on line 92 in tests/docs-status-updates.test.ts

View workflow job for this annotation

GitHub Actions / Unit coverage

[node] tests/docs-status-updates.test.ts > docs/ingestion-concurrency-fix-workorder.md — deep-memory scoping closed > references the commit that reconciled the commit body

AssertionError: expected '# Ingestion-concurrency phase-3 — fix…' to contain '#569' - Expected + Received - #569 + # Ingestion-concurrency phase-3 — fix work-order + + **Status refresh 2026-07-15:** the July-8 migration batch is applied and verified live. The only + remaining repository design item in this document is deep-memory section ownership/delete scoping + (see the final section); it is intentionally blocked on an explicit ownership model and a + retrieval/eval-gated implementation. Worker redeploy and other live operations are tracked in + [`operator-backlog.md`](operator-backlog.md). Historical author-time status below is retained as + provenance and must not be read as current live state. + + Sequenced, operator-applied plan for the state-machine violations that could + **not** be safely landed from a chat session. Companion to + `docs/ingestion-state-machine.md` (§6 findings, §8 backlog) and + `docs/scale-readiness-review.md`. + + Author date: 2026-07-08. All facts below were read from the **live** project + `Clinical KB Database` (`sjrfecxgysukkwxsowpy`) via read-only `execute_sql`; + nothing here was applied to live at author time. **Historical status (2026-07-09):** July 8 migrations were merged to `main` but pending live apply — see [`docs/operator-apply-july8-batch.md`](operator-apply-july8-batch.md). Function bodies are quoted from + `pg_get_functiondef` so migrations are derived from live truth, not `schema.sql` + (which is known-drifted — see R24e and `docs/database-drift-detection.md`). + + ## Already landed on `main` (do not redo) + + - **R11, R15/R16, R22, R24d-gate** — merged (PR #346). + - **R11 janitor-side guard** (`scripts/cleanup-storage.ts` + + `src/lib/storage-cleanup-safety.ts`) and **R1 lease heartbeat** + (`shouldPersistJobProgress` in `src/lib/ingestion.ts`, worker refresh of + `locked_at`) — merged (PR #369). + - **R1/R2/R7/R9/R23 RPC hardening** — migration `20260708130000` merged (PR #380) and applied live. + - **R24e** — phantom `ingestion_job_stages.job_id` FK dropped from `schema.sql` (PR #380 batch); live apply was a no-op as expected. + - **R17** — partial unique index + reindex-route 409 handling merged (PR #405); migration `20260708170000` applied live. + - **R5** — metadata deep-merge RPC + worker merged (PR #408); migration applied live; worker redeploy remains an operator action. + + ## Still open (not merged or needs design) + + - **deep-memory delete-scoping** — design required (see bottom of this doc). + + ## Global rules for this release + + 1. **Never raw-SQL against live.** Every DB change is a committed migration + (`supabase/migrations/<ts>_*.sql`) + a matching `supabase/schema.sql` edit + + `npm run drift:manifest` (Docker) in the same PR, per + `docs/database-drift-detection.md`. Operator applies with `supabase db push` + after review. + 2. **Expand/contract for RPC signature changes.** New params are added with + defaults so existing callers keep resolving; the fence/behavior only engages + once the new param is passed. This lets the **DB migration ship first** and + the worker/edge deploy follow, with no broken window. + 3. **Deploy order per item is explicit below.** Items marked + _coordinated_ must not have their DB half applied without the paired + app/worker/edge deploy reaching a state where the old callers are still + safe (guaranteed by rule 2). + 4. **Eval gate.** Any item marked _retrieval-affecting_ must show + `npm run eval:retrieval:quality` unchanged (currently **36/36**, + content_mrr@10 = 0.924, live 2026-07-08) before defaults change. + 5. **Drift-backlog coordination.** Items touching `ingestion_jobs` indexes + (R17) or the `ingestion_job_stages` FK (R24e) overlap the open reconciliation + backlog in `docs/database-drift-detection.md` (§ "Reconciliation backlog" + items #7 and #8). Land them **through that backlog**, not as a competing PR. + + --- + + ## R2 — lease fences on complete / fail (root fix, expand/contract) + + **Finding (SILENT-CORRUPTION/OPS-CHURN):**
});

it("retains the original 2026-07-15 status refresh and historical author-date content as provenance", () => {
expect(doc).toContain("Status refresh 2026-07-15");
expect(doc).toContain("Author date: 2026-07-08");
});
});

describe("docs/operator-backlog.md — launch-gating table refresh", () => {
const doc = readDoc("operator-backlog.md");

it("flips the drift-codify migration row to done", () => {
const row = lineContaining(doc, "Apply drift-codify forward migration (step 1h)");
expect(row).toBeDefined();
expect(row).toContain("✅ done");
expect(row).not.toContain("⏳ pending");
});

it("adds a repo-ahead migrations verify row referencing the three pending migrations", () => {
const row = lineContaining(doc, "Apply repo-ahead migrations to live (post-2026-07-13)");
expect(row).toBeDefined();
expect(row).toContain("🔎 verify");
for (const ts of ["20260713201542", "20260714110000", "20260717120000"]) {
expect(row).toContain(ts);
}
});

it("links the new verify row to a runbook doc that exists on disk", () => {
const row = lineContaining(doc, "Apply repo-ahead migrations to live (post-2026-07-13)");
expect(row).toContain("[deploy-corrector-public-titles.md](deploy-corrector-public-titles.md)");
expect(existsSync(path.join(docsDir, "deploy-corrector-public-titles.md"))).toBe(true);
});

it("links the drift-codify row to its forward-codify work-order doc that exists on disk", () => {
const row = lineContaining(doc, "Apply drift-codify forward migration (step 1h)");
expect(row).toContain("[forward-codify-retrieval-rpcs-workorder.md](forward-codify-retrieval-rpcs-workorder.md)");
expect(existsSync(path.join(docsDir, "forward-codify-retrieval-rpcs-workorder.md"))).toBe(true);
});

it("every migration timestamp referenced in the verify row corresponds to a real migration file", () => {
for (const ts of ["20260713201542", "20260714110000", "20260717120000"]) {
expect(migrationExists(ts)).toBe(true);
}
});

it("keeps the launch-gating table well-formed (every row has the same column count as the header)", () => {
const lines = doc.split("\n");
const headerIndex = lines.findIndex((line) => line.startsWith("| Action"));
expect(headerIndex).toBeGreaterThan(-1);
const headerCols = lines[headerIndex].split("|").length;

let i = headerIndex + 2; // skip the header and the `---` separator row
let rowCount = 0;
while (lines[i]?.startsWith("|")) {
expect(lines[i].split("|").length).toBe(headerCols);
i += 1;
rowCount += 1;
}
expect(rowCount).toBeGreaterThanOrEqual(6);
});
});
68 changes: 68 additions & 0 deletions tests/env-example-weak-or-relaxation.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { readFileSync } from "node:fs";
import path from "node:path";
import { afterEach, describe, expect, it, vi } from "vitest";

// RAG_TEXT_WEAK_OR_RELAXATION is an opt-in P8b experiment that is known to
// regress the golden retrieval eval when left on (see the comment above the
// field in src/lib/env.ts). .env.example previously committed the stale
// `true` value, which disagreed with the schema's actual `false` default;
// this PR corrects the committed default back to `false`. These tests guard
// against the two drifting apart again: the literal value committed in
// .env.example, and its parity with the env.ts zod schema default (which is
// the actual runtime behaviour whenever the var is left unset).

const envExamplePath = path.join(process.cwd(), ".env.example");

function readEnvExampleValue(key: string): string | undefined {
const content = readFileSync(envExamplePath, "utf8");
const match = content.match(new RegExp(`^${key}=(.*)$`, "m"));
return match?.[1];
}

async function loadEnvWith(value: string | undefined) {
vi.resetModules();
vi.stubEnv("RAG_TEXT_WEAK_OR_RELAXATION", value);
return import("../src/lib/env");
}

afterEach(() => {
vi.unstubAllEnvs();
vi.resetModules();
});

describe(".env.example RAG_TEXT_WEAK_OR_RELAXATION", () => {
it("commits the safe default (false), not the regressive true", () => {
expect(readEnvExampleValue("RAG_TEXT_WEAK_OR_RELAXATION")).toBe("false");
});

it("matches src/lib/env.ts's own schema default when the var is unset", async () => {
const { env } = await loadEnvWith(undefined);
expect(env.RAG_TEXT_WEAK_OR_RELAXATION).toBe(false);
expect(String(env.RAG_TEXT_WEAK_OR_RELAXATION)).toBe(readEnvExampleValue("RAG_TEXT_WEAK_OR_RELAXATION"));
});

it("resolves to the same boolean whether taken from env.ts's default or the literal .env.example value", async () => {
const exampleValue = readEnvExampleValue("RAG_TEXT_WEAK_OR_RELAXATION");
expect(exampleValue).toBeDefined();

const { env: defaulted } = await loadEnvWith(undefined);
const { env: fromExample } = await loadEnvWith(exampleValue);

expect(fromExample.RAG_TEXT_WEAK_OR_RELAXATION).toBe(defaulted.RAG_TEXT_WEAK_OR_RELAXATION);
});

it("still transforms an explicit true to true (regression guard: flag is not hard-disabled)", async () => {
const { env } = await loadEnvWith("true");
expect(env.RAG_TEXT_WEAK_OR_RELAXATION).toBe(true);
});

it("documents the golden-eval regression and kill-switch semantics in the surrounding comment", () => {
const content = readFileSync(envExamplePath, "utf8");
const idx = content.indexOf("RAG_TEXT_WEAK_OR_RELAXATION=false");
expect(idx).toBeGreaterThan(-1);
const commentBlock = content.slice(Math.max(0, idx - 500), idx);
expect(commentBlock).toMatch(/OFF by default/i);
expect(commentBlock).toMatch(/golden retrieval eval/i);
expect(commentBlock).toMatch(/36\/36/);
});
});
Loading