perf(web): add idempotent batch verification fast paths
This commit is contained in:
48
web/tests/unit/wbv2-fast-paths.test.mjs
Normal file
48
web/tests/unit/wbv2-fast-paths.test.mjs
Normal file
@@ -0,0 +1,48 @@
|
||||
import assert from "node:assert/strict";
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import test from "node:test";
|
||||
|
||||
import {
|
||||
adaptiveBatchSize,
|
||||
batchContract,
|
||||
commandBudget,
|
||||
completedBatch,
|
||||
} from "../../../tools/web/wbv2-batch-contract.mjs";
|
||||
import { createFailureLedgerSession } from "../../../tools/web/wbv2-failure-ledger.mjs";
|
||||
|
||||
test("batch contract is stable and completion is idempotent", () => {
|
||||
const module = { moduleId: "FCURVE", coverageBindings: ["rna:a", "rna:b"] };
|
||||
const contract = batchContract("WBV2-P1-001", module);
|
||||
assert.equal(contract.selectedCount, 2);
|
||||
assert.match(contract.batchId, /^WBV2-P1-001:FCURVE:[a-f0-9]{16}$/u);
|
||||
assert.equal(completedBatch({ status: "done", batchId: contract.batchId, selectedRecordIds: contract.selectedRecordIds }, "WBV2-P1-001", module), true);
|
||||
});
|
||||
|
||||
test("adaptive batches follow the three-cycle fast and slow paths", () => {
|
||||
assert.equal(adaptiveBatchSize({ currentSize: 24, maxSize: 32, history: [{ durationMs: 120_000, commands: 10, focusedGateFailure: false }] }), 28);
|
||||
assert.equal(adaptiveBatchSize({ currentSize: 24, maxSize: 32, history: [{ durationMs: 901_000, commands: 10 }] }), 12);
|
||||
assert.equal(adaptiveBatchSize({ currentSize: 24, maxSize: 32, remaining: 5, history: [] }), 5);
|
||||
});
|
||||
|
||||
test("command budget separates exploration from execution", () => {
|
||||
assert.equal(commandBudget(["cat file", "npm run build"]).withinBudget, true);
|
||||
assert.equal(commandBudget(Array.from({ length: 49 }, () => "npm run focused")).withinBudget, false);
|
||||
assert.equal(commandBudget(Array.from({ length: 17 }, () => "rg pattern")).withinBudget, false);
|
||||
});
|
||||
|
||||
test("failure ledger hydrates completed cycles and flushes once", () => {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), "wbv2-fast-path-ledger-"));
|
||||
const logPath = "tests/golden/WBV2/cycle.log";
|
||||
fs.mkdirSync(path.dirname(path.join(root, logPath)), { recursive: true });
|
||||
fs.writeFileSync(path.join(root, logPath), 'prefix {"event":"cycle.completed","failure":{"task":"T","phase":"gate","reason":"failed"}}\n');
|
||||
const session = createFailureLedgerSession(root, { logPaths: [logPath] });
|
||||
assert.equal(session.ledger.entries.length, 1);
|
||||
session.record({ task: "T2", phase: "gate", reason: "failed" });
|
||||
assert.equal(fs.existsSync(path.join(root, "tests/golden/WBV2/failure-ledger.json")), false);
|
||||
session.flush();
|
||||
const written = JSON.parse(fs.readFileSync(path.join(root, "tests/golden/WBV2/failure-ledger.json"), "utf8"));
|
||||
assert.equal(written.entries.length, 2);
|
||||
assert.deepEqual(written.hydratedLogs, [logPath]);
|
||||
});
|
||||
Reference in New Issue
Block a user