Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
fb45463
chore: close verified ledger follow-ups
BigSimmo Jul 30, 2026
a9596f8
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
268b201
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
763846f
docs: record ledger bundle review
BigSimmo Jul 30, 2026
1ee749b
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
40bfc09
docs: supersede ledger bundle review
BigSimmo Jul 30, 2026
ee66a39
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
2ca74fa
docs: supersede ledger review after main sync
BigSimmo Jul 30, 2026
23572a4
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
606280b
docs: supersede ledger review after governance sync
BigSimmo Jul 30, 2026
b43817f
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
1447cac
docs: supersede ledger review with conflict evidence
BigSimmo Jul 30, 2026
072051e
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
5a59a6a
docs: supersede ledger review after Codex fix sync
BigSimmo Jul 30, 2026
2a590d8
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
cc9aa4b
docs: supersede ledger review after reliability sync
BigSimmo Jul 30, 2026
7d6a341
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
c5a1bd3
docs: supersede ledger review after archive sync
BigSimmo Jul 30, 2026
85a6bdf
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
20f9405
docs: supersede ledger review after state-matrix sync
BigSimmo Jul 30, 2026
14508ca
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
f44c376
docs: supersede ledger review after phone-flake sync
BigSimmo Jul 30, 2026
226ab15
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
e0d96d1
docs: supersede ledger review after worker sync
BigSimmo Jul 30, 2026
039b43a
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
a3192f6
docs: supersede ledger review after live-workflow sync
BigSimmo Jul 30, 2026
9511c61
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
22bd074
docs: supersede ledger review after compact-table sync
BigSimmo Jul 30, 2026
a71bfd3
fix(ci): keep composite actions in coverage scope
BigSimmo Jul 30, 2026
a278aca
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
12c5437
docs: supersede ledger review after deletion-guard sync
BigSimmo Jul 30, 2026
4195646
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
4e4828c
docs: supersede ledger review after latest main sync
BigSimmo Jul 30, 2026
71d5ad7
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
349cc8b
docs: supersede ledger review after budget sync
BigSimmo Jul 30, 2026
035166d
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
9583b7f
fix(ci): honor file-wide issue ledger formatting guard
BigSimmo Jul 30, 2026
ab24110
docs: record final ledger bundle review
BigSimmo Jul 30, 2026
dfb23bb
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
633a5bf
docs: record synced ledger bundle review
BigSimmo Jul 30, 2026
011a371
docs: preserve verified issue closures after main sync
BigSimmo Jul 30, 2026
36dea3b
docs: record closure-preservation review
BigSimmo Jul 30, 2026
7779f5d
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
067ff22
fix(docs): deduplicate archived advisory issue
BigSimmo Jul 30, 2026
bfbfe2c
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
cd5e89e
docs: record final main decision sync
BigSimmo Jul 30, 2026
3ece237
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
9680455
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
7238475
docs: retain canonical archived issue records
BigSimmo Jul 30, 2026
8445acc
docs: record final ledger repair review
BigSimmo Jul 30, 2026
ade61ba
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
c5fcedf
docs: record post-guard-sync review
BigSimmo Jul 30, 2026
4a78824
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
63f03a6
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
6d386e7
Merge remote-tracking branch 'origin/main' into codex/ledger-next-202…
BigSimmo Jul 30, 2026
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
62 changes: 42 additions & 20 deletions docs/branch-review-ledger.md

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions docs/codex-review-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ Use this protocol for every Codex review, audit, bug hunt, PR review, release-re
- Ask before any OpenAI, Supabase, GitHub/GitLab, hosted CI, or provider-backed workflow.
- After any completed branch/PR review, append to `docs/branch-review-ledger.md` with `npm run ledger:append -- --ref <x> --head <full-sha> --scope <s> --outcome <o> --checks <c>`. Record the full 40-character SHA; `see PR head` and abbreviations make the record unmatchable and cause the review to run again. The ledger is append-only: never edit or delete an existing record; append a correction or superseding record (`--supersede`) instead. This ledger append is allowed even during a pure review. Do not hand-write the markdown row — hand-written rows are what produced the mojibake, wrong-width, and duplicate records the 2026-07-28 hygiene pass had to repair. Do not push a tip whose sole delta is a babysit ledger append; after merging `origin/main` into a branch that touched the ledger, run `npm run ledger:dedupe` when exact twins appear.

## Ledger Rotation

At the start of each UTC calendar quarter, or earlier when the live table becomes unwieldy, run `npm run ledger:rotate -- --dry-run`. If the preview contains only the intended completed records, run `npm run ledger:rotate` and commit the live ledger and generated archive together. Lookup, sweep, and integrity checks read both locations. Never hand-move rows or delete unique review content; stop if the dry-run shows unexpected mass movement or an archive-path collision.

## Severity Guide

- P0: Data loss, security breach, production outage, or clinical safety issue likely to harm users immediately.
Expand Down
18 changes: 9 additions & 9 deletions docs/outstanding-issues.md

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions scripts/check-github-action-pins.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,16 @@ failures.push(...collectPinFailures(process.cwd()));

const ciWorkflowPath = path.join(workflowDir, "ci.yml");
const ciWorkflow = readFileSync(ciWorkflowPath, "utf8");
const ciPullRequestTrigger = yamlBlock(ciWorkflow, "pull_request:", 2);
const migrationJob = yamlBlock(ciWorkflow, "db-reset-verify:", 2);
const setupSupabaseStep = yamlBlock(migrationJob, "- name: Setup Supabase CLI", 6);
const restoreSupabaseStep = yamlBlock(migrationJob, "- name: Restore Supabase Docker image cache", 6);
const saveSupabaseStep = yamlBlock(migrationJob, "- name: Save Supabase Docker images", 6);
if (!/^ types: \[opened, synchronize, reopened, ready_for_review\]$/m.test(ciPullRequestTrigger)) {
failures.push(
"ci.yml: pull_request events must retain opened/synchronize/reopened and include ready_for_review so undrafting starts required CI.",
);
}
if (!new RegExp(`^ SUPABASE_CLI_VERSION: ${expectedSupabaseCliVersionPattern}$`, "m").test(ciWorkflow)) {
failures.push(`ci.yml: global SUPABASE_CLI_VERSION must remain pinned to ${expectedSupabaseCliVersion}.`);
}
Expand Down
65 changes: 63 additions & 2 deletions scripts/check-outstanding-issues.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export const ISSUES_PATH = "docs/outstanding-issues.md";
const OPEN_HEADING = "## Open items";
const ARCHIVE_HEADING = "## Resolved / archive";
const MARKER = /<!--\s*issues:next-id=(\d+)\s*-->/;
const PRETTIER_IGNORE = "<!-- prettier-ignore -->";
/**
* An id cell's shape, e.g. `#042`. Used to READ the number, never to decide
* whether a line is a row.
Expand Down Expand Up @@ -72,6 +73,10 @@ function cells(line) {
.map((cell) => cell.trim());
}

function canonicalTableRow(line) {
return `| ${cells(line).join(" | ")} |`;
}

/**
* The lines that make up one table's BODY, and the width its separator declares.
*
Expand Down Expand Up @@ -224,9 +229,33 @@ export function parseIssues(markdown) {
};
}

export function checkIssues(markdown) {
export function checkIssues(markdown, { prettierIgnored = false } = {}) {
const problems = [];
const { openStart, archiveStart, nextId, markerCount, rows, orphans, bodyCount } = parseIssues(markdown);
const lines = markdown.split("\n");

// Prettier pads every Markdown table cell to the widest value in its column.
// In this long-lived ledger, changing one cell would then rewrite hundreds
// of unrelated rows and make concurrent merges needlessly conflict.
for (let index = 0; index < lines.length; index += 1) {
const line = lines[index];
if (/^\|.*\|\s*$/.test(line) && line !== canonicalTableRow(line)) {
problems.push(
`line ${index + 1} is not a compact canonical table row — use one space around each cell delimiter`,
);
}
if (
!prettierIgnored &&
/^\|/.test(line) &&
SEPARATOR.test(lines[index + 1] ?? "") &&
lines[index - 1]?.trim() !== PRETTIER_IGNORE
) {
problems.push(
`line ${index + 1} starts a table without ${PRETTIER_IGNORE} immediately above it — ` +
"formatting would re-pad every row and amplify merge conflicts",
);
}
}

if (openStart < 0) problems.push(`missing the "${OPEN_HEADING}" heading`);
if (archiveStart < 0) problems.push(`missing the "${ARCHIVE_HEADING}" heading`);
Expand Down Expand Up @@ -338,6 +367,10 @@ export function checkIssues(markdown) {
return problems;
}

export function prettierIgnoreCoversIssues(prettierIgnore) {
return prettierIgnore.split(/\r?\n/).some((line) => line.trim() === ISSUES_PATH);
}

/**
* IDs that existed at the comparison base but disappeared from the current
* ledger entirely. Moving a row from open to archive keeps its allocation and
Expand Down Expand Up @@ -396,17 +429,26 @@ function readIssuesAtRevision(ref) {
function selfTest() {
const good = [
"<!-- issues:next-id=3 -->",
"## Recommended execution queue",
PRETTIER_IGNORE,
"| Rank | ID |",
"| --- | --- |",
"| 1 | #001 |",
"## Open items",
PRETTIER_IGNORE,
"| ID | Pri | Summary |",
"| --- | --- | --- |",
"| #001 | P2 | a |",
"## Resolved / archive",
PRETTIER_IGNORE,
"| ID | Summary |",
"| --- | --- |",
"| #002 | b |",
].join("\n");
const cases = [
["a well-formed file", good, 0],
["a table without a scoped prettier ignore", good.replace(`${PRETTIER_IGNORE}\n| Rank | ID |`, "| Rank | ID |"), 1],
["a padded table row", good.replace("| #001 | P2 | a |", "| #001 | P2 | a |"), 1],
["a duplicated id", good.replace("| #002 | b |", "| #001 | b |"), 2], // duplicate + both-tables
["an id at the marker", good.replace("next-id=3", "next-id=2"), 1],
["a row with a stray pipe", good.replace("| #001 | P2 | a |", "| #001 | P2 | a | b |"), 1],
Expand Down Expand Up @@ -459,6 +501,19 @@ function selfTest() {
for (const problem of problems) console.error(` - ${problem}`);
}
}
const fileWideIgnoreProblems = checkIssues(good.replaceAll(`${PRETTIER_IGNORE}\n`, ""), {
prettierIgnored: true,
});
if (fileWideIgnoreProblems.length !== 0) {
failures += 1;
console.error(
`self-test FAILED: a file-wide prettier ignore replaces scoped table comments — expected 0 problems, got ${fileWideIgnoreProblems.length}`,
);
}
if (!prettierIgnoreCoversIssues(`# ledger files\n${ISSUES_PATH}\n`) || prettierIgnoreCoversIssues("docs/*.md\n")) {
failures += 1;
console.error("self-test FAILED: file-wide prettier-ignore detection must require the exact ledger path");
}
if (failures > 0) process.exit(1);

const deletionCases = [
Expand Down Expand Up @@ -526,7 +581,13 @@ function main() {
return;
}
const markdown = readFileSync(ISSUES_PATH, "utf8");
const problems = checkIssues(markdown);
let prettierIgnored = false;
try {
prettierIgnored = prettierIgnoreCoversIssues(readFileSync(".prettierignore", "utf8"));
} catch {
// Without a file-wide ignore, each table must carry its own scoped comment.
}
const problems = checkIssues(markdown, { prettierIgnored });
const base = issueBaseRevision();
let checkedBase = null;
if (base) {
Expand Down
12 changes: 12 additions & 0 deletions scripts/ci-change-scope.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,18 @@ function selfTest() {
},
);

assertScope("workflow-only-keeps-coverage", [".github/workflows/ci.yml"], {
coverage_changed: true,
workflow_changed: true,
});
assertScope("composite-action-only-keeps-coverage", [".github/actions/setup-ui-e2e/action.yml"], {
coverage_changed: true,
workflow_changed: true,
});
assertScope("runtime-config-keeps-coverage", ["lighthouse-budget.json"], {
coverage_changed: true,
});

assertScope("unstaged-status", parseStatusPorcelain(" M scripts/ci-change-scope.mjs\0"), {
source_changed: true,
workflow_changed: true,
Expand Down
12 changes: 12 additions & 0 deletions tests/ui-smoke.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,17 @@ test.beforeEach(stubZeroTouchPoints);
test.describe("Clinical KB UI smoke coverage", () => {
test.describe.configure({ timeout: 60000 });

test("Supabase connection hints reach the document head without provider traffic", async ({ page }) => {
await page.goto("/", { waitUntil: "domcontentloaded" });

const preconnect = page.locator('head link[rel="preconnect"][href="http://127.0.0.1:1"]');
const dnsPrefetch = page.locator('head link[rel="dns-prefetch"][href="http://127.0.0.1:1"]');

await expect(preconnect).toHaveCount(1);
await expect(preconnect).toHaveAttribute("crossorigin", "anonymous");
await expect(dnsPrefetch).toHaveCount(1);
});

for (const viewport of dashboardViewports) {
test(`dashboard loads without page overflow at ${viewport.name}`, async ({ page }) => {
await page.setViewportSize({ width: viewport.width, height: viewport.height });
Expand Down Expand Up @@ -3584,6 +3595,7 @@ test.describe("Clinical KB UI smoke coverage", () => {
).toBeVisible();

const sourceSearch = page.getByLabel("Search within indexed source text").last();
await waitForReactEventHandler(sourceSearch, "onChange");
await sourceSearch.fill("safety plan include");
const desktopTextPanel = page.getByTestId("source-chunk-indexed-text-panel");
await expect(desktopTextPanel.getByText("Hit 1 of 2").first()).toBeVisible();
Expand Down
Loading