ppef 1.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -125
- package/bin/ppef.mjs +20 -0
- package/dist/__tests__/cli/evaluate-command.integration.test.d.ts +8 -0
- package/dist/__tests__/cli/evaluate-command.integration.test.d.ts.map +1 -0
- package/dist/__tests__/cli/evaluate-command.integration.test.js +308 -0
- package/dist/__tests__/cli/evaluate-command.integration.test.js.map +1 -0
- package/dist/__tests__/evaluators/claims-evaluator.unit.test.d.ts +8 -0
- package/dist/__tests__/evaluators/claims-evaluator.unit.test.d.ts.map +1 -0
- package/dist/__tests__/evaluators/claims-evaluator.unit.test.js +405 -0
- package/dist/__tests__/evaluators/claims-evaluator.unit.test.js.map +1 -0
- package/dist/__tests__/evaluators/metrics-evaluator.unit.test.d.ts +8 -0
- package/dist/__tests__/evaluators/metrics-evaluator.unit.test.d.ts.map +1 -0
- package/dist/__tests__/evaluators/metrics-evaluator.unit.test.js +424 -0
- package/dist/__tests__/evaluators/metrics-evaluator.unit.test.js.map +1 -0
- package/dist/__tests__/evaluators/registry.unit.test.d.ts +7 -0
- package/dist/__tests__/evaluators/registry.unit.test.d.ts.map +1 -0
- package/dist/__tests__/evaluators/registry.unit.test.js +173 -0
- package/dist/__tests__/evaluators/registry.unit.test.js.map +1 -0
- package/dist/__tests__/evaluators/robustness-evaluator.unit.test.d.ts +8 -0
- package/dist/__tests__/evaluators/robustness-evaluator.unit.test.d.ts.map +1 -0
- package/dist/__tests__/evaluators/robustness-evaluator.unit.test.js +260 -0
- package/dist/__tests__/evaluators/robustness-evaluator.unit.test.js.map +1 -0
- package/dist/__tests__/framework-pipeline.integration.test.js +49 -20
- package/dist/__tests__/framework-pipeline.integration.test.js.map +1 -1
- package/dist/__tests__/index-exports.unit.test.d.ts +8 -0
- package/dist/__tests__/index-exports.unit.test.d.ts.map +1 -0
- package/dist/__tests__/index-exports.unit.test.js +124 -0
- package/dist/__tests__/index-exports.unit.test.js.map +1 -0
- package/dist/__tests__/registry-executor.integration.test.js +12 -9
- package/dist/__tests__/registry-executor.integration.test.js.map +1 -1
- package/dist/aggregation/__tests__/aggregators.unit.test.d.ts +7 -0
- package/dist/aggregation/__tests__/aggregators.unit.test.d.ts.map +1 -0
- package/dist/aggregation/__tests__/aggregators.unit.test.js +350 -0
- package/dist/aggregation/__tests__/aggregators.unit.test.js.map +1 -0
- package/dist/aggregation/__tests__/pipeline.unit.test.d.ts +7 -0
- package/dist/aggregation/__tests__/pipeline.unit.test.d.ts.map +1 -0
- package/dist/aggregation/__tests__/pipeline.unit.test.js +213 -0
- package/dist/aggregation/__tests__/pipeline.unit.test.js.map +1 -0
- package/dist/aggregation/aggregators.d.ts +9 -0
- package/dist/aggregation/aggregators.d.ts.map +1 -1
- package/dist/aggregation/aggregators.js +1 -1
- package/dist/aggregation/aggregators.js.map +1 -1
- package/dist/aggregation/index.d.ts +1 -1
- package/dist/aggregation/index.d.ts.map +1 -1
- package/dist/aggregation/index.js +1 -1
- package/dist/aggregation/index.js.map +1 -1
- package/dist/aggregation/pipeline.d.ts.map +1 -1
- package/dist/aggregation/pipeline.js +40 -3
- package/dist/aggregation/pipeline.js.map +1 -1
- package/dist/claims/index.d.ts +6 -3
- package/dist/claims/index.d.ts.map +1 -1
- package/dist/claims/index.js +6 -3
- package/dist/claims/index.js.map +1 -1
- package/dist/cli/__tests__/aggregate.command.unit.test.d.ts +7 -0
- package/dist/cli/__tests__/aggregate.command.unit.test.d.ts.map +1 -0
- package/dist/cli/__tests__/aggregate.command.unit.test.js +399 -0
- package/dist/cli/__tests__/aggregate.command.unit.test.js.map +1 -0
- package/dist/cli/__tests__/binary-sut.integration.test.d.ts +8 -0
- package/dist/cli/__tests__/binary-sut.integration.test.d.ts.map +1 -0
- package/dist/cli/__tests__/binary-sut.integration.test.js +165 -0
- package/dist/cli/__tests__/binary-sut.integration.test.js.map +1 -0
- package/dist/cli/__tests__/commands.unit.test.d.ts +10 -0
- package/dist/cli/__tests__/commands.unit.test.d.ts.map +1 -0
- package/dist/cli/__tests__/commands.unit.test.js +217 -0
- package/dist/cli/__tests__/commands.unit.test.js.map +1 -0
- package/dist/cli/__tests__/config-loader.unit.test.d.ts +7 -0
- package/dist/cli/__tests__/config-loader.unit.test.d.ts.map +1 -0
- package/dist/cli/__tests__/config-loader.unit.test.js +611 -0
- package/dist/cli/__tests__/config-loader.unit.test.js.map +1 -0
- package/dist/cli/__tests__/index.unit.test.d.ts +10 -0
- package/dist/cli/__tests__/index.unit.test.d.ts.map +1 -0
- package/dist/cli/__tests__/index.unit.test.js +65 -0
- package/dist/cli/__tests__/index.unit.test.js.map +1 -0
- package/dist/cli/__tests__/logger.unit.test.d.ts +11 -0
- package/dist/cli/__tests__/logger.unit.test.d.ts.map +1 -0
- package/dist/cli/__tests__/logger.unit.test.js +180 -0
- package/dist/cli/__tests__/logger.unit.test.js.map +1 -0
- package/dist/cli/__tests__/module-loader.unit.test.d.ts +11 -0
- package/dist/cli/__tests__/module-loader.unit.test.d.ts.map +1 -0
- package/dist/cli/__tests__/module-loader.unit.test.js +262 -0
- package/dist/cli/__tests__/module-loader.unit.test.js.map +1 -0
- package/dist/cli/__tests__/output-writer.unit.test.d.ts +10 -0
- package/dist/cli/__tests__/output-writer.unit.test.d.ts.map +1 -0
- package/dist/cli/__tests__/output-writer.unit.test.js +216 -0
- package/dist/cli/__tests__/output-writer.unit.test.js.map +1 -0
- package/dist/cli/__tests__/plan.command.unit.test.d.ts +7 -0
- package/dist/cli/__tests__/plan.command.unit.test.d.ts.map +1 -0
- package/dist/cli/__tests__/plan.command.unit.test.js +289 -0
- package/dist/cli/__tests__/plan.command.unit.test.js.map +1 -0
- package/dist/cli/__tests__/run.command.unit.test.d.ts +7 -0
- package/dist/cli/__tests__/run.command.unit.test.d.ts.map +1 -0
- package/dist/cli/__tests__/run.command.unit.test.js +422 -0
- package/dist/cli/__tests__/run.command.unit.test.js.map +1 -0
- package/dist/cli/__tests__/validate.command.unit.test.d.ts +7 -0
- package/dist/cli/__tests__/validate.command.unit.test.d.ts.map +1 -0
- package/dist/cli/__tests__/validate.command.unit.test.js +226 -0
- package/dist/cli/__tests__/validate.command.unit.test.js.map +1 -0
- package/dist/cli/command-deps.d.ts +137 -0
- package/dist/cli/command-deps.d.ts.map +1 -0
- package/dist/cli/command-deps.js +7 -0
- package/dist/cli/command-deps.js.map +1 -0
- package/dist/cli/commands/aggregate.d.ts +35 -0
- package/dist/cli/commands/aggregate.d.ts.map +1 -0
- package/dist/cli/commands/aggregate.js +124 -0
- package/dist/cli/commands/aggregate.js.map +1 -0
- package/dist/cli/commands/evaluate.d.ts +41 -0
- package/dist/cli/commands/evaluate.d.ts.map +1 -0
- package/dist/cli/commands/evaluate.js +287 -0
- package/dist/cli/commands/evaluate.js.map +1 -0
- package/dist/cli/commands/plan.d.ts +36 -0
- package/dist/cli/commands/plan.d.ts.map +1 -0
- package/dist/cli/commands/plan.js +109 -0
- package/dist/cli/commands/plan.js.map +1 -0
- package/dist/cli/commands/run.d.ts +33 -0
- package/dist/cli/commands/run.d.ts.map +1 -0
- package/dist/cli/commands/run.js +277 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +27 -0
- package/dist/cli/commands/validate.d.ts.map +1 -0
- package/dist/cli/commands/validate.js +88 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/config-loader.d.ts +30 -0
- package/dist/cli/config-loader.d.ts.map +1 -0
- package/dist/cli/config-loader.js +181 -0
- package/dist/cli/config-loader.js.map +1 -0
- package/dist/cli/index.d.ts +27 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +60 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/logger.d.ts +75 -0
- package/dist/cli/logger.d.ts.map +1 -0
- package/dist/cli/logger.js +131 -0
- package/dist/cli/logger.js.map +1 -0
- package/dist/cli/module-loader.d.ts +68 -0
- package/dist/cli/module-loader.d.ts.map +1 -0
- package/dist/cli/module-loader.js +134 -0
- package/dist/cli/module-loader.js.map +1 -0
- package/dist/cli/output-writer.d.ts +51 -0
- package/dist/cli/output-writer.d.ts.map +1 -0
- package/dist/cli/output-writer.js +65 -0
- package/dist/cli/output-writer.js.map +1 -0
- package/dist/cli/types.d.ts +193 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +7 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/collector/__tests__/result-collector.unit.test.d.ts +7 -0
- package/dist/collector/__tests__/result-collector.unit.test.d.ts.map +1 -0
- package/dist/collector/__tests__/result-collector.unit.test.js +1021 -0
- package/dist/collector/__tests__/result-collector.unit.test.js.map +1 -0
- package/dist/collector/__tests__/schema.unit.test.d.ts +7 -0
- package/dist/collector/__tests__/schema.unit.test.d.ts.map +1 -0
- package/dist/collector/__tests__/schema.unit.test.js +360 -0
- package/dist/collector/__tests__/schema.unit.test.js.map +1 -0
- package/dist/evaluators/claims-evaluator.d.ts +87 -0
- package/dist/evaluators/claims-evaluator.d.ts.map +1 -0
- package/dist/evaluators/claims-evaluator.js +289 -0
- package/dist/evaluators/claims-evaluator.js.map +1 -0
- package/dist/evaluators/exploratory-evaluator.d.ts +136 -0
- package/dist/evaluators/exploratory-evaluator.d.ts.map +1 -0
- package/dist/evaluators/exploratory-evaluator.js +545 -0
- package/dist/evaluators/exploratory-evaluator.js.map +1 -0
- package/dist/evaluators/index.d.ts +13 -0
- package/dist/evaluators/index.d.ts.map +1 -0
- package/dist/evaluators/index.js +14 -0
- package/dist/evaluators/index.js.map +1 -0
- package/dist/evaluators/metrics-evaluator.d.ts +114 -0
- package/dist/evaluators/metrics-evaluator.d.ts.map +1 -0
- package/dist/evaluators/metrics-evaluator.js +433 -0
- package/dist/evaluators/metrics-evaluator.js.map +1 -0
- package/dist/evaluators/registry.d.ts +106 -0
- package/dist/evaluators/registry.d.ts.map +1 -0
- package/dist/evaluators/registry.js +148 -0
- package/dist/evaluators/registry.js.map +1 -0
- package/dist/evaluators/robustness-evaluator.d.ts +57 -0
- package/dist/evaluators/robustness-evaluator.d.ts.map +1 -0
- package/dist/evaluators/robustness-evaluator.js +186 -0
- package/dist/evaluators/robustness-evaluator.js.map +1 -0
- package/dist/executor/__tests__/binary-sut.unit.test.d.ts +8 -0
- package/dist/executor/__tests__/binary-sut.unit.test.d.ts.map +1 -0
- package/dist/executor/__tests__/binary-sut.unit.test.js +313 -0
- package/dist/executor/__tests__/binary-sut.unit.test.js.map +1 -0
- package/dist/executor/__tests__/checkpoint-manager.unit.test.js +83 -1
- package/dist/executor/__tests__/checkpoint-manager.unit.test.js.map +1 -1
- package/dist/executor/__tests__/checkpoint-merge-bug.diagnostic.test.d.ts +3 -6
- package/dist/executor/__tests__/checkpoint-merge-bug.diagnostic.test.d.ts.map +1 -1
- package/dist/executor/__tests__/checkpoint-merge-bug.diagnostic.test.js +428 -159
- package/dist/executor/__tests__/checkpoint-merge-bug.diagnostic.test.js.map +1 -1
- package/dist/executor/__tests__/checkpoint-storage.unit.test.js +148 -1
- package/dist/executor/__tests__/checkpoint-storage.unit.test.js.map +1 -1
- package/dist/executor/__tests__/executor.unit.test.js +123 -8
- package/dist/executor/__tests__/executor.unit.test.js.map +1 -1
- package/dist/executor/__tests__/memory-monitor.unit.test.d.ts +7 -0
- package/dist/executor/__tests__/memory-monitor.unit.test.d.ts.map +1 -0
- package/dist/executor/__tests__/memory-monitor.unit.test.js +285 -0
- package/dist/executor/__tests__/memory-monitor.unit.test.js.map +1 -0
- package/dist/executor/__tests__/parallel-executor.unit.test.d.ts +2 -1
- package/dist/executor/__tests__/parallel-executor.unit.test.d.ts.map +1 -1
- package/dist/executor/__tests__/parallel-executor.unit.test.js +426 -156
- package/dist/executor/__tests__/parallel-executor.unit.test.js.map +1 -1
- package/dist/executor/__tests__/resource-calculator.unit.test.d.ts +10 -0
- package/dist/executor/__tests__/resource-calculator.unit.test.d.ts.map +1 -0
- package/dist/executor/__tests__/resource-calculator.unit.test.js +104 -0
- package/dist/executor/__tests__/resource-calculator.unit.test.js.map +1 -0
- package/dist/executor/__tests__/run-id.unit.test.d.ts +8 -0
- package/dist/executor/__tests__/run-id.unit.test.d.ts.map +1 -0
- package/dist/executor/__tests__/run-id.unit.test.js +156 -0
- package/dist/executor/__tests__/run-id.unit.test.js.map +1 -0
- package/dist/executor/__tests__/worker-entry.integration.test.d.ts +24 -0
- package/dist/executor/__tests__/worker-entry.integration.test.d.ts.map +1 -0
- package/dist/executor/__tests__/worker-entry.integration.test.js +82 -0
- package/dist/executor/__tests__/worker-entry.integration.test.js.map +1 -0
- package/dist/executor/__tests__/worker-entry.unit.test.d.ts +7 -0
- package/dist/executor/__tests__/worker-entry.unit.test.d.ts.map +1 -0
- package/dist/executor/__tests__/worker-entry.unit.test.js +364 -0
- package/dist/executor/__tests__/worker-entry.unit.test.js.map +1 -0
- package/dist/executor/__tests__/worker-threads-executor.unit.test.d.ts +8 -0
- package/dist/executor/__tests__/worker-threads-executor.unit.test.d.ts.map +1 -0
- package/dist/executor/__tests__/worker-threads-executor.unit.test.js +276 -0
- package/dist/executor/__tests__/worker-threads-executor.unit.test.js.map +1 -0
- package/dist/executor/binary-sut.d.ts +105 -0
- package/dist/executor/binary-sut.d.ts.map +1 -0
- package/dist/executor/binary-sut.js +174 -0
- package/dist/executor/binary-sut.js.map +1 -0
- package/dist/executor/checkpoint-storage.d.ts.map +1 -1
- package/dist/executor/checkpoint-storage.js +6 -4
- package/dist/executor/checkpoint-storage.js.map +1 -1
- package/dist/executor/executor.d.ts +28 -0
- package/dist/executor/executor.d.ts.map +1 -1
- package/dist/executor/executor.js +85 -24
- package/dist/executor/executor.js.map +1 -1
- package/dist/executor/index.d.ts +4 -0
- package/dist/executor/index.d.ts.map +1 -1
- package/dist/executor/index.js +4 -0
- package/dist/executor/index.js.map +1 -1
- package/dist/executor/parallel-executor.d.ts +186 -0
- package/dist/executor/parallel-executor.d.ts.map +1 -1
- package/dist/executor/parallel-executor.js +218 -83
- package/dist/executor/parallel-executor.js.map +1 -1
- package/dist/executor/resource-calculator.d.ts +49 -0
- package/dist/executor/resource-calculator.d.ts.map +1 -0
- package/dist/executor/resource-calculator.js +129 -0
- package/dist/executor/resource-calculator.js.map +1 -0
- package/dist/executor/run-id.d.ts.map +1 -1
- package/dist/executor/run-id.js +8 -1
- package/dist/executor/run-id.js.map +1 -1
- package/dist/executor/worker-entry.d.ts +2 -0
- package/dist/executor/worker-entry.d.ts.map +1 -1
- package/dist/executor/worker-entry.js +46 -55
- package/dist/executor/worker-entry.js.map +1 -1
- package/dist/executor/worker-executor.d.ts +257 -0
- package/dist/executor/worker-executor.d.ts.map +1 -0
- package/dist/executor/worker-executor.js +308 -0
- package/dist/executor/worker-executor.js.map +1 -0
- package/dist/executor/worker-threads-executor.d.ts +245 -0
- package/dist/executor/worker-threads-executor.d.ts.map +1 -0
- package/dist/executor/worker-threads-executor.js +332 -0
- package/dist/executor/worker-threads-executor.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/renderers/latex-renderer.d.ts +60 -0
- package/dist/renderers/latex-renderer.d.ts.map +1 -1
- package/dist/renderers/latex-renderer.js +299 -0
- package/dist/renderers/latex-renderer.js.map +1 -1
- package/dist/renderers/types.d.ts +9 -0
- package/dist/renderers/types.d.ts.map +1 -1
- package/dist/renderers/types.js.map +1 -1
- package/dist/robustness/__tests__/perturbations.unit.test.d.ts +11 -0
- package/dist/robustness/__tests__/perturbations.unit.test.d.ts.map +1 -0
- package/dist/robustness/__tests__/perturbations.unit.test.js +284 -0
- package/dist/robustness/__tests__/perturbations.unit.test.js.map +1 -0
- package/dist/robustness/index.d.ts +5 -2
- package/dist/robustness/index.d.ts.map +1 -1
- package/dist/robustness/index.js +4 -2
- package/dist/robustness/index.js.map +1 -1
- package/dist/statistical/__tests__/mann-whitney-u.unit.test.d.ts +7 -0
- package/dist/statistical/__tests__/mann-whitney-u.unit.test.d.ts.map +1 -0
- package/dist/statistical/__tests__/mann-whitney-u.unit.test.js +185 -0
- package/dist/statistical/__tests__/mann-whitney-u.unit.test.js.map +1 -0
- package/dist/types/evaluator.d.ts +449 -0
- package/dist/types/evaluator.d.ts.map +1 -0
- package/dist/types/evaluator.js +9 -0
- package/dist/types/evaluator.js.map +1 -0
- package/dist/types/result.d.ts +2 -0
- package/dist/types/result.d.ts.map +1 -1
- package/package.json +8 -1
- package/dist/claims/evaluator.d.ts +0 -33
- package/dist/claims/evaluator.d.ts.map +0 -1
- package/dist/claims/evaluator.js +0 -174
- package/dist/claims/evaluator.js.map +0 -1
- package/dist/robustness/analyzer.d.ts +0 -61
- package/dist/robustness/analyzer.d.ts.map +0 -1
- package/dist/robustness/analyzer.js +0 -191
- package/dist/robustness/analyzer.js.map +0 -1
|
@@ -1,21 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Checkpoint Integration Tests
|
|
3
3
|
*
|
|
4
|
-
* Tests
|
|
5
|
-
*
|
|
6
|
-
* - Workers report "No checkpoint"
|
|
7
|
-
* - Workers report "Total runs: 0, From checkpoint: 0, New this run: 0"
|
|
8
|
-
* - Main checkpoint has 123/132 runs but workers start fresh
|
|
4
|
+
* Tests checkpoint save/load functionality, shard merging,
|
|
5
|
+
* and config hash validation.
|
|
9
6
|
*/
|
|
10
7
|
import { createHash, randomBytes } from "node:crypto";
|
|
11
8
|
import { rmSync } from "node:fs";
|
|
12
9
|
import { tmpdir } from "node:os";
|
|
13
10
|
import { join } from "node:path";
|
|
14
|
-
import { strict as assert } from "node:assert";
|
|
15
11
|
import { afterEach, beforeEach, describe, it } from "node:test";
|
|
12
|
+
import { strict as assert } from "node:assert";
|
|
16
13
|
import { CheckpointManager } from "../checkpoint-manager.js";
|
|
17
14
|
import { FileStorage } from "../checkpoint-storage.js";
|
|
18
|
-
describe("Checkpoint Integration
|
|
15
|
+
describe("Checkpoint Integration", () => {
|
|
19
16
|
let testDir;
|
|
20
17
|
let checkpoint;
|
|
21
18
|
let checkpointPath;
|
|
@@ -27,164 +24,437 @@ describe("Checkpoint Integration Bug Diagnostics", () => {
|
|
|
27
24
|
afterEach(() => {
|
|
28
25
|
rmSync(testDir, { recursive: true, force: true });
|
|
29
26
|
});
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
27
|
+
describe("save and load", () => {
|
|
28
|
+
it("should save and load single run", async () => {
|
|
29
|
+
const result = {
|
|
30
|
+
run: {
|
|
31
|
+
runId: "test-run-001",
|
|
32
|
+
sut: "test-sut",
|
|
33
|
+
sutRole: "primary",
|
|
34
|
+
sutVersion: "1.0.0",
|
|
35
|
+
caseId: "case-001",
|
|
36
|
+
caseClass: "test-class",
|
|
37
|
+
seed: 42,
|
|
38
|
+
repetition: 0,
|
|
39
|
+
},
|
|
40
|
+
correctness: {
|
|
41
|
+
expectedExists: false,
|
|
42
|
+
producedOutput: true,
|
|
43
|
+
valid: true,
|
|
44
|
+
matchesExpected: null,
|
|
45
|
+
},
|
|
46
|
+
outputs: { summary: {} },
|
|
47
|
+
metrics: { numeric: { test: 1 } },
|
|
48
|
+
provenance: {
|
|
49
|
+
runtime: { platform: "linux", arch: "x64", nodeVersion: "v22.0.0" },
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
// Save
|
|
53
|
+
await checkpoint.saveIncremental(result);
|
|
54
|
+
// Load fresh checkpoint
|
|
55
|
+
const fresh = new CheckpointManager({ storage: new FileStorage(checkpointPath) });
|
|
56
|
+
await fresh.load();
|
|
57
|
+
const results = fresh.getResults();
|
|
58
|
+
assert.strictEqual(results.length, 1);
|
|
59
|
+
assert.strictEqual(results[0]?.run.runId, "test-run-001");
|
|
60
|
+
});
|
|
61
|
+
it("should save and load multiple runs", async () => {
|
|
62
|
+
const results = [];
|
|
63
|
+
for (let i = 0; i < 5; i++) {
|
|
64
|
+
const result = {
|
|
65
|
+
run: {
|
|
66
|
+
runId: `test-run-${i}`,
|
|
67
|
+
sut: "test-sut",
|
|
68
|
+
sutRole: "primary",
|
|
69
|
+
sutVersion: "1.0.0",
|
|
70
|
+
caseId: "case-001",
|
|
71
|
+
caseClass: "test-class",
|
|
72
|
+
seed: 42,
|
|
73
|
+
repetition: i,
|
|
74
|
+
},
|
|
75
|
+
correctness: {
|
|
76
|
+
expectedExists: false,
|
|
77
|
+
producedOutput: true,
|
|
78
|
+
valid: true,
|
|
79
|
+
matchesExpected: null,
|
|
80
|
+
},
|
|
81
|
+
outputs: { summary: {} },
|
|
82
|
+
metrics: { numeric: { test: i } },
|
|
83
|
+
provenance: {
|
|
84
|
+
runtime: { platform: "linux", arch: "x64", nodeVersion: "v22.0.0" },
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
results.push(result);
|
|
40
88
|
await checkpoint.saveIncremental(result);
|
|
41
|
-
}
|
|
89
|
+
}
|
|
90
|
+
// Load fresh checkpoint
|
|
91
|
+
const fresh = new CheckpointManager({ storage: new FileStorage(checkpointPath) });
|
|
92
|
+
await fresh.load();
|
|
93
|
+
const loaded = fresh.getResults();
|
|
94
|
+
assert.strictEqual(loaded.length, 5);
|
|
95
|
+
for (let i = 0; i < 5; i++) {
|
|
96
|
+
assert.strictEqual(loaded[i]?.run.runId, `test-run-${i}`);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
it("should persist results to file", async () => {
|
|
100
|
+
const result = {
|
|
101
|
+
run: {
|
|
102
|
+
runId: "test-run-001",
|
|
103
|
+
sut: "test-sut",
|
|
104
|
+
sutRole: "primary",
|
|
105
|
+
sutVersion: "1.0.0",
|
|
106
|
+
caseId: "case-001",
|
|
107
|
+
caseClass: "test-class",
|
|
108
|
+
seed: 42,
|
|
109
|
+
repetition: 0,
|
|
110
|
+
},
|
|
111
|
+
correctness: {
|
|
112
|
+
expectedExists: false,
|
|
113
|
+
producedOutput: true,
|
|
114
|
+
valid: true,
|
|
115
|
+
matchesExpected: null,
|
|
116
|
+
},
|
|
117
|
+
outputs: { summary: {} },
|
|
118
|
+
metrics: { numeric: { test: 1 } },
|
|
119
|
+
provenance: {
|
|
120
|
+
runtime: { platform: "linux", arch: "x64", nodeVersion: "v22.0.0" },
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
await checkpoint.saveIncremental(result);
|
|
124
|
+
// Verify file exists
|
|
125
|
+
const fresh = new CheckpointManager({ storage: new FileStorage(checkpointPath) });
|
|
126
|
+
await fresh.load();
|
|
127
|
+
assert.strictEqual(fresh.getResults().length, 1);
|
|
42
128
|
});
|
|
43
|
-
// Execute
|
|
44
|
-
const summary = await executor.execute([sut], [testCase], () => ({}));
|
|
45
|
-
// Verify
|
|
46
|
-
assert.strictEqual(summary.successfulRuns, 1);
|
|
47
|
-
const results = checkpoint.getResults();
|
|
48
|
-
assert.strictEqual(results.length, 1);
|
|
49
|
-
// Load fresh checkpoint
|
|
50
|
-
const fresh = new CheckpointManager({ storage: new FileStorage(checkpointPath) });
|
|
51
|
-
await fresh.load();
|
|
52
|
-
assert.strictEqual(fresh.getResults().length, 1);
|
|
53
|
-
});
|
|
54
|
-
it("diagnostic-2: should detect config hash mismatch", async () => {
|
|
55
|
-
// Save with one config
|
|
56
|
-
const result = {
|
|
57
|
-
run: {
|
|
58
|
-
runId: "test-run-001",
|
|
59
|
-
sut: "test-sut",
|
|
60
|
-
sutRole: "primary",
|
|
61
|
-
sutVersion: "1.0.0",
|
|
62
|
-
caseId: "case-001",
|
|
63
|
-
caseClass: "test-class",
|
|
64
|
-
seed: 42,
|
|
65
|
-
repetition: 0,
|
|
66
|
-
},
|
|
67
|
-
correctness: {
|
|
68
|
-
expectedExists: false,
|
|
69
|
-
producedOutput: true,
|
|
70
|
-
valid: true,
|
|
71
|
-
matchesExpected: null,
|
|
72
|
-
},
|
|
73
|
-
outputs: { summary: {} },
|
|
74
|
-
metrics: { numeric: { test: 1 } },
|
|
75
|
-
provenance: {
|
|
76
|
-
runtime: { platform: "linux", arch: "x64", nodeVersion: "v22.0.0" },
|
|
77
|
-
},
|
|
78
|
-
};
|
|
79
|
-
await checkpoint.saveIncremental(result);
|
|
80
|
-
// Try to load with different config
|
|
81
|
-
const fresh = new CheckpointManager({ storage: new FileStorage(checkpointPath) });
|
|
82
|
-
await fresh.load();
|
|
83
|
-
// Check if stale with different config
|
|
84
|
-
const isStale = fresh.isStale([createMockSut()], [createMockCase("case-001")], {
|
|
85
|
-
repetitions: 2, // Different from original (1)
|
|
86
|
-
seedBase: 42,
|
|
87
|
-
timeoutMs: 5000,
|
|
88
|
-
collectProvenance: false,
|
|
89
|
-
}, 1);
|
|
90
|
-
assert.strictEqual(isStale, true);
|
|
91
129
|
});
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
130
|
+
describe("config hash", () => {
|
|
131
|
+
it("should detect config hash mismatch", async () => {
|
|
132
|
+
const result = {
|
|
133
|
+
run: {
|
|
134
|
+
runId: "test-run-001",
|
|
135
|
+
sut: "test-sut",
|
|
136
|
+
sutRole: "primary",
|
|
137
|
+
sutVersion: "1.0.0",
|
|
138
|
+
caseId: "case-001",
|
|
139
|
+
caseClass: "test-class",
|
|
140
|
+
seed: 42,
|
|
141
|
+
repetition: 0,
|
|
142
|
+
},
|
|
143
|
+
correctness: {
|
|
144
|
+
expectedExists: false,
|
|
145
|
+
producedOutput: true,
|
|
146
|
+
valid: true,
|
|
147
|
+
matchesExpected: null,
|
|
148
|
+
},
|
|
149
|
+
outputs: { summary: {} },
|
|
150
|
+
metrics: { numeric: { test: 1 } },
|
|
151
|
+
provenance: {
|
|
152
|
+
runtime: { platform: "linux", arch: "x64", nodeVersion: "v22.0.0" },
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
await checkpoint.saveIncremental(result);
|
|
156
|
+
// Try to load with different config
|
|
157
|
+
const fresh = new CheckpointManager({ storage: new FileStorage(checkpointPath) });
|
|
158
|
+
await fresh.load();
|
|
159
|
+
// Check if stale with different config
|
|
160
|
+
const isStale = fresh.isStale([createMockSut()], [createMockCase("case-001")], {
|
|
161
|
+
repetitions: 2, // Different from original (1)
|
|
162
|
+
seedBase: 42,
|
|
163
|
+
timeoutMs: 5000,
|
|
164
|
+
collectProvenance: false,
|
|
165
|
+
}, 1);
|
|
166
|
+
assert.strictEqual(isStale, true);
|
|
167
|
+
});
|
|
168
|
+
it("should not be stale when config matches", async () => {
|
|
169
|
+
const result = {
|
|
170
|
+
run: {
|
|
171
|
+
runId: "test-run-001",
|
|
172
|
+
sut: "test-sut",
|
|
173
|
+
sutRole: "primary",
|
|
174
|
+
sutVersion: "1.0.0",
|
|
175
|
+
caseId: "case-001",
|
|
176
|
+
caseClass: "test-class",
|
|
177
|
+
seed: 42,
|
|
178
|
+
repetition: 0,
|
|
179
|
+
},
|
|
180
|
+
correctness: {
|
|
181
|
+
expectedExists: false,
|
|
182
|
+
producedOutput: true,
|
|
183
|
+
valid: true,
|
|
184
|
+
matchesExpected: null,
|
|
185
|
+
},
|
|
186
|
+
outputs: { summary: {} },
|
|
187
|
+
metrics: { numeric: { test: 1 } },
|
|
188
|
+
provenance: {
|
|
189
|
+
runtime: { platform: "linux", arch: "x64", nodeVersion: "v22.0.0" },
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
// Initialize with proper config hash first
|
|
193
|
+
checkpoint.initializeEmpty([createMockSut()], [createMockCase("case-001")], {
|
|
194
|
+
repetitions: 1,
|
|
195
|
+
seedBase: 42,
|
|
196
|
+
timeoutMs: 5000,
|
|
197
|
+
collectProvenance: false,
|
|
198
|
+
}, 1);
|
|
199
|
+
// Save the initialized checkpoint to persist the config hash
|
|
200
|
+
await checkpoint.save();
|
|
201
|
+
await checkpoint.saveIncremental(result);
|
|
202
|
+
const fresh = new CheckpointManager({ storage: new FileStorage(checkpointPath) });
|
|
203
|
+
await fresh.load();
|
|
204
|
+
// Same config should not be stale
|
|
205
|
+
const isStale = fresh.isStale([createMockSut()], [createMockCase("case-001")], {
|
|
206
|
+
repetitions: 1,
|
|
207
|
+
seedBase: 42,
|
|
208
|
+
timeoutMs: 5000,
|
|
209
|
+
collectProvenance: false,
|
|
210
|
+
}, 1);
|
|
211
|
+
assert.strictEqual(isStale, false);
|
|
105
212
|
});
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
213
|
+
it("should include all executor config properties in hash", async () => {
|
|
214
|
+
const config1 = {
|
|
215
|
+
continueOnError: true,
|
|
216
|
+
repetitions: 1,
|
|
217
|
+
seedBase: 42,
|
|
218
|
+
timeoutMs: 300_000,
|
|
219
|
+
collectProvenance: true,
|
|
220
|
+
};
|
|
221
|
+
const config2 = {
|
|
222
|
+
...config1,
|
|
223
|
+
concurrency: 12, // Additional property
|
|
224
|
+
};
|
|
225
|
+
const hash1 = createHash("sha256")
|
|
226
|
+
.update(JSON.stringify(config1, Object.keys(config1).sort()))
|
|
227
|
+
.digest("hex");
|
|
228
|
+
const hash2 = createHash("sha256")
|
|
229
|
+
.update(JSON.stringify(config2, Object.keys(config2).sort()))
|
|
230
|
+
.digest("hex");
|
|
231
|
+
// They should be different because concurrency is different
|
|
232
|
+
assert.notStrictEqual(hash1, hash2);
|
|
113
233
|
});
|
|
114
|
-
// Find shards
|
|
115
|
-
const shards = await FileStorage.findShards(testDir);
|
|
116
|
-
assert.strictEqual(shards.length, 2);
|
|
117
|
-
assert.ok(shards.includes(shard1));
|
|
118
|
-
assert.ok(shards.includes(shard2));
|
|
119
234
|
});
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
235
|
+
describe("shard operations", () => {
|
|
236
|
+
it("should find worker shards", async () => {
|
|
237
|
+
// Create mock worker shards
|
|
238
|
+
const shard1 = join(testDir, "checkpoint-worker-00.json");
|
|
239
|
+
const shard2 = join(testDir, "checkpoint-worker-01.json");
|
|
240
|
+
const storage1 = new FileStorage(shard1);
|
|
241
|
+
const storage2 = new FileStorage(shard2);
|
|
242
|
+
await storage1.save({
|
|
243
|
+
configHash: "test-hash",
|
|
244
|
+
createdAt: new Date().toISOString(),
|
|
245
|
+
updatedAt: new Date().toISOString(),
|
|
246
|
+
completedRunIds: ["run-001", "run-002"],
|
|
247
|
+
results: {},
|
|
248
|
+
totalPlanned: 0,
|
|
249
|
+
});
|
|
250
|
+
await storage2.save({
|
|
251
|
+
configHash: "test-hash",
|
|
252
|
+
createdAt: new Date().toISOString(),
|
|
253
|
+
updatedAt: new Date().toISOString(),
|
|
254
|
+
completedRunIds: ["run-003", "run-004"],
|
|
255
|
+
results: {},
|
|
256
|
+
totalPlanned: 0,
|
|
257
|
+
});
|
|
258
|
+
// Find shards
|
|
259
|
+
const shards = await FileStorage.findShards(testDir);
|
|
260
|
+
assert.strictEqual(shards.length, 2);
|
|
261
|
+
assert.ok(shards.includes(shard1));
|
|
262
|
+
assert.ok(shards.includes(shard2));
|
|
263
|
+
});
|
|
264
|
+
it("should return empty array when no shards exist", async () => {
|
|
265
|
+
const shards = await FileStorage.findShards(testDir);
|
|
266
|
+
assert.deepStrictEqual(shards, []);
|
|
267
|
+
});
|
|
268
|
+
it("should filter shards by config hash", async () => {
|
|
269
|
+
const shard1 = join(testDir, "checkpoint-worker-00.json");
|
|
270
|
+
const shard2 = join(testDir, "checkpoint-worker-01.json");
|
|
271
|
+
const storage1 = new FileStorage(shard1);
|
|
272
|
+
const storage2 = new FileStorage(shard2);
|
|
273
|
+
await storage1.save({
|
|
274
|
+
configHash: "hash-1",
|
|
275
|
+
createdAt: new Date().toISOString(),
|
|
276
|
+
updatedAt: new Date().toISOString(),
|
|
277
|
+
completedRunIds: ["run-001"],
|
|
278
|
+
results: {},
|
|
279
|
+
totalPlanned: 0,
|
|
280
|
+
});
|
|
281
|
+
await storage2.save({
|
|
282
|
+
configHash: "hash-2",
|
|
283
|
+
createdAt: new Date().toISOString(),
|
|
284
|
+
updatedAt: new Date().toISOString(),
|
|
285
|
+
completedRunIds: ["run-002"],
|
|
286
|
+
results: {},
|
|
287
|
+
totalPlanned: 0,
|
|
288
|
+
});
|
|
289
|
+
// Find shards with specific hash
|
|
290
|
+
const shards = await FileStorage.findShards(testDir);
|
|
291
|
+
assert.strictEqual(shards.length, 2);
|
|
292
|
+
});
|
|
293
|
+
it("should merge shards without duplicates", async () => {
|
|
294
|
+
// Create main checkpoint
|
|
295
|
+
const result1 = {
|
|
296
|
+
run: {
|
|
297
|
+
runId: "run-001",
|
|
298
|
+
sut: "sut-1",
|
|
299
|
+
sutRole: "primary",
|
|
300
|
+
sutVersion: "1.0.0",
|
|
301
|
+
caseId: "case-001",
|
|
302
|
+
caseClass: "test-class",
|
|
303
|
+
seed: 42,
|
|
304
|
+
repetition: 0,
|
|
305
|
+
},
|
|
306
|
+
correctness: {
|
|
307
|
+
expectedExists: false,
|
|
308
|
+
producedOutput: true,
|
|
309
|
+
valid: true,
|
|
310
|
+
matchesExpected: null,
|
|
311
|
+
},
|
|
312
|
+
outputs: { summary: {} },
|
|
313
|
+
metrics: { numeric: { test: 1 } },
|
|
314
|
+
provenance: {
|
|
315
|
+
runtime: { platform: "linux", arch: "x64", nodeVersion: "v22.0.0" },
|
|
316
|
+
},
|
|
317
|
+
};
|
|
318
|
+
await checkpoint.saveIncremental(result1);
|
|
319
|
+
// Create worker shard with overlapping run
|
|
320
|
+
const workerStorage = new FileStorage(join(testDir, "checkpoint-worker-00.json"));
|
|
321
|
+
await workerStorage.save({
|
|
322
|
+
configHash: "test-hash",
|
|
323
|
+
createdAt: new Date().toISOString(),
|
|
324
|
+
updatedAt: new Date().toISOString(),
|
|
325
|
+
completedRunIds: ["run-001", "run-002"], // run-001 overlaps with main
|
|
326
|
+
results: {},
|
|
327
|
+
totalPlanned: 0,
|
|
328
|
+
});
|
|
329
|
+
// Merge
|
|
330
|
+
const shards = await FileStorage.findShards(testDir);
|
|
331
|
+
const merged = await checkpoint.mergeShards(shards);
|
|
332
|
+
// Verify no duplicates
|
|
333
|
+
const uniqueIds = new Set(merged.completedRunIds);
|
|
334
|
+
assert.strictEqual(uniqueIds.size, 2); // run-001, run-002 (no duplicates)
|
|
335
|
+
assert.strictEqual(merged.completedRunIds.length, 2);
|
|
336
|
+
});
|
|
337
|
+
it("should merge all completed run IDs from shards", async () => {
|
|
338
|
+
// Save main checkpoint with some runs
|
|
339
|
+
const result1 = {
|
|
340
|
+
run: {
|
|
341
|
+
runId: "run-001",
|
|
342
|
+
sut: "sut-1",
|
|
343
|
+
sutRole: "primary",
|
|
344
|
+
sutVersion: "1.0.0",
|
|
345
|
+
caseId: "case-001",
|
|
346
|
+
seed: 42,
|
|
347
|
+
repetition: 0,
|
|
348
|
+
},
|
|
349
|
+
correctness: {
|
|
350
|
+
expectedExists: false,
|
|
351
|
+
producedOutput: true,
|
|
352
|
+
valid: true,
|
|
353
|
+
matchesExpected: null,
|
|
354
|
+
},
|
|
355
|
+
outputs: { summary: {} },
|
|
356
|
+
metrics: { numeric: { test: 1 } },
|
|
357
|
+
provenance: {
|
|
358
|
+
runtime: { platform: "linux", arch: "x64", nodeVersion: "v22.0.0" },
|
|
359
|
+
},
|
|
360
|
+
};
|
|
361
|
+
await checkpoint.saveIncremental(result1);
|
|
362
|
+
// Reload to update in-memory data (saveIncremental only writes to file)
|
|
363
|
+
await checkpoint.load();
|
|
364
|
+
// Create two worker shards with different runs
|
|
365
|
+
const shard1 = join(testDir, "checkpoint-worker-00.json");
|
|
366
|
+
const shard2 = join(testDir, "checkpoint-worker-01.json");
|
|
367
|
+
const storage1 = new FileStorage(shard1);
|
|
368
|
+
const storage2 = new FileStorage(shard2);
|
|
369
|
+
await storage1.save({
|
|
370
|
+
configHash: "test-hash",
|
|
371
|
+
createdAt: new Date().toISOString(),
|
|
372
|
+
updatedAt: new Date().toISOString(),
|
|
373
|
+
completedRunIds: ["run-002", "run-003"],
|
|
374
|
+
results: {},
|
|
375
|
+
totalPlanned: 0,
|
|
376
|
+
});
|
|
377
|
+
await storage2.save({
|
|
378
|
+
configHash: "test-hash",
|
|
379
|
+
createdAt: new Date().toISOString(),
|
|
380
|
+
updatedAt: new Date().toISOString(),
|
|
381
|
+
completedRunIds: ["run-004", "run-005"],
|
|
382
|
+
results: {},
|
|
383
|
+
totalPlanned: 0,
|
|
384
|
+
});
|
|
385
|
+
// Merge shards
|
|
386
|
+
const shards = await FileStorage.findShards(testDir);
|
|
387
|
+
const merged = await checkpoint.mergeShards(shards);
|
|
388
|
+
// Verify all runs are included
|
|
389
|
+
const runIds = new Set(merged.completedRunIds);
|
|
390
|
+
assert.strictEqual(runIds.size, 5);
|
|
391
|
+
assert.ok(runIds.has("run-001"));
|
|
392
|
+
assert.ok(runIds.has("run-002"));
|
|
393
|
+
assert.ok(runIds.has("run-003"));
|
|
394
|
+
assert.ok(runIds.has("run-004"));
|
|
395
|
+
assert.ok(runIds.has("run-005"));
|
|
155
396
|
});
|
|
156
|
-
// Merge
|
|
157
|
-
const shards = await FileStorage.findShards(testDir);
|
|
158
|
-
const merged = await checkpoint.mergeShards(shards);
|
|
159
|
-
// Verify no duplicates
|
|
160
|
-
const uniqueIds = new Set(merged.completedRunIds);
|
|
161
|
-
assert.strictEqual(uniqueIds.size, 2); // run-001, run-002 (no duplicates)
|
|
162
|
-
assert.strictEqual(merged.completedRunIds.length, 2);
|
|
163
397
|
});
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
398
|
+
describe("edge cases", () => {
|
|
399
|
+
it("should handle loading non-existent checkpoint file", async () => {
|
|
400
|
+
const fresh = new CheckpointManager({
|
|
401
|
+
storage: new FileStorage(join(testDir, "non-existent.json")),
|
|
402
|
+
});
|
|
403
|
+
// Should not throw, just return empty checkpoint
|
|
404
|
+
await fresh.load();
|
|
405
|
+
assert.strictEqual(fresh.getResults().length, 0);
|
|
406
|
+
});
|
|
407
|
+
it("should handle empty shard list during merge", async () => {
|
|
408
|
+
const merged = await checkpoint.mergeShards([]);
|
|
409
|
+
assert.strictEqual(merged.completedRunIds.length, 0);
|
|
410
|
+
assert.strictEqual(merged.totalPlanned, 0);
|
|
411
|
+
});
|
|
412
|
+
it("should handle shard with different config hash", async () => {
|
|
413
|
+
// Save main checkpoint with one config
|
|
414
|
+
const result = {
|
|
415
|
+
run: {
|
|
416
|
+
runId: "run-001",
|
|
417
|
+
sut: "test-sut",
|
|
418
|
+
sutRole: "primary",
|
|
419
|
+
sutVersion: "1.0.0",
|
|
420
|
+
caseId: "case-001",
|
|
421
|
+
seed: 42,
|
|
422
|
+
repetition: 0,
|
|
423
|
+
},
|
|
424
|
+
correctness: {
|
|
425
|
+
expectedExists: false,
|
|
426
|
+
producedOutput: true,
|
|
427
|
+
valid: true,
|
|
428
|
+
matchesExpected: null,
|
|
429
|
+
},
|
|
430
|
+
outputs: { summary: {} },
|
|
431
|
+
metrics: { numeric: { test: 1 } },
|
|
432
|
+
provenance: {
|
|
433
|
+
runtime: { platform: "linux", arch: "x64", nodeVersion: "v22.0.0" },
|
|
434
|
+
},
|
|
435
|
+
};
|
|
436
|
+
await checkpoint.saveIncremental(result);
|
|
437
|
+
// Reload to update in-memory data
|
|
438
|
+
await checkpoint.load();
|
|
439
|
+
// Create shard with different config hash
|
|
440
|
+
const shard1 = join(testDir, "checkpoint-worker-00.json");
|
|
441
|
+
const storage1 = new FileStorage(shard1);
|
|
442
|
+
await storage1.save({
|
|
443
|
+
configHash: "different-hash", // Different config
|
|
444
|
+
createdAt: new Date().toISOString(),
|
|
445
|
+
updatedAt: new Date().toISOString(),
|
|
446
|
+
completedRunIds: ["run-002"],
|
|
447
|
+
results: {},
|
|
448
|
+
totalPlanned: 0,
|
|
449
|
+
});
|
|
450
|
+
// Merge merges all shards regardless of config hash
|
|
451
|
+
// (implementation doesn't filter by hash)
|
|
452
|
+
const shards = await FileStorage.findShards(testDir);
|
|
453
|
+
const merged = await checkpoint.mergeShards(shards);
|
|
454
|
+
// Should include both runs (merge doesn't filter by hash)
|
|
455
|
+
assert.ok(merged.completedRunIds.includes("run-001"));
|
|
456
|
+
assert.ok(merged.completedRunIds.includes("run-002"));
|
|
457
|
+
});
|
|
188
458
|
});
|
|
189
459
|
});
|
|
190
460
|
/**
|
|
@@ -207,7 +477,6 @@ const createMockSut = () => ({
|
|
|
207
477
|
});
|
|
208
478
|
/**
|
|
209
479
|
* Create a mock case for testing.
|
|
210
|
-
* @param id
|
|
211
480
|
*/
|
|
212
481
|
const createMockCase = (id) => ({
|
|
213
482
|
case: {
|