From 31236a0c7c2d4800762d03783b531145577f7b73 Mon Sep 17 00:00:00 2001 From: Wang Runyuan <281843989+runyuan-wang@users.noreply.github.com> Date: Wed, 12 Aug 2026 23:59:24 -0700 Subject: [PATCH 1/4] Keep mini-benchmark JSON artifacts Prettier-clean --- .../performance/artifacts-m3-final/A5-one-byte-edit.json | 6 +----- tests/performance/artifacts/A5-one-byte-edit.json | 6 +----- tests/performance/mini-bench.mjs | 8 +++++++- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/tests/performance/artifacts-m3-final/A5-one-byte-edit.json b/tests/performance/artifacts-m3-final/A5-one-byte-edit.json index 4f0fe6c..2a665c8 100644 --- a/tests/performance/artifacts-m3-final/A5-one-byte-edit.json +++ b/tests/performance/artifacts-m3-final/A5-one-byte-edit.json @@ -22,11 +22,7 @@ "counters": { "wallMs": 70.676, "editCount": 3, - "perEditMs": [ - 31.492, - 23.338, - 15.617 - ], + "perEditMs": [31.492, 23.338, 15.617], "dbGrowthBytes": 939360, "transactions": 6, "statements": 144, diff --git a/tests/performance/artifacts/A5-one-byte-edit.json b/tests/performance/artifacts/A5-one-byte-edit.json index ce0eefe..b263473 100644 --- a/tests/performance/artifacts/A5-one-byte-edit.json +++ b/tests/performance/artifacts/A5-one-byte-edit.json @@ -22,11 +22,7 @@ "counters": { "wallMs": 74.747, "editCount": 3, - "perEditMs": [ - 31.671, - 23.772, - 19.148 - ], + "perEditMs": [31.671, 23.772, 19.148], "dbGrowthBytes": 939360, "transactions": 6, "statements": 156, diff --git a/tests/performance/mini-bench.mjs b/tests/performance/mini-bench.mjs index 2b79071..c71c7a4 100644 --- a/tests/performance/mini-bench.mjs +++ b/tests/performance/mini-bench.mjs @@ -24,6 +24,7 @@ import { tmpdir } from "node:os"; import path from "node:path"; import { performance } from "node:perf_hooks"; import { createHash } from "node:crypto"; +import { format, resolveConfig } from "prettier"; import { openNodeSqlite } from "../../packages/sqlite-node/dist/index.js"; import { EphemeralFS } from "../../packages/fs/dist/index.js"; @@ -327,9 +328,14 @@ function artifactFor(cell, result, configuration, fixtureBytes, pass) { async function writeArtifacts(artifacts, directory) { await mkdir(directory, { recursive: true }); + const options = (await resolveConfig(path.join(ROOT, "package.json"))) ?? {}; for (const artifact of artifacts) { const filename = path.join(directory, `${artifact.benchmark}.json`); - await writeFile(filename, `${JSON.stringify(artifact, null, 2)}\n`); + const contents = await format(JSON.stringify(artifact), { + ...options, + filepath: filename, + }); + await writeFile(filename, contents); } } From e0d9322e8850e5308904d00030ce4acd26b6d6bf Mon Sep 17 00:00:00 2001 From: Wang Runyuan <281843989+runyuan-wang@users.noreply.github.com> Date: Thu, 13 Aug 2026 02:14:37 -0700 Subject: [PATCH 2/4] ci: fetch full history for evidence checks --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a3c971d..41e3c73 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,6 +12,8 @@ jobs: timeout-minutes: 10 steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - uses: pnpm/action-setup@v4 with: version: 10.32.1 From fc36e2ebcaad555f8d0befce040cf792938e22bf Mon Sep 17 00:00:00 2001 From: Wang Runyuan <281843989+runyuan-wang@users.noreply.github.com> Date: Thu, 13 Aug 2026 03:22:17 -0700 Subject: [PATCH 3/4] fix(ci): validate only accepted evidence milestones --- scripts/check-evidence.mjs | 28 +++++++++++++++++++------- scripts/evidence-milestones.mjs | 8 ++++++++ tests/architecture/foundation.test.mjs | 14 +++++++++++++ 3 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 scripts/evidence-milestones.mjs diff --git a/scripts/check-evidence.mjs b/scripts/check-evidence.mjs index 0a87121..880c831 100644 --- a/scripts/check-evidence.mjs +++ b/scripts/check-evidence.mjs @@ -4,6 +4,7 @@ import { readFile } from "node:fs/promises"; import path from "node:path"; import { promisify } from "node:util"; import ts from "typescript"; +import { evidenceMilestonesThrough } from "./evidence-milestones.mjs"; const execute = promisify(execFile); const root = path.resolve(import.meta.dirname, ".."); @@ -15,10 +16,7 @@ const acceptedMatch = /^pnpm validate:(m\d+)$/u.exec(acceptedValidation ?? ""); if (!acceptedMatch) throw new Error("validate:accepted must select one milestone validation command"); const activeAcceptedMilestone = acceptedMatch[1]; -if (!new Set(["m0", "m1", "m2", "m3"]).has(activeAcceptedMilestone)) - throw new Error( - `evidence checker has no validation schema for ${activeAcceptedMilestone}`, - ); +const evidenceMilestones = new Set(evidenceMilestonesThrough(activeAcceptedMilestone)); function requireObject(value, name) { if (!value || typeof value !== "object" || Array.isArray(value)) @@ -269,6 +267,12 @@ if (process.argv[2] === "--owned-tree-digest") { process.exit(0); } +function reportValidationSuccess() { + console.log( + `evidence: preserved predecessor candidates through current ${activeAcceptedMilestone.toUpperCase()} with schemas, zero-failure results, candidate parents, sequential predecessors, independent audit, and required metrics internally consistent`, + ); +} + const m0 = await validateMilestone( "m0", [ @@ -292,6 +296,10 @@ if ( m0.artifact.metrics.matrixRuns * m0.artifact.metrics.architectureTestsPerCell ) throw new Error("m0 passed count differs from the recorded tests per matrix cell"); +if (!evidenceMilestones.has("m1")) { + reportValidationSuccess(); + process.exit(0); +} const m1 = await validateMilestone( "m1", @@ -317,6 +325,10 @@ const predecessor = m1.exit.match( )?.[1]; if (predecessor !== m0.candidate) throw new Error("m1 sequential predecessor differs from the accepted m0 candidate"); +if (!evidenceMilestones.has("m2")) { + reportValidationSuccess(); + process.exit(0); +} const m2 = await validateMilestone( "m2", @@ -349,6 +361,10 @@ const m2Predecessor = m2.exit.match( )?.[1]; if (m2Predecessor !== m1.candidate) throw new Error("m2 sequential predecessor differs from the accepted m1 candidate"); +if (!evidenceMilestones.has("m3")) { + reportValidationSuccess(); + process.exit(0); +} const m3 = await validateMilestone( "m3", @@ -388,6 +404,4 @@ const m3Predecessor = m3.exit.match( if (m3Predecessor !== m2.candidate) throw new Error("m3 sequential predecessor differs from the accepted m2 candidate"); -console.log( - `evidence: preserved predecessor candidates and current ${activeAcceptedMilestone.toUpperCase()} schemas, zero-failure results, candidate parents, sequential predecessors, independent audit, and required metrics are internally consistent`, -); +reportValidationSuccess(); diff --git a/scripts/evidence-milestones.mjs b/scripts/evidence-milestones.mjs new file mode 100644 index 0000000..6c6fd45 --- /dev/null +++ b/scripts/evidence-milestones.mjs @@ -0,0 +1,8 @@ +const supportedEvidenceMilestones = Object.freeze(["m0", "m1", "m2", "m3"]); + +export function evidenceMilestonesThrough(activeMilestone) { + const activeIndex = supportedEvidenceMilestones.indexOf(activeMilestone); + if (activeIndex < 0) + throw new Error(`evidence checker has no validation schema for ${activeMilestone}`); + return supportedEvidenceMilestones.slice(0, activeIndex + 1); +} diff --git a/tests/architecture/foundation.test.mjs b/tests/architecture/foundation.test.mjs index 6171fe3..97f4c0d 100644 --- a/tests/architecture/foundation.test.mjs +++ b/tests/architecture/foundation.test.mjs @@ -6,6 +6,7 @@ import { createRecordingFactory } from "../../packages/testkit/dist/index.js"; import { load as parseYaml } from "js-yaml"; import { documentationLinkErrors } from "../../scripts/documentation-links.mjs"; import { workflowPolicyErrors } from "../../scripts/workflow-policy.mjs"; +import { evidenceMilestonesThrough } from "../../scripts/evidence-milestones.mjs"; import eslintConfig from "../../eslint.config.js"; const root = path.resolve(import.meta.dirname, "../.."); @@ -36,6 +37,11 @@ test("CI invokes only the explicit highest accepted milestone gate", () => { ); const parsed = parseYaml(workflow); assert.deepEqual(workflowPolicyErrors(parsed), []); + const checkoutSteps = parsed.jobs.validate.steps.filter((step) => + /^actions\/checkout@/u.test(step.uses ?? ""), + ); + assert.equal(checkoutSteps.length, 1); + assert.equal(checkoutSteps[0].with?.["fetch-depth"], 0); const runSteps = parsed.jobs.validate.steps .filter((step) => Object.hasOwn(step, "run")) .map((step) => step.run); @@ -124,6 +130,14 @@ test("milestone gates select only their owned suites and sequential predecessors assert.equal(scripts["validate:accepted"], "pnpm validate:m2"); }); +test("evidence validation stops at the active accepted milestone", () => { + assert.deepEqual(evidenceMilestonesThrough("m0"), ["m0"]); + assert.deepEqual(evidenceMilestonesThrough("m1"), ["m0", "m1"]); + assert.deepEqual(evidenceMilestonesThrough("m2"), ["m0", "m1", "m2"]); + assert.deepEqual(evidenceMilestonesThrough("m3"), ["m0", "m1", "m2", "m3"]); + assert.throws(() => evidenceMilestonesThrough("m4"), /no validation schema for m4/u); +}); + test("documentation links resolve inline and reference-style targets", async () => { const filename = path.join(root, "docs", "fixture.md"); const read = async (target) => { From b5a7c5960c3f811a971e16600ab937f49d7881e7 Mon Sep 17 00:00:00 2001 From: Wang Runyuan <281843989+runyuan-wang@users.noreply.github.com> Date: Thu, 13 Aug 2026 03:29:06 -0700 Subject: [PATCH 4/4] docs(evidence): refresh M2 acceptance record --- docs/evidence/m2/correctness.json | 33 +++++++------- docs/evidence/m2/exit.md | 71 ++++++++++++++++--------------- 2 files changed, 54 insertions(+), 50 deletions(-) diff --git a/docs/evidence/m2/correctness.json b/docs/evidence/m2/correctness.json index 63521bf..45d1678 100644 --- a/docs/evidence/m2/correctness.json +++ b/docs/evidence/m2/correctness.json @@ -1,45 +1,46 @@ { "schema": "efs-correctness-result-v1", - "commit": "d01651b4ba3a5b9f2e5d02ab48d3d1b519396922", + "commit": "fc36e2ebcaad555f8d0befce040cf792938e22bf", "adapter": "node-sqlite-storage-suite", "schemaVersion": 2, "formatVersion": "efs-merkle-manifest-v1", "seed": 1592639710, "fixtureDigest": "37fcc2662466658ff1c3345de0dd5454764eded6ea1019a701563f359ab8c086", "faultPoint": "every-migration-statement-and-content-write-statement-fault-injection", - "passed": 99, + "passed": 105, "failed": 0, - "elapsedMs": 70919, - "ownedTreeDigest": "649f8c5017144efafd912829c871186d1066c978370549b8e2d496a2e99f5c8a", + "elapsedMs": 40662, + "ownedTreeDigest": "19975bff7857f772e3c7529db3d654467491248114d79868e4b89dd87fd19a97", "independentAudit": "approved", "metrics": { "operatingSystems": 1, "nodeVersions": 1, "matrixRuns": 1, - "nodeStorageTests": 86, + "nodeStorageTests": 92, "maintenanceTests": 13, "streamedBytes": 104857600, "streamManagedPeakBytes": 12373056, - "fallbackManagedPeakBytes": 11182080, + "fallbackManagedPeakBytes": 12759060, "fallbackSourceReadCalls": 3200, - "fallbackStorageTransactions": 3231, - "observedWalBytes": 124823672, + "fallbackStorageTransactions": 3233, + "observedWalBytes": 124691832, "sealedManifestEntries": 100001, "finalCertificateValidationStatements": 1, "stagedUniqueClosureMembers": 7, - "reconciliationStatementsPerManifestEntry": 0.04654953450465495, - "pathCopyLargestSourceReadBytes": 256, + "reconciliationStatementsPerManifestEntry": 0.017439825601743984, + "pathCopyLargestSourceReadBytes": 32768, "managedResidentLimitBytes": 134217728, "cacheLimitBytes": 67108864, "finalTransactionLimitBytes": 16777216, "fastCdcBufferCapacityBytes": 524288 }, "deviations": [ - "No hosted GitHub Actions run exists because the branch has not been pushed; this evidence records only the actually executed Windows x64, Node 24.11.1 local validation cell.", - "Independent audit approval is recorded for the accepted M2 baseline candidate 2e06a44; the M2 improvements candidate d01651b re-ran the complete acceptance gate chain (fixtures, docs, style, architecture, build, exports/API snapshots, 35 M1 algorithm tests, 11 workerd parity checks, and all 99 M2 storage tests) and refreshed this record with its measured metrics. No acceptance criterion or boundedness/quota/parity contract changed semantics.", - "R3 introduced a host-injected synchronous SHA-256 capability on the operations storage port: packages/sqlite-node provides node:crypto createHash and packages/fs/src keeps the byte-identical pure-JS implementation as the fallback used by workerd and any adapter without the capability. M1 golden vectors and the workerd parity suite pass unchanged; no node-only import entered packages/fs/src.", - "R5 batched staging entry/level-record inserts and reconciliation leaf-edge lookups (one hash IN (...) per leaf with a multi-row queue insert). The 100,001-entry closure now reconciles with 4,655 statements (0.0465 per manifest entry, down from 0.0507); the prepared-statement cache (256-entry bound) measured earlier is unchanged.", - "The FastCDC acceptChunk copy reduction removed a redundant defensive copy: StreamingFastCdc already emits fresh detached chunk slices. Storage accounting, quotas, and dedup behavior are unchanged; the mini-bench matrix (tests/performance) reports the same 7.19% fresh-data overhead, +4.7 MiB identical-rewrite delta, and exact quota ceilings before and after.", - "The mini-bench A6 cell (1,000 scattered one-byte edits on the 100 MiB file) records pass=false by design: default leaves exceed the bounded path-copy window, so edits use the O(file) streamed fallback and the harness caps the loop at 8 s. This is R1's M3 target; the deviation is recorded in the artifact, not hidden." + "No hosted GitHub Actions run exists yet for candidate fc36e2e because the branch has not been pushed; this evidence records only the actually executed macOS 14.4.1 arm64, Node 26.5.0, pnpm 10.32.1 local validation cell.", + "Independent audit approval remains the approval recorded for the accepted M2 baseline candidate 2e06a44. Candidate fc36e2e changes the mini-benchmark JSON formatting path, CI checkout depth, and evidence-checker accepted-milestone control flow; it re-ran the complete pre-evidence chain locally with 6 architecture tests, 40 M1/workerd tests, and all 105 M2 tests passing. This record does not claim a new independent audit of fc36e2e.", + "The refreshed M2 suite measured 92 storage/node-integration tests plus 13 maintenance tests. Its fallback diagnostic reported 3,200 source reads, 104,857,599 source bytes, 32,768 largest-read bytes, 34 repository persistence transactions, 3,233 reported storage transactions, and 12,759,060 managed peak bytes.", + "The sealed 100,001-entry closure reconciled with 1,744 statements (0.017439825601743984 per manifest entry), reached 7 unique closure members, and final-validated with one statement. The 100 MiB streaming diagnostic reported 12,373,056 managed peak bytes and a 124,691,832-byte WAL before reopen.", + "R3 continues to use a host-injected synchronous SHA-256 capability on the operations storage port: packages/sqlite-node provides node:crypto createHash and packages/fs/src keeps the byte-identical pure-JS fallback used by workerd and adapters without the capability. No node-only import entered packages/fs/src.", + "R5 continues to batch staging entry and level-record inserts plus reconciliation leaf-edge lookups. No statement, row, byte, boundedness, quota, or parity contract changed in this CI/evidence repair.", + "The FastCDC acceptChunk copy reduction remains unchanged. The mini-bench A6 cell remains the documented M3 target: default leaves exceed the bounded path-copy window, so scattered edits use the O(file) streamed fallback and the harness caps the loop at 8 seconds." ] } diff --git a/docs/evidence/m2/exit.md b/docs/evidence/m2/exit.md index 84ca089..103a1e7 100644 --- a/docs/evidence/m2/exit.md +++ b/docs/evidence/m2/exit.md @@ -1,57 +1,60 @@ ### Milestone 2 exit -- Candidate commit: `d01651b4ba3a5b9f2e5d02ab48d3d1b519396922` -- Date: 2026-08-11 +- Candidate commit: `fc36e2ebcaad555f8d0befce040cf792938e22bf` +- Date: 2026-08-13 - Sequential predecessor: accepted M1 candidate `ff8cd5a74e3b57392ff232788e6f9244cc447aaf`; this record supersedes the accepted M2 - baseline candidate `2e06a446aa5781102d9c028c62519582ee3b1519` with the M2 improvements - candidate + improvements candidate `d01651b4ba3a5b9f2e5d02ab48d3d1b519396922` with the CI/evidence + repair candidate - Checklist complete: yes; this record accepts M0, M1, and M2 only -- Primary environment: Microsoft Windows NT `10.0.26200.0`, x64, Node `24.11.1`, pnpm - `10.32.1` +- Primary environment: macOS `14.4.1`, arm64, Node `26.5.0`, pnpm `10.32.1` - Primary commands: `pnpm validate:m2:pre-evidence` (fixtures, docs, style, architecture, build, exports, M1 algorithms, workerd parity, M2 storage suite) and `pnpm check:evidence` -- Primary result: pass; 99 Node storage tests (86 storage/node-integration plus 13 - maintenance) in 70,919 ms total, 0 failed +- Primary result: pass; 105 M2 tests (92 storage/node-integration plus 13 maintenance) + in 40,662 ms, 0 failed; the complete local pre-evidence chain exited 0 in 87 seconds - Correctness artifact: [`correctness.json`](./correctness.json) +- Pre-evidence receipt: candidate `fc36e2e`; log SHA-256 + `c05233ae6f987909f89eee0f6526c017e8ebbe422f7325208e7c3a547d7ba967`; 25,414 bytes; + 2026-08-13T10:22:55Z through 2026-08-13T10:24:22Z - Benchmark artifact: the `tests/performance/mini-bench.mjs` matrix (cells A1-A7, B1-B5, C1-C3) with raw artifacts under `tests/performance/artifacts/`, `artifacts-r3/`, and `artifacts-baseline/`; see [`docs/benchmarks/m2-minibench.md`](../../benchmarks/m2-minibench.md) -- Smoke duration and operation counts: 70,919 ms for the M2 suite; the sealed - 100,001-entry closure reconciled with 4,655 statements (0.0465 per manifest entry, - down from 0.0507), reached 7 unique closure members, and final-validated with one +- Smoke duration and operation counts: 40,662 ms for the M2 suite; the sealed + 100,001-entry closure reconciled with 1,744 statements (0.017439825601743984 per + manifest entry), reached 7 unique closure members, and final-validated with one statement - Resource high-water: 128 MiB managed-resident default, 64 MiB byte-weighted cache, 16 MiB final-transaction ceiling, and a fixed 524,288-byte FastCDC buffer; observed - streamed-managed peak 12,373,056 bytes and fallback-managed peak 11,182,080 bytes on + streamed-managed peak 12,373,056 bytes and fallback-managed peak 12,759,060 bytes on the 100 MiB fixtures - Known deviations: - - No hosted GitHub Actions run exists because the branch has not been pushed; only the - actually executed Windows x64 / Node 24.11.1 cell is claimed. - - Reopen-after-fault is demonstrated per statement for migrations; content, expiry, - and cleanup fault tests verify complete rollback on the same connection without a - reopen leg. The testkit fault-controller capability is declared but not yet + - No hosted GitHub Actions run exists yet for candidate `fc36e2e` because the branch + has not been pushed; only the actually executed macOS 14.4.1 arm64 / Node 26.5.0 / + pnpm 10.32.1 cell is claimed. + - Independent audit approval remains the approval recorded for accepted M2 baseline + candidate `2e06a44`. Candidate `fc36e2e` re-ran the complete local pre-evidence + chain (6 architecture tests, 40 M1/workerd tests, and all 105 M2 tests) but this + record does not claim a new independent audit of that candidate. + - Candidate `fc36e2e` contains only the mini-benchmark JSON formatting repair, CI + full- history checkout, and accepted-milestone checker control-flow repair beyond + the existing accepted M2 implementation. It does not change an M2 storage, + boundedness, quota, parity, or benchmark acceptance contract. + - Reopen-after-fault remains demonstrated per statement for migrations; content, + expiry, and cleanup fault tests verify complete rollback on the same connection + without a reopen leg. The testkit fault-controller capability is declared but not implemented; both are evidence gaps, not observed defects. - - R3 hashing seam: the Node adapter injects `node:crypto` SHA-256 through the - operations storage port; workerd and adapters without the capability fall back to - the byte-identical pure-JS implementation. No node-only module enters - `packages/fs/src`, and M1 golden vectors plus the 11 workerd parity checks pass - unchanged. - - R5 statement batching: per-chunk staging inserts became multi-row `VALUES` inserts - and reconciliation leaf edges use one `hash IN (...)` lookup plus one multi-row - queue insert per leaf; write-path statements measured ~4x fewer on the mini-bench - (A1: 12,472 -> 3,065). No statement/row/byte budget contract changed. - - The mini-bench A6 cell (1,000 scattered one-byte edits on the 100 MiB file) records - `pass: false` by design: default leaves exceed the bounded path-copy window, so the - edits use the O(file) streamed fallback and the harness caps the loop at 8 s - (`completedEdits`/`scaledEdits` in the artifact). R1 targets sub-10 ms path-copy - edits in M3. + - The Node adapter injects `node:crypto` SHA-256 through the operations storage port; + workerd and adapters without the capability fall back to the byte-identical pure-JS + implementation. No node-only module enters `packages/fs/src`. + - The mini-bench A6 cell remains the documented M3 target: default leaves exceed the + bounded path-copy window, so scattered edits use the O(file) streamed fallback and + the harness caps the loop at 8 seconds. - Independent audit: the M2 baseline candidate `2e06a44` was independently approved (all 25 M2 checklist items and all ten acceptance criteria, `efs_usage` exactness, quota-race serialization, sealed-closure constant-row validation, WAL backpressure - observability, and deterministic restart-safe migrations). The M2 improvements - candidate `d01651b` re-ran the full gate chain and refreshed this record with its - measured metrics; no acceptance criterion changed semantics. + observability, and deterministic restart-safe migrations). The current candidate + `fc36e2e` re-ran the complete local gate chain and refreshed this record with its + measured metrics; no new independent audit of `fc36e2e` is claimed. - Approved to begin next milestone: yes