Skip to content
Merged
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
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
33 changes: 17 additions & 16 deletions docs/evidence/m2/correctness.json
Original file line number Diff line number Diff line change
@@ -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."
]
}
71 changes: 37 additions & 34 deletions docs/evidence/m2/exit.md
Original file line number Diff line number Diff line change
@@ -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
28 changes: 21 additions & 7 deletions scripts/check-evidence.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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, "..");
Expand All @@ -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))
Expand Down Expand Up @@ -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",
[
Expand All @@ -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",
Expand All @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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();
8 changes: 8 additions & 0 deletions scripts/evidence-milestones.mjs
Original file line number Diff line number Diff line change
@@ -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);
}
14 changes: 14 additions & 0 deletions tests/architecture/foundation.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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, "../..");
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) => {
Expand Down
6 changes: 1 addition & 5 deletions tests/performance/artifacts-m3-final/A5-one-byte-edit.json
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 1 addition & 5 deletions tests/performance/artifacts/A5-one-byte-edit.json
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
8 changes: 7 additions & 1 deletion tests/performance/mini-bench.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -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);
}
}

Expand Down
Loading