From f6f66a92517eed0762d89e000729ffc8b04b5ed3 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 14 Aug 2026 15:13:10 +0000 Subject: [PATCH 01/11] test(live-drift): prove the drift-failure routing script The routing script merged in #1938/#1939 carries issues: write and had no test, so its create/update/close behaviour would first have been exercised against the real repository. Extracts the embedded github-script body and executes it against stubbed issue APIs, using the same extraction pattern as tests/codex-autofix-workflow.test.ts. Asserts: - a failure with no open issue creates exactly one labelled issue carrying the run URL and the captured findings - a repeat failure updates that same issue and comments, never opening a second - a run that died before the comparison is not presented as a clean schema - a green run comments the resolution and closes with state_reason completed - a green run with no open issue writes nothing at all - an unknown job result is treated as failure, not as a reason to close Also pins the trigger/privilege contract: schedule + dispatch + the migrations-push trigger, never pull_request, cancel-in-progress false, the secret preflight, the pinned github-script SHA, and issues: write appearing exactly once and only inside drift-routing. Verified by mutation: inverting the update-in-place branch, the close-on-green state, and escalating issues: write to workflow level each turn this test red. Registered in test:ci-workflows so a future workflow-scope change runs it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01BKNFogaYfCQBvFVqFQnfRt --- package.json | 2 +- tests/live-drift-workflow.test.ts | 259 ++++++++++++++++++++++++++++++ 2 files changed, 260 insertions(+), 1 deletion(-) create mode 100644 tests/live-drift-workflow.test.ts diff --git a/package.json b/package.json index dae68aafb9..aa5bc15901 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "test:coverage": "node scripts/run-vitest.mjs run --coverage", "test:coverage:node": "node scripts/run-vitest.mjs run --project=node --coverage", "test:coverage:ui": "node scripts/run-vitest.mjs run --project=jsdom --coverage", - "test:ci-workflows": "node scripts/run-vitest.mjs run tests/ci-cache-safety.test.ts tests/authenticated-live-workflow.test.ts tests/codex-autofix-workflow.test.ts tests/codex-run-pr-operator-workflow.test.ts tests/eval-canary-workflow.test.ts tests/container-ci-contract.test.ts tests/test-runner-safety.test.ts tests/installed-lock-parity.test.ts tests/railway-config.test.ts tests/ingestion-autopilot.test.ts tests/ingestion-autopilot-workflow.test.ts tests/check-lighthouse-budget.test.ts tests/live-web-vitals-inputs.test.ts tests/offline-release-profile.test.ts", + "test:ci-workflows": "node scripts/run-vitest.mjs run tests/ci-cache-safety.test.ts tests/authenticated-live-workflow.test.ts tests/codex-autofix-workflow.test.ts tests/codex-run-pr-operator-workflow.test.ts tests/eval-canary-workflow.test.ts tests/live-drift-workflow.test.ts tests/container-ci-contract.test.ts tests/test-runner-safety.test.ts tests/installed-lock-parity.test.ts tests/railway-config.test.ts tests/ingestion-autopilot.test.ts tests/ingestion-autopilot-workflow.test.ts tests/check-lighthouse-budget.test.ts tests/live-web-vitals-inputs.test.ts tests/offline-release-profile.test.ts", "test:e2e": "node scripts/run-playwright.mjs", "test:e2e:all": "node scripts/run-playwright.mjs", "test:e2e:accessibility": "node scripts/run-playwright.mjs tests/ui-accessibility.spec.ts --project=chromium", diff --git a/tests/live-drift-workflow.test.ts b/tests/live-drift-workflow.test.ts new file mode 100644 index 0000000000..4e614608bf --- /dev/null +++ b/tests/live-drift-workflow.test.ts @@ -0,0 +1,259 @@ +import { readFileSync } from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +import { describe, expect, it } from "vitest"; + +const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const workflowPath = path.join(repoRoot, ".github", "workflows", "live-drift.yml"); +const workflow = readFileSync(workflowPath, "utf8").replace(/\r\n/g, "\n"); + +type Issue = { number: number; title: string }; + +type ScriptFunction = ( + github: Record, + context: Record, + core: { + info: (message: string) => void; + warning: (message: string) => void; + }, +) => Promise; + +const AsyncFunction = Object.getPrototypeOf(async () => undefined).constructor as new ( + ...args: string[] +) => ScriptFunction; + +// Same extraction shape as tests/codex-autofix-workflow.test.ts: the block is +// `script: |` at ten spaces, so its body is everything indented twelve or more. +function extractWorkflowScripts(source: string) { + const scriptMarker = " script: |\n"; + const scripts: string[] = []; + let searchFrom = 0; + + while (true) { + const scriptStart = source.indexOf(scriptMarker, searchFrom); + if (scriptStart === -1) break; + + const scriptLines = source.slice(scriptStart + scriptMarker.length).split("\n"); + const extractedLines: string[] = []; + + for (const line of scriptLines) { + if (line.length === 0) { + extractedLines.push(""); + continue; + } + if (!line.startsWith(" ")) break; + extractedLines.push(line.slice(12)); + } + + scripts.push(extractedLines.join("\n")); + searchFrom = scriptStart + scriptMarker.length; + } + + return scripts; +} + +const [routingScriptSource, ...extraScripts] = extractWorkflowScripts(workflow); +if (!routingScriptSource) { + throw new Error("Expected a github-script block for drift routing in .github/workflows/live-drift.yml."); +} +if (extraScripts.length > 0) { + throw new Error("Expected exactly one github-script block in live-drift.yml; update this test if that changes."); +} + +const routingScript = new AsyncFunction("github", "context", "core", routingScriptSource); + +type Calls = { + closed: Array<{ issue_number: number; state?: string; state_reason?: string }>; + comments: Array<{ issue_number: number; body: string }>; + created: Array<{ title: string; labels: string[]; body: string }>; + listed: Array<{ labels: string; state: string }>; + updatedBodies: Array<{ issue_number: number; body: string }>; + warnings: string[]; +}; + +async function runRoutingScript(options: { findings?: string; openIssues?: Issue[]; result: string }) { + const calls: Calls = { closed: [], comments: [], created: [], listed: [], updatedBodies: [], warnings: [] }; + + const github = { + rest: { + issues: { + create: async (request: { body: string; labels: string[]; title: string }) => { + calls.created.push({ body: request.body, labels: request.labels, title: request.title }); + return { data: { number: 4242 } }; + }, + createComment: async (request: { body: string; issue_number: number }) => { + calls.comments.push({ body: request.body, issue_number: request.issue_number }); + }, + listForRepo: async (request: { labels: string; state: string }) => { + calls.listed.push({ labels: request.labels, state: request.state }); + return { data: options.openIssues ?? [] }; + }, + update: async (request: { body?: string; issue_number: number; state?: string; state_reason?: string }) => { + if (request.state) { + calls.closed.push({ + issue_number: request.issue_number, + state: request.state, + state_reason: request.state_reason, + }); + } + if (typeof request.body === "string") { + calls.updatedBodies.push({ body: request.body, issue_number: request.issue_number }); + } + }, + }, + }, + }; + + const context = { + eventName: "schedule", + repo: { owner: "BigSimmo", repo: "Database" }, + runId: 99, + serverUrl: "https://github.com", + }; + + const core = { + info: () => undefined, + warning: (message: string) => { + calls.warnings.push(message); + }, + }; + + const previous = { findings: process.env.DRIFT_FINDINGS, result: process.env.DRIFT_RESULT }; + process.env.DRIFT_RESULT = options.result; + process.env.DRIFT_FINDINGS = options.findings ?? ""; + try { + await routingScript(github, context, core); + } finally { + if (previous.result === undefined) delete process.env.DRIFT_RESULT; + else process.env.DRIFT_RESULT = previous.result; + if (previous.findings === undefined) delete process.env.DRIFT_FINDINGS; + else process.env.DRIFT_FINDINGS = previous.findings; + } + + return calls; +} + +const pinnedIssue: Issue = { number: 1234, title: "Live drift check failing" }; +const sampleFindings = "UNEXPECTED DRIFT (2):\n ! [indexes] missing_live documents_title_trgm_idx"; + +describe("live-drift workflow triggers and privileges", () => { + it("keeps the weekly schedule and manual dispatch", () => { + expect(workflow).toContain("workflow_dispatch:"); + expect(workflow).toContain('- cron: "30 18 * * 0"'); + }); + + it("also runs once a schema change reaches main, and never on pull requests", () => { + expect(workflow).toContain("branches: [main]"); + expect(workflow).toContain('- "supabase/migrations/**"'); + expect(workflow).toContain('- "supabase/schema.sql"'); + expect(workflow).not.toMatch(/^on:[\s\S]*?^\s{2}pull_request/m); + }); + + it("never cancels an in-flight drift run", () => { + expect(workflow).toContain("group: live-drift-check"); + expect(workflow).toContain("cancel-in-progress: false"); + }); + + it("keeps the secret preflight so a missing key fails loudly rather than silently passing", () => { + expect(workflow).toContain("Preflight required secrets"); + expect(workflow).toContain("Live drift check cannot run - missing repo secrets:"); + }); + + it("grants issues: write only to the routing job", () => { + // Workflow-level permissions stay read-only, so no job inherits issue writes. + expect(workflow).toMatch(/^permissions:\n {2}contents: read\n/m); + + const routingStart = workflow.indexOf("\n drift-routing:"); + expect(routingStart).toBeGreaterThan(-1); + + // Match the YAML key only. Matching the bare string would also hit the + // explanatory comment above the job and silently pass on a real regression. + const grantPattern = /^ +issues: write$/gm; + const grants = [...workflow.matchAll(grantPattern)]; + expect(grants).toHaveLength(1); + expect(grants[0].index).toBeGreaterThan(routingStart); + }); + + it("keeps the service-role key out of the job that can write issues", () => { + const routingStart = workflow.indexOf(" drift-routing:"); + expect(workflow.slice(routingStart)).not.toContain("SUPABASE_SERVICE_ROLE_KEY"); + }); + + it("pins github-script to the reviewed immutable commit", () => { + expect(workflow).toContain("uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0"); + }); + + it("captures findings even when the drift step failed", () => { + expect(workflow).toContain("set -o pipefail"); + expect(workflow).toMatch(/id: findings\n\s+if: always\(\)/); + }); + + it("still routes when the drift job fails", () => { + expect(workflow).toContain("if: ${{ !cancelled() }}"); + }); +}); + +describe("live-drift failure routing", () => { + it("opens one labelled issue when the check fails and none is open", async () => { + const calls = await runRoutingScript({ findings: sampleFindings, result: "failure" }); + + expect(calls.listed).toEqual([{ labels: "live-drift-failure", state: "open" }]); + expect(calls.created).toHaveLength(1); + expect(calls.created[0].title).toBe("Live drift check failing"); + expect(calls.created[0].labels).toEqual(["live-drift-failure"]); + expect(calls.created[0].body).toContain("https://github.com/BigSimmo/Database/actions/runs/99"); + expect(calls.created[0].body).toContain("documents_title_trgm_idx"); + expect(calls.closed).toHaveLength(0); + }); + + it("updates the same issue on a repeat failure instead of stacking a second one", async () => { + const calls = await runRoutingScript({ + findings: sampleFindings, + openIssues: [pinnedIssue], + result: "failure", + }); + + expect(calls.created).toHaveLength(0); + expect(calls.updatedBodies).toEqual([expect.objectContaining({ issue_number: 1234 })]); + expect(calls.comments).toHaveLength(1); + expect(calls.comments[0].issue_number).toBe(1234); + expect(calls.comments[0].body).toContain("Still failing"); + expect(calls.closed).toHaveLength(0); + expect(calls.warnings.join(" ")).toContain("1234"); + }); + + it("does not present a run that died before the comparison as a clean schema", async () => { + const calls = await runRoutingScript({ findings: "", result: "failure" }); + + expect(calls.created).toHaveLength(1); + expect(calls.created[0].body).toContain("not** evidence of a clean schema"); + expect(calls.created[0].body).not.toContain("UNEXPECTED DRIFT"); + }); + + it("comments the resolution and closes the issue on the next green run", async () => { + const calls = await runRoutingScript({ openIssues: [pinnedIssue], result: "success" }); + + expect(calls.comments).toHaveLength(1); + expect(calls.comments[0].body).toContain("Resolved"); + expect(calls.comments[0].body).toContain("https://github.com/BigSimmo/Database/actions/runs/99"); + expect(calls.closed).toEqual([{ issue_number: 1234, state: "closed", state_reason: "completed" }]); + expect(calls.created).toHaveLength(0); + }); + + it("writes nothing when the check is green and no issue is open", async () => { + const calls = await runRoutingScript({ result: "success" }); + + expect(calls.created).toHaveLength(0); + expect(calls.comments).toHaveLength(0); + expect(calls.closed).toHaveLength(0); + expect(calls.updatedBodies).toHaveLength(0); + }); + + it("treats an unknown job result as a failure rather than closing the issue", async () => { + const calls = await runRoutingScript({ openIssues: [pinnedIssue], result: "" }); + + expect(calls.closed).toHaveLength(0); + expect(calls.updatedBodies).toHaveLength(1); + }); +}); From 7ce2872bc0e3064c1ac1f618b5dcde5eccf84224 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 14 Aug 2026 15:13:16 +0000 Subject: [PATCH 02/11] docs(medications): refresh the generated lexicon review to unstick its staleness check check:medication-lexicon-report fails on clean main, so any PR whose scope reaches that gate is red before it starts. This is what #333 asked for as its next step, and it refutes #331's hypothesis of a comparison bug. The staleness was real but wrapping-only: normalising whitespace on the committed and regenerated files leaves them byte-identical across all 28 catalogue terms, so no content changed and no clinical review is implicated. Every branch saw the failure because main itself carried the stale copy, which is why "zero diff on my branch" was the wrong instrument. It escaped npm run format because prettier runs proseWrap: preserve, so both wrappings are valid. Regenerated with npm run medications:lexicon-report followed by prettier, the order the check expects. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01BKNFogaYfCQBvFVqFQnfRt --- docs/medication-interaction-lexicon-review.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/medication-interaction-lexicon-review.md b/docs/medication-interaction-lexicon-review.md index 8c8687a64c..ff70571c26 100644 --- a/docs/medication-interaction-lexicon-review.md +++ b/docs/medication-interaction-lexicon-review.md @@ -96,8 +96,8 @@ the class cannot be enumerated, and holds the medication at grey rather than gre **35 of the catalogue's 328 medications sit outside both ends of every resolved interaction row.** Entering one of them produces no alert — not because the combination was checked and -found clear, but because no machine-resolved edge in the corpus includes that drug. On screen those -outcomes look the same, so this list is the honest boundary of the feature. +found clear, but because no machine-resolved edge in the corpus includes that drug. On screen those outcomes look the +same, so this list is the honest boundary of the feature. This is a **corpus coverage** limit, not necessarily a lexicon fault. Widening it means adding an interaction row or making an existing row machine-resolvable, with clinical review of the source content. From f928be19b0164a5386d6b5a8bc26c5fbedca55a4 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 14 Aug 2026 15:13:43 +0000 Subject: [PATCH 03/11] docs(issues): record Phase 0 closure and retarget the lexicon findings Four merge-safe inbox requests; docs/outstanding-issues.md is untouched and is reconciled separately after this PR lands. - update #316: Phase 0 closed, including the forced-dispatch proof (run 31813064485 -> auto-created issue #1963). Also supersedes the stale 2026-08-09 drift figures with measured ones: 10 RPC mismatches unchanged, 20 missing indexes, 2 unexpected, and the two trigram indexes confirmed restored. - done #331: its comparison-bug hypothesis is refuted; the staleness was real and wrapping-only, inherited from main by every branch. - update #333: the regeneration half is done here; its real question - the check runs in verify:pr-local but in no CI job - stays open. - update #292: records the #1938/#1939 Phase 0 duplicate against the existing duplicate-work row rather than opening a near-identical new one. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01BKNFogaYfCQBvFVqFQnfRt --- .../21b6525a-dd2d-4dcc-95d5-c3c777420adf.json | 10 ++++++++++ .../3f8797e0-dffa-4d26-8019-15147b9af397.json | 10 ++++++++++ .../9792c896-78d8-46ab-b194-6a52b7fd7cab.json | 10 ++++++++++ .../c3d91fce-52e5-41ed-8648-b2bf5e95b32c.json | 10 ++++++++++ 4 files changed, 40 insertions(+) create mode 100644 docs/outstanding-issues-inbox/21b6525a-dd2d-4dcc-95d5-c3c777420adf.json create mode 100644 docs/outstanding-issues-inbox/3f8797e0-dffa-4d26-8019-15147b9af397.json create mode 100644 docs/outstanding-issues-inbox/9792c896-78d8-46ab-b194-6a52b7fd7cab.json create mode 100644 docs/outstanding-issues-inbox/c3d91fce-52e5-41ed-8648-b2bf5e95b32c.json diff --git a/docs/outstanding-issues-inbox/21b6525a-dd2d-4dcc-95d5-c3c777420adf.json b/docs/outstanding-issues-inbox/21b6525a-dd2d-4dcc-95d5-c3c777420adf.json new file mode 100644 index 0000000000..dd2f90d2c5 --- /dev/null +++ b/docs/outstanding-issues-inbox/21b6525a-dd2d-4dcc-95d5-c3c777420adf.json @@ -0,0 +1,10 @@ +{ + "version": 1, + "id": "21b6525a-dd2d-4dcc-95d5-c3c777420adf", + "createdOn": "2026-08-14", + "action": "update", + "payload": { + "id": "#333", + "detail": "PARTIAL 2026-08-14 (PR #1951): the regeneration half of this row's Next step is done. Ran npm run medications:lexicon-report, confirmed by whitespace-normalised byte comparison that it is a pure re-wrap and not a content change needing clinical review (all 28 catalogue terms identical), and committed it. The diagnosis in #331 is now closed out: it was not a staleness-comparison bug, it was a genuinely stale committed file that prettier could not flag because proseWrap: preserve accepts both wrappings. STILL OPEN, and the more important half: the check is in the local verify:pr-local chain but in no CI job, so it fails every local preflight while every required check stays green. Decide one way or the other — wire it into CI so it cannot silently rot again, or drop it from verify:pr-local so it stops failing preflights it does not gate. Caveat on this PR: #1951 carries the regeneration alongside a workflow test rather than strictly on its own as this row asked, because the session was constrained to a single designated branch; the regeneration is its own revertible commit." + } +} diff --git a/docs/outstanding-issues-inbox/3f8797e0-dffa-4d26-8019-15147b9af397.json b/docs/outstanding-issues-inbox/3f8797e0-dffa-4d26-8019-15147b9af397.json new file mode 100644 index 0000000000..fa7ca93a2f --- /dev/null +++ b/docs/outstanding-issues-inbox/3f8797e0-dffa-4d26-8019-15147b9af397.json @@ -0,0 +1,10 @@ +{ + "version": 1, + "id": "3f8797e0-dffa-4d26-8019-15147b9af397", + "createdOn": "2026-08-14", + "action": "update", + "payload": { + "id": "#292", + "detail": "Recurred 2026-08-14 on the database remediation plan, this time with two assistants building Phase 0: PR #1938 and PR #1939 both implemented live-drift failure routing and the post-migration trigger, merged four hours apart. Both landed and no harm resulted — #1939 built on #1938's commit and improved it, moving the findings capture after the migration-history step so a migration-history failure is visible instead of a clean drift result being published as its explanation. The cost was still two full authoring sessions and two CI cycles for one deliverable. This matters more for the phases still ahead than it did here: Phase 1 consumes an approved read-only production window, and Phases 3 and 4 consume approved mutation windows and live eval-canary budget, so a duplicate there wastes an operator-gated resource rather than just tokens. Concrete ask for the remediation work specifically: check the open-PR list for the surface before starting any of Phases 1-5, per docs/database-remediation-playbook.md." + } +} diff --git a/docs/outstanding-issues-inbox/9792c896-78d8-46ab-b194-6a52b7fd7cab.json b/docs/outstanding-issues-inbox/9792c896-78d8-46ab-b194-6a52b7fd7cab.json new file mode 100644 index 0000000000..d24e272a62 --- /dev/null +++ b/docs/outstanding-issues-inbox/9792c896-78d8-46ab-b194-6a52b7fd7cab.json @@ -0,0 +1,10 @@ +{ + "version": 1, + "id": "9792c896-78d8-46ab-b194-6a52b7fd7cab", + "createdOn": "2026-08-14", + "action": "update", + "payload": { + "id": "#316", + "detail": "Phase 0 CLOSED 2026-08-14, including the forced-dispatch proof its definition of done required. Dispatched live-drift on main (run 31813064485): the drift job failed as expected, the always() capture step still ran, and the separate drift-routing job then created issue #1963 'Live drift check failing' automatically, carrying the run URL, job result, trigger and the full findings block. Failure routing is therefore proven end-to-end against the real repository, not just offline; PR #1951 adds a mutation-verified contract test so it stays proven. That run also supersedes the stale 2026-08-09 drift numbers this row was opened with. Measured now: 10 match_* function def_hash mismatches (UNCHANGED - Phase 3 is entirely outstanding and remains the highest-stakes unknown), 20 missing_live indexes (not 21), and the same 2 unexpected_live indexes (document_table_facts_document_id_idx, storage_cleanup_jobs_owner_id_idx). documents_title_trgm_idx and document_chunks_content_trgm_idx are no longer in the missing list, independently confirmed by direct read-only query against sjrfecxgysukkwxsowpy (both indisvalid/indisready, 648 kB and 68 MB), which corroborates the restoration recorded in PR #1960. Next: Phase 3 (RPC reconciliation) before Phase 4, per the plan's ordering — the change that can alter clinical answers goes before the ones that only speed them up." + } +} diff --git a/docs/outstanding-issues-inbox/c3d91fce-52e5-41ed-8648-b2bf5e95b32c.json b/docs/outstanding-issues-inbox/c3d91fce-52e5-41ed-8648-b2bf5e95b32c.json new file mode 100644 index 0000000000..308af5387a --- /dev/null +++ b/docs/outstanding-issues-inbox/c3d91fce-52e5-41ed-8648-b2bf5e95b32c.json @@ -0,0 +1,10 @@ +{ + "version": 1, + "id": "c3d91fce-52e5-41ed-8648-b2bf5e95b32c", + "createdOn": "2026-08-14", + "action": "done", + "payload": { + "id": "#331", + "outcome": "Not a comparison bug. Investigated 2026-08-14 in PR #1951: the staleness was real and wrapping-only. Normalising whitespace on the committed and regenerated docs/medication-interaction-lexicon-review.md leaves them byte-identical across all 28 catalogue terms, so no content changed, but the committed line wrapping genuinely differed from the generator's. The reason three branches saw it with 'zero diff on their branch' is that it was already stale on main, so every branch inherited the failure regardless of what it touched — git diff origin/main was the wrong instrument, since main itself carried the stale copy. It also escaped npm run format because prettier runs proseWrap: preserve, which accepts both wrappings. Fixed by regenerating with npm run medications:lexicon-report followed by prettier (the order the check expects). The remaining open question — that no CI job runs this check — is tracked in #333 rather than here." + } +} From e77bae771233bf7b1bf9a6b22eded661712c2340 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 14 Aug 2026 15:21:32 +0000 Subject: [PATCH 04/11] docs(audit): record the Phase 0 forced-dispatch proof and the corrected drift figures Closes the last open item in the evidence file's Phase 0 section. Dispatch run 31813064485 exercised the whole path: the drift job failed, the always() capture still ran, the migration-history step correctly skipped, and the separate drift-routing job created issue #1963 with the label, run URL, job result, trigger and findings block. That run also supersedes the stale 2026-08-09 figures the file was opened with: 10 RPC def_hash mismatches (unchanged), 20 missing_live indexes (not 21), 2 unexpected_live (unchanged). Both trigram indexes are absent from the missing list, corroborating the Phase 4 restoration already recorded here. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01BKNFogaYfCQBvFVqFQnfRt --- docs/audit/live-drift-forensics-2026-08.md | 33 ++++++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/docs/audit/live-drift-forensics-2026-08.md b/docs/audit/live-drift-forensics-2026-08.md index 1846e8abe1..50c111e669 100644 --- a/docs/audit/live-drift-forensics-2026-08.md +++ b/docs/audit/live-drift-forensics-2026-08.md @@ -27,9 +27,36 @@ runs on pushes to `main` touching `supabase/migrations/**` or `supabase/schema.s `workflow_dispatch`, the secret preflight, and `concurrency.cancel-in-progress: false` were kept unchanged. No hosted Supabase call was made. -Outstanding for the operator: dispatch `live-drift` once to confirm a real failure produces the -pinned issue (provider-backed — not run from the authoring session), and add -`SUPABASE_ACCESS_TOKEN` to environment secrets per plan step 0.3 and ledger `#183`. +_2026-08-14, forced-dispatch proof (owner-authorized)._ `live-drift` dispatched on `main` +(Actions run `31813064485`). The definition-of-done behaviour was observed end-to-end: + +- `live-drift` job **failed** at `Compare live schema drift`, as intended for this proof. +- `Capture drift and migration-history findings` still ran (`if: always()`), and + `Align migration history for Supabase Preview` correctly **skipped** after the failing step. +- The separate `drift-routing` job then ran (`if: ${{ !cancelled() }}`) and **succeeded**, + creating issue **#1963 "Live drift check failing"** with label `live-drift-failure`, the run + URL, `Job result: failure`, `Trigger: workflow_dispatch`, and the full findings block. + +That run also supersedes the stale 2026-08-09 figures this file was opened with. Measured +2026-08-14, `UNEXPECTED DRIFT (32)`: + +| Category | 2026-08-09 | 2026-08-14 | +| ---------------------------------------- | ---------- | ------------------ | +| `match_*` function `def_hash` mismatches | 10 | **10 — unchanged** | +| `missing_live` indexes | 21 | **20** | +| `unexpected_live` indexes | 2 | **2 — unchanged** | + +`documents_title_trgm_idx` and `document_chunks_content_trgm_idx` are absent from the missing +list, independently corroborating the Phase 4 restoration below (verified separately by +read-only query against `sjrfecxgysukkwxsowpy`: both `indisvalid`/`indisready`, 648 kB and +68 MB). The 10 RPC mismatches are untouched, so **Phase 3 remains entirely outstanding** and is +the next step per the plan's ordering. + +Routing is also covered offline by `tests/live-drift-workflow.test.ts` (mutation-verified), so a +future regression fails a test rather than waiting for a live failure to be mishandled. + +Outstanding for the operator: add `SUPABASE_ACCESS_TOKEN` to environment secrets per plan step +0.3 and ledger `#183` (dashboard work; names only, never values). ## Phase 1 — Read-only forensics From 20228faa6002da009e290bc398345a47d2cd7a02 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 14 Aug 2026 15:30:05 +0000 Subject: [PATCH 05/11] docs(issues): resolve the two competing #316 updates into one accurate record Two pending mutations targeted #316 - this branch's dispatch-proof update and the incident session's restoration update from PR #1960 - which the inbox correctly refuses to apply without an explicit decision. Cancelled both and queued a single combined update so the row carries one coherent account. The combined text keeps the incident findings verbatim (both indexes restored and validated, supabase_rpc_latency_ms 31610 -> 1535 text / 8519 hybrid, the drop window, the outstanding dashboard-audit attribution) and corrects two details that PR #1960's own review and the 2026-08-14 dispatch have since settled: the 20260804110240 guard validates four OTHER indexes and never checks this pair, so it gives no existence bound for 2026-08-04; and the missing-index count is measured at 20, not 21. Also cancels a placeholder request queued in error by a failed shell substitution. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01BKNFogaYfCQBvFVqFQnfRt --- .../3d0adf39-ec7a-4fa3-9309-057a193410de.json | 10 ++++++++++ .../3dda04ff-1ae9-4153-80ed-ad081931e396.json | 10 ++++++++++ .../6b09c1df-5f7c-4103-af3c-aead33eafb00.json | 10 ++++++++++ .../e265c3b4-a97a-4575-a3bd-3fa1ddcdbb5f.json | 10 ++++++++++ .../fd548180-f031-44d8-bd70-24c3b03c5f21.json | 10 ++++++++++ 5 files changed, 50 insertions(+) create mode 100644 docs/outstanding-issues-inbox/3d0adf39-ec7a-4fa3-9309-057a193410de.json create mode 100644 docs/outstanding-issues-inbox/3dda04ff-1ae9-4153-80ed-ad081931e396.json create mode 100644 docs/outstanding-issues-inbox/6b09c1df-5f7c-4103-af3c-aead33eafb00.json create mode 100644 docs/outstanding-issues-inbox/e265c3b4-a97a-4575-a3bd-3fa1ddcdbb5f.json create mode 100644 docs/outstanding-issues-inbox/fd548180-f031-44d8-bd70-24c3b03c5f21.json diff --git a/docs/outstanding-issues-inbox/3d0adf39-ec7a-4fa3-9309-057a193410de.json b/docs/outstanding-issues-inbox/3d0adf39-ec7a-4fa3-9309-057a193410de.json new file mode 100644 index 0000000000..0249dbcdc8 --- /dev/null +++ b/docs/outstanding-issues-inbox/3d0adf39-ec7a-4fa3-9309-057a193410de.json @@ -0,0 +1,10 @@ +{ + "version": 1, + "id": "3d0adf39-ec7a-4fa3-9309-057a193410de", + "createdOn": "2026-08-14", + "action": "update", + "payload": { + "id": "#316", + "detail": "Combined 2026-08-14 update, superseding the two partial requests cancelled in this same batch. PHASE 0 CLOSED including the forced-dispatch proof its definition of done required: live-drift dispatched on main (Actions run 31813064485) failed at the drift step, the always() capture step still ran, the migration-history step correctly skipped, and the separate drift-routing job then created issue #1963 \"Live drift check failing\" carrying the label, run URL, job result, trigger and the full findings block. Routing is now also covered offline by tests/live-drift-workflow.test.ts, mutation-verified. INCIDENT REPAIR, owner-approved in-session: the two retrieval-critical indexes documents_title_trgm_idx and document_chunks_content_trgm_idx were restored with CREATE INDEX CONCURRENTLY plus ANALYZE, both indisvalid and indisready at 648 kB and 68 MB, re-verified afterwards by an independent read-only query. Before and after supabase_rpc_latency_ms 31610 to 1535 on the text fast path and 8519 hybrid, with match_document_chunks_text_v2 at 14 ms. No repo schema change was needed because the definitions were already codified. CORRECTED FIGURES measured 2026-08-14, superseding the 2026-08-09 numbers this row was opened with: 10 match_* def_hash mismatches (unchanged), 20 missing_live indexes rather than 21, and the same 2 unexpected_live. ATTRIBUTION STILL OPEN: migration 20260705180000 recorded 14 executed statements so it was not mark-applied, and the 20260804110240 guard validates four other indexes and never checks this pair, so it gives no existence bound for 2026-08-04. The drop window is therefore 2026-07-05 to 2026-08-02 and the dashboard audit-history pairing remains owner action; #248 stays open. NEXT: Phase 3 RPC reconciliation before Phase 4, per the plan's ordering that the change which can alter clinical answers precedes the ones that only speed them up. Evidence: docs/audit/live-drift-forensics-2026-08.md." + } +} diff --git a/docs/outstanding-issues-inbox/3dda04ff-1ae9-4153-80ed-ad081931e396.json b/docs/outstanding-issues-inbox/3dda04ff-1ae9-4153-80ed-ad081931e396.json new file mode 100644 index 0000000000..14a45f2ac1 --- /dev/null +++ b/docs/outstanding-issues-inbox/3dda04ff-1ae9-4153-80ed-ad081931e396.json @@ -0,0 +1,10 @@ +{ + "version": 1, + "id": "3dda04ff-1ae9-4153-80ed-ad081931e396", + "createdOn": "2026-08-14", + "action": "cancel", + "payload": { + "requestId": "9792c896-78d8-46ab-b194-6a52b7fd7cab", + "reason": "Superseded by the single combined #316 update queued in the same batch, which merges this request's dispatch proof and corrected drift figures with the incident-session findings from request bbf21714 so the row carries one coherent account instead of two partial ones." + } +} diff --git a/docs/outstanding-issues-inbox/6b09c1df-5f7c-4103-af3c-aead33eafb00.json b/docs/outstanding-issues-inbox/6b09c1df-5f7c-4103-af3c-aead33eafb00.json new file mode 100644 index 0000000000..82fe278626 --- /dev/null +++ b/docs/outstanding-issues-inbox/6b09c1df-5f7c-4103-af3c-aead33eafb00.json @@ -0,0 +1,10 @@ +{ + "version": 1, + "id": "6b09c1df-5f7c-4103-af3c-aead33eafb00", + "createdOn": "2026-08-14", + "action": "update", + "payload": { + "id": "#316", + "detail": "MISSING" + } +} diff --git a/docs/outstanding-issues-inbox/e265c3b4-a97a-4575-a3bd-3fa1ddcdbb5f.json b/docs/outstanding-issues-inbox/e265c3b4-a97a-4575-a3bd-3fa1ddcdbb5f.json new file mode 100644 index 0000000000..f66c3bbdc4 --- /dev/null +++ b/docs/outstanding-issues-inbox/e265c3b4-a97a-4575-a3bd-3fa1ddcdbb5f.json @@ -0,0 +1,10 @@ +{ + "version": 1, + "id": "e265c3b4-a97a-4575-a3bd-3fa1ddcdbb5f", + "createdOn": "2026-08-14", + "action": "cancel", + "payload": { + "requestId": "bbf21714-0ef9-4c2f-942f-1b8d7e328ac8", + "reason": "Superseded by a single combined #316 update queued in the same batch, which carries this request's findings verbatim (the two-index restoration, supabase_rpc_latency_ms 31610 -> 1535 text / 8519 hybrid, the drop window, and the outstanding dashboard-audit attribution) and corrects two details that PR #1960's own review and the 2026-08-14 dispatch have since settled: the 20260804110240 guard validates four OTHER indexes and never checks this pair, so it gives no existence bound for 2026-08-04; and the missing-index count is measured at 20, not 21. Cancelled rather than left pending because two pending mutations on one row require an explicit decision." + } +} diff --git a/docs/outstanding-issues-inbox/fd548180-f031-44d8-bd70-24c3b03c5f21.json b/docs/outstanding-issues-inbox/fd548180-f031-44d8-bd70-24c3b03c5f21.json new file mode 100644 index 0000000000..2963919720 --- /dev/null +++ b/docs/outstanding-issues-inbox/fd548180-f031-44d8-bd70-24c3b03c5f21.json @@ -0,0 +1,10 @@ +{ + "version": 1, + "id": "fd548180-f031-44d8-bd70-24c3b03c5f21", + "createdOn": "2026-08-14", + "action": "cancel", + "payload": { + "requestId": "6b09c1df-5f7c-4103-af3c-aead33eafb00", + "reason": "Queued in error: a shell substitution resolved to the placeholder text MISSING instead of the intended detail. Replaced by the correct combined update in the same batch." + } +} From 4c55ec05875dcf063555e71021adb9d1f1a42f5c Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Sat, 15 Aug 2026 00:15:52 +0800 Subject: [PATCH 06/11] test(drift): enforce routing API contracts --- tests/live-drift-workflow.test.ts | 99 +++++++++++++++++++++++-------- 1 file changed, 73 insertions(+), 26 deletions(-) diff --git a/tests/live-drift-workflow.test.ts b/tests/live-drift-workflow.test.ts index 4e614608bf..b7c41db244 100644 --- a/tests/live-drift-workflow.test.ts +++ b/tests/live-drift-workflow.test.ts @@ -9,6 +9,7 @@ const workflowPath = path.join(repoRoot, ".github", "workflows", "live-drift.yml const workflow = readFileSync(workflowPath, "utf8").replace(/\r\n/g, "\n"); type Issue = { number: number; title: string }; +type RepositoryCoordinates = { owner: string; repo: string }; type ScriptFunction = ( github: Record, @@ -64,11 +65,11 @@ if (extraScripts.length > 0) { const routingScript = new AsyncFunction("github", "context", "core", routingScriptSource); type Calls = { - closed: Array<{ issue_number: number; state?: string; state_reason?: string }>; - comments: Array<{ issue_number: number; body: string }>; - created: Array<{ title: string; labels: string[]; body: string }>; - listed: Array<{ labels: string; state: string }>; - updatedBodies: Array<{ issue_number: number; body: string }>; + closed: Array; + comments: Array; + created: Array; + listed: Array; + updatedBodies: Array; warnings: string[]; }; @@ -78,27 +79,47 @@ async function runRoutingScript(options: { findings?: string; openIssues?: Issue const github = { rest: { issues: { - create: async (request: { body: string; labels: string[]; title: string }) => { - calls.created.push({ body: request.body, labels: request.labels, title: request.title }); + create: async (request: RepositoryCoordinates & { body: string; labels: string[]; title: string }) => { + calls.created.push({ + body: request.body, + labels: request.labels, + owner: request.owner, + repo: request.repo, + title: request.title, + }); return { data: { number: 4242 } }; }, - createComment: async (request: { body: string; issue_number: number }) => { - calls.comments.push({ body: request.body, issue_number: request.issue_number }); + createComment: async (request: RepositoryCoordinates & { body: string; issue_number: number }) => { + calls.comments.push({ + body: request.body, + issue_number: request.issue_number, + owner: request.owner, + repo: request.repo, + }); }, - listForRepo: async (request: { labels: string; state: string }) => { - calls.listed.push({ labels: request.labels, state: request.state }); + listForRepo: async (request: RepositoryCoordinates & { labels: string; state: string }) => { + calls.listed.push({ labels: request.labels, owner: request.owner, repo: request.repo, state: request.state }); return { data: options.openIssues ?? [] }; }, - update: async (request: { body?: string; issue_number: number; state?: string; state_reason?: string }) => { + update: async ( + request: RepositoryCoordinates & { body?: string; issue_number: number; state?: string; state_reason?: string }, + ) => { if (request.state) { calls.closed.push({ issue_number: request.issue_number, + owner: request.owner, + repo: request.repo, state: request.state, state_reason: request.state_reason, }); } if (typeof request.body === "string") { - calls.updatedBodies.push({ body: request.body, issue_number: request.issue_number }); + calls.updatedBodies.push({ + body: request.body, + issue_number: request.issue_number, + owner: request.owner, + repo: request.repo, + }); } }, }, @@ -136,6 +157,30 @@ async function runRoutingScript(options: { findings?: string; openIssues?: Issue const pinnedIssue: Issue = { number: 1234, title: "Live drift check failing" }; const sampleFindings = "UNEXPECTED DRIFT (2):\n ! [indexes] missing_live documents_title_trgm_idx"; +const repositoryCoordinates = { owner: "BigSimmo", repo: "Database" }; + +function workflowJobPermissionMaps(source: string) { + const jobsStart = source.indexOf("jobs:\n"); + if (jobsStart < 0) throw new Error("Expected a jobs map in .github/workflows/live-drift.yml."); + + const jobsSection = source.slice(jobsStart); + const jobHeaders = [...jobsSection.matchAll(/^ ([a-z][\w-]*):$/gm)]; + const jobs = Object.fromEntries( + jobHeaders.map((header, index) => { + const bodyStart = (header.index ?? 0) + header[0].length + 1; + const bodyEnd = jobHeaders[index + 1]?.index ?? jobsSection.length; + const body = jobsSection.slice(bodyStart, bodyEnd); + const permissions = Object.fromEntries( + [...body.matchAll(/^ permissions:\n((?: [^\n]+\n?)*)/gm)].flatMap((permissionsMatch) => + [...permissionsMatch[1].matchAll(/^ ([\w-]+): ([\w-]+)$/gm)].map((entry) => [entry[1], entry[2]]), + ), + ); + return [header[1], { permissions }]; + }), + ); + + return { jobs }; +} describe("live-drift workflow triggers and privileges", () => { it("keeps the weekly schedule and manual dispatch", () => { @@ -164,15 +209,11 @@ describe("live-drift workflow triggers and privileges", () => { // Workflow-level permissions stay read-only, so no job inherits issue writes. expect(workflow).toMatch(/^permissions:\n {2}contents: read\n/m); - const routingStart = workflow.indexOf("\n drift-routing:"); - expect(routingStart).toBeGreaterThan(-1); - - // Match the YAML key only. Matching the bare string would also hit the - // explanatory comment above the job and silently pass on a real regression. - const grantPattern = /^ +issues: write$/gm; - const grants = [...workflow.matchAll(grantPattern)]; - expect(grants).toHaveLength(1); - expect(grants[0].index).toBeGreaterThan(routingStart); + const parsed = workflowJobPermissionMaps(workflow); + expect(parsed.jobs["drift-routing"]?.permissions).toEqual({ contents: "read", issues: "write" }); + for (const [jobName, job] of Object.entries(parsed.jobs)) { + if (jobName !== "drift-routing") expect(job.permissions.issues).toBeUndefined(); + } }); it("keeps the service-role key out of the job that can write issues", () => { @@ -198,10 +239,11 @@ describe("live-drift failure routing", () => { it("opens one labelled issue when the check fails and none is open", async () => { const calls = await runRoutingScript({ findings: sampleFindings, result: "failure" }); - expect(calls.listed).toEqual([{ labels: "live-drift-failure", state: "open" }]); + expect(calls.listed).toEqual([{ ...repositoryCoordinates, labels: "live-drift-failure", state: "open" }]); expect(calls.created).toHaveLength(1); expect(calls.created[0].title).toBe("Live drift check failing"); expect(calls.created[0].labels).toEqual(["live-drift-failure"]); + expect(calls.created[0]).toMatchObject(repositoryCoordinates); expect(calls.created[0].body).toContain("https://github.com/BigSimmo/Database/actions/runs/99"); expect(calls.created[0].body).toContain("documents_title_trgm_idx"); expect(calls.closed).toHaveLength(0); @@ -215,9 +257,10 @@ describe("live-drift failure routing", () => { }); expect(calls.created).toHaveLength(0); - expect(calls.updatedBodies).toEqual([expect.objectContaining({ issue_number: 1234 })]); + expect(calls.updatedBodies).toEqual([expect.objectContaining({ ...repositoryCoordinates, issue_number: 1234 })]); expect(calls.comments).toHaveLength(1); expect(calls.comments[0].issue_number).toBe(1234); + expect(calls.comments[0]).toMatchObject(repositoryCoordinates); expect(calls.comments[0].body).toContain("Still failing"); expect(calls.closed).toHaveLength(0); expect(calls.warnings.join(" ")).toContain("1234"); @@ -227,6 +270,7 @@ describe("live-drift failure routing", () => { const calls = await runRoutingScript({ findings: "", result: "failure" }); expect(calls.created).toHaveLength(1); + expect(calls.created[0]).toMatchObject(repositoryCoordinates); expect(calls.created[0].body).toContain("not** evidence of a clean schema"); expect(calls.created[0].body).not.toContain("UNEXPECTED DRIFT"); }); @@ -237,8 +281,11 @@ describe("live-drift failure routing", () => { expect(calls.comments).toHaveLength(1); expect(calls.comments[0].body).toContain("Resolved"); expect(calls.comments[0].body).toContain("https://github.com/BigSimmo/Database/actions/runs/99"); - expect(calls.closed).toEqual([{ issue_number: 1234, state: "closed", state_reason: "completed" }]); + expect(calls.closed).toEqual([ + { ...repositoryCoordinates, issue_number: 1234, state: "closed", state_reason: "completed" }, + ]); expect(calls.created).toHaveLength(0); + expect(calls.listed).toEqual([{ ...repositoryCoordinates, labels: "live-drift-failure", state: "open" }]); }); it("writes nothing when the check is green and no issue is open", async () => { @@ -254,6 +301,6 @@ describe("live-drift failure routing", () => { const calls = await runRoutingScript({ openIssues: [pinnedIssue], result: "" }); expect(calls.closed).toHaveLength(0); - expect(calls.updatedBodies).toHaveLength(1); + expect(calls.updatedBodies).toEqual([expect.objectContaining({ ...repositoryCoordinates, issue_number: 1234 })]); }); }); From e4d3e4d41f8f780945df1466713d8639e31b0c03 Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Sat, 15 Aug 2026 00:16:37 +0800 Subject: [PATCH 07/11] docs(review): record PR-1951 contract fix --- ...df7c5c774b595dbdd7338816418b90abb2584b88d3d49962c5d.record.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/branch-review-records/248b36b92b06adf7c5c774b595dbdd7338816418b90abb2584b88d3d49962c5d.record.md diff --git a/docs/branch-review-records/248b36b92b06adf7c5c774b595dbdd7338816418b90abb2584b88d3d49962c5d.record.md b/docs/branch-review-records/248b36b92b06adf7c5c774b595dbdd7338816418b90abb2584b88d3d49962c5d.record.md new file mode 100644 index 0000000000..5577d0b845 --- /dev/null +++ b/docs/branch-review-records/248b36b92b06adf7c5c774b595dbdd7338816418b90abb2584b88d3d49962c5d.record.md @@ -0,0 +1 @@ +| 2026-08-14 | PR-1951 | 4c55ec05875dcf063555e71021adb9d1f1a42f5c | PR #1951 full review and unblock | fixed | workflow permission-map parser; GitHub Issue API owner/repo assertions; node scripts/check-docs-links.mjs; node scripts/ledger-inbox.mjs check; node scripts/check-ledger-write-discipline.mjs --self-test; Vitest unavailable: node_modules absent | From c39d8fb27f44fe837a1ad756feaa994ef92811e5 Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Sat, 15 Aug 2026 01:14:44 +0800 Subject: [PATCH 08/11] docs(review): record PR-1951 current-base review --- ...58783c42bcd3a18b865415668919f9bc7f081bedf9fe16aecdf.record.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/branch-review-records/0ab0fabc55b3958783c42bcd3a18b865415668919f9bc7f081bedf9fe16aecdf.record.md diff --git a/docs/branch-review-records/0ab0fabc55b3958783c42bcd3a18b865415668919f9bc7f081bedf9fe16aecdf.record.md b/docs/branch-review-records/0ab0fabc55b3958783c42bcd3a18b865415668919f9bc7f081bedf9fe16aecdf.record.md new file mode 100644 index 0000000000..dba4be1fb9 --- /dev/null +++ b/docs/branch-review-records/0ab0fabc55b3958783c42bcd3a18b865415668919f9bc7f081bedf9fe16aecdf.record.md @@ -0,0 +1 @@ +| 2026-08-14 | PR-1951 | 7d70c74cc5449d577df3895aa766ad31f3204045 | tests/live-drift-workflow.test.ts; docs/outstanding-issues-inbox; docs/branch-review-records | preserved prior test fixes; merged latest main; cancelled superseded #331/#333 ledger mutations to restore deterministic queue application | manual adversarial review; current thread verification; docs links passed; ledger inbox passed; ledger guards passed; git merge-tree; git diff --check; focused Vitest unavailable (node_modules absent) | From 809c50bf4ca8ede8c2c0ec49df9371cd4d56c517 Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Sat, 15 Aug 2026 01:28:21 +0800 Subject: [PATCH 09/11] test(live-drift): format workflow coverage --- tests/live-drift-workflow.test.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/live-drift-workflow.test.ts b/tests/live-drift-workflow.test.ts index b7c41db244..66c3ac8ef5 100644 --- a/tests/live-drift-workflow.test.ts +++ b/tests/live-drift-workflow.test.ts @@ -102,7 +102,12 @@ async function runRoutingScript(options: { findings?: string; openIssues?: Issue return { data: options.openIssues ?? [] }; }, update: async ( - request: RepositoryCoordinates & { body?: string; issue_number: number; state?: string; state_reason?: string }, + request: RepositoryCoordinates & { + body?: string; + issue_number: number; + state?: string; + state_reason?: string; + }, ) => { if (request.state) { calls.closed.push({ From 85f9c244701d66f136f967dc6b9837c6850506ec Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Sat, 15 Aug 2026 01:29:08 +0800 Subject: [PATCH 10/11] docs(review): record PR-1951 format repair --- ...8c67da3f5d43e867ed46a9dbfa89fdd249cead35fa563bd9119.record.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/branch-review-records/28051a48f8acb8c67da3f5d43e867ed46a9dbfa89fdd249cead35fa563bd9119.record.md diff --git a/docs/branch-review-records/28051a48f8acb8c67da3f5d43e867ed46a9dbfa89fdd249cead35fa563bd9119.record.md b/docs/branch-review-records/28051a48f8acb8c67da3f5d43e867ed46a9dbfa89fdd249cead35fa563bd9119.record.md new file mode 100644 index 0000000000..c775fff880 --- /dev/null +++ b/docs/branch-review-records/28051a48f8acb8c67da3f5d43e867ed46a9dbfa89fdd249cead35fa563bd9119.record.md @@ -0,0 +1 @@ +| 2026-08-14 | PR-1951 | 809c50bf4ca8ede8c2c0ec49df9371cd4d56c517 | PR #1951 CI format repair | fixed the exact-head Changed-file format check failure in live-drift workflow coverage | Prettier 3.9.6; All matched files use Prettier code style!; Tests 15 passed (15); git diff --check passed; docs link check passed: 1775 repo path references resolve.; Ledger inbox check passed: 22 pending request(s), 138 applied.; ledger write discipline self-test passed.; Branch review ledger guard passed: 880 live table records + 1206 archived + 91 immutable | From 4ceb2e5bbf1a8f60035a7574755016ece7f5a0b0 Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Sat, 15 Aug 2026 01:45:31 +0800 Subject: [PATCH 11/11] docs(ledger): record PR #1951 final base sync --- ...0affd610471e14ffdbacf8e042b608a2c3553c5ae303b34e92b.record.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/branch-review-records/9cb91634447e60affd610471e14ffdbacf8e042b608a2c3553c5ae303b34e92b.record.md diff --git a/docs/branch-review-records/9cb91634447e60affd610471e14ffdbacf8e042b608a2c3553c5ae303b34e92b.record.md b/docs/branch-review-records/9cb91634447e60affd610471e14ffdbacf8e042b608a2c3553c5ae303b34e92b.record.md new file mode 100644 index 0000000000..8cdd6530c8 --- /dev/null +++ b/docs/branch-review-records/9cb91634447e60affd610471e14ffdbacf8e042b608a2c3553c5ae303b34e92b.record.md @@ -0,0 +1 @@ +| 2026-08-14 | PR-1951 | 6ed1fb871c7e16e89ed111a9576d502d90a765b1 | PR #1951 final base sync after formatting fix | Merged the current main including the #1959 ledger reconciliation after the targeted Prettier repair; merge tree is clean and the run-scoped workflow regression suite remains green. | All matched files use Prettier code style; Test Files 1 passed; Tests 15 passed; docs link check passed: 1775 repo path references resolve; Ledger inbox check passed: 22 pending request(s), 138 applied; branch-review-ledger self-test passed; Branch review ledger guard passed: 880 live table records + 1206 archived + 98 immutable; verify:pr-local unavailable: tsx/cli absent from isolated worktree (Node v24.14.0). |