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
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run Command
|
|
3
|
+
*
|
|
4
|
+
* Executes experiments based on JSON configuration.
|
|
5
|
+
*/
|
|
6
|
+
import { resolve } from "node:path";
|
|
7
|
+
import { aggregateResults, createAggregationOutput } from "../../aggregation/index.js";
|
|
8
|
+
import { Executor } from "../../executor/index.js";
|
|
9
|
+
import { loadAndValidateConfig } from "../config-loader.js";
|
|
10
|
+
import { loadCaseDefinition, loadMetricsExtractor, loadSutFactory } from "../module-loader.js";
|
|
11
|
+
import { generateOutputFilename, writeAggregates, writeResults } from "../output-writer.js";
|
|
12
|
+
/**
|
|
13
|
+
* Merge checkpoint shards from worker threads.
|
|
14
|
+
*
|
|
15
|
+
* After worker threads complete execution, each worker has its own checkpoint shard.
|
|
16
|
+
* This function merges all shards into a single checkpoint file.
|
|
17
|
+
*
|
|
18
|
+
* @param baseDir - Base directory for checkpoints
|
|
19
|
+
* @param logger - Command logger
|
|
20
|
+
*/
|
|
21
|
+
async function mergeCheckpointShards(baseDir, logger) {
|
|
22
|
+
const { readdir, unlink } = await import("node:fs/promises");
|
|
23
|
+
const { FileStorage } = await import("../../executor/checkpoint-storage.js");
|
|
24
|
+
const checkpointDir = resolve(baseDir, "results/execute");
|
|
25
|
+
try {
|
|
26
|
+
const files = await readdir(checkpointDir);
|
|
27
|
+
const shards = files.filter((f) => f.startsWith("checkpoint-worker-") && f.endsWith(".json"));
|
|
28
|
+
if (shards.length === 0) {
|
|
29
|
+
// No shards found - nothing to merge
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
logger.info(`Merging ${shards.length} checkpoint shards...`);
|
|
33
|
+
// Load and merge all shards
|
|
34
|
+
const mergedData = {
|
|
35
|
+
configHash: "merged",
|
|
36
|
+
createdAt: new Date().toISOString(),
|
|
37
|
+
updatedAt: new Date().toISOString(),
|
|
38
|
+
completedRunIds: [],
|
|
39
|
+
results: {},
|
|
40
|
+
totalPlanned: 0,
|
|
41
|
+
};
|
|
42
|
+
for (const shard of shards) {
|
|
43
|
+
const shardPath = resolve(checkpointDir, shard);
|
|
44
|
+
const storage = new FileStorage(shardPath);
|
|
45
|
+
const data = await storage.load();
|
|
46
|
+
if (data?.completedRunIds) {
|
|
47
|
+
// Merge run IDs into the array
|
|
48
|
+
for (const runId of data.completedRunIds) {
|
|
49
|
+
if (!mergedData.completedRunIds.includes(runId)) {
|
|
50
|
+
mergedData.completedRunIds.push(runId);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Merge results if present
|
|
55
|
+
if (data?.results) {
|
|
56
|
+
Object.assign(mergedData.results, data.results);
|
|
57
|
+
}
|
|
58
|
+
// Update total planned from first shard
|
|
59
|
+
if (data?.totalPlanned && mergedData.totalPlanned === 0) {
|
|
60
|
+
mergedData.totalPlanned = data.totalPlanned;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Write merged checkpoint
|
|
64
|
+
const mainStorage = new FileStorage(resolve(checkpointDir, "checkpoint.json"));
|
|
65
|
+
await mainStorage.save(mergedData);
|
|
66
|
+
logger.info("Checkpoint shards merged successfully");
|
|
67
|
+
// Clean up shard files
|
|
68
|
+
for (const shard of shards) {
|
|
69
|
+
const shardPath = resolve(checkpointDir, shard);
|
|
70
|
+
await unlink(shardPath).catch(() => {
|
|
71
|
+
// Ignore errors during cleanup
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
logger.debug(`Cleaned up ${shards.length} shard files`);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
// Checkpoint directory doesn't exist or other error - log and continue
|
|
78
|
+
logger.debug(`Checkpoint merge skipped: ${error instanceof Error ? error.message : String(error)}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Execute run command with injected dependencies.
|
|
83
|
+
*
|
|
84
|
+
* This function is exported for testing.
|
|
85
|
+
*
|
|
86
|
+
* @param configFile - Path to config file
|
|
87
|
+
* @param options - Command options
|
|
88
|
+
* @param dependencies - Injected dependencies
|
|
89
|
+
*/
|
|
90
|
+
export async function executeRun(configFile, options, dependencies) {
|
|
91
|
+
const { logger, configLoader, moduleLoader, createExecutor, aggregator, outputWriter, processExit, } = dependencies;
|
|
92
|
+
try {
|
|
93
|
+
logger.header(`Experiment: ${options.dryRun ? "Dry Run" : "Execution"}`);
|
|
94
|
+
// Load and validate configuration
|
|
95
|
+
const loaded = await configLoader.loadAndValidateConfig(configFile);
|
|
96
|
+
const { config, baseDir } = loaded;
|
|
97
|
+
logger.info(`Configuration: ${loaded.configPath}`);
|
|
98
|
+
logger.info(`Experiment: ${config.experiment.name}`);
|
|
99
|
+
if (config.experiment.description) {
|
|
100
|
+
logger.info(`Description: ${config.experiment.description}`);
|
|
101
|
+
}
|
|
102
|
+
// Apply CLI overrides
|
|
103
|
+
const executorConfig = { ...config.executor };
|
|
104
|
+
if (options.jobs !== undefined) {
|
|
105
|
+
executorConfig.concurrency = options.jobs;
|
|
106
|
+
logger.debug(`Concurrency overridden to ${options.jobs}`);
|
|
107
|
+
}
|
|
108
|
+
// Handle unsafe in-process flag
|
|
109
|
+
if (options.unsafeInProcess) {
|
|
110
|
+
executorConfig.forceInProcess = true;
|
|
111
|
+
logger.warn("Running in-process without worker thread isolation (SUT crashes can crash CLI)");
|
|
112
|
+
}
|
|
113
|
+
// Load SUTs
|
|
114
|
+
logger.subheader("Loading SUTs...");
|
|
115
|
+
const sutDefinitions = await Promise.all(config.suts.map(async (sutConfig) => {
|
|
116
|
+
logger.debug(`Loading SUT: ${sutConfig.id} from ${sutConfig.module}`);
|
|
117
|
+
// Build binary config if this is a binary SUT
|
|
118
|
+
const binaryConfig = sutConfig.type === "binary" && sutConfig.binaryCommand
|
|
119
|
+
? {
|
|
120
|
+
type: "binary",
|
|
121
|
+
command: sutConfig.binaryCommand,
|
|
122
|
+
args: sutConfig.binaryArgs,
|
|
123
|
+
inputFormat: sutConfig.binaryInputFormat,
|
|
124
|
+
outputFormat: sutConfig.binaryOutputFormat,
|
|
125
|
+
timeout: sutConfig.binaryTimeout,
|
|
126
|
+
successExitCode: undefined, // Could add to SutConfig if needed
|
|
127
|
+
}
|
|
128
|
+
: undefined;
|
|
129
|
+
return moduleLoader.loadSutFactory(sutConfig.module, sutConfig.exportName, baseDir, {
|
|
130
|
+
id: sutConfig.id,
|
|
131
|
+
name: sutConfig.registration.name,
|
|
132
|
+
version: sutConfig.registration.version,
|
|
133
|
+
role: sutConfig.registration.role,
|
|
134
|
+
config: sutConfig.config ?? {},
|
|
135
|
+
tags: sutConfig.registration.tags ?? [],
|
|
136
|
+
description: sutConfig.registration.description,
|
|
137
|
+
}, sutConfig.config, binaryConfig);
|
|
138
|
+
}));
|
|
139
|
+
logger.info(`Loaded ${sutDefinitions.length} SUTs`);
|
|
140
|
+
// Load cases
|
|
141
|
+
logger.subheader("Loading cases...");
|
|
142
|
+
const caseDefinitions = await Promise.all(config.cases.map(async (caseConfig) => {
|
|
143
|
+
logger.debug(`Loading case: ${caseConfig.id} from ${caseConfig.module}`);
|
|
144
|
+
return moduleLoader.loadCaseDefinition(caseConfig.module, caseConfig.exportName, baseDir);
|
|
145
|
+
}));
|
|
146
|
+
logger.info(`Loaded ${caseDefinitions.length} cases`);
|
|
147
|
+
// Load metrics extractor
|
|
148
|
+
logger.subheader("Loading metrics extractor...");
|
|
149
|
+
const metricsExtractor = await moduleLoader.loadMetricsExtractor(config.metricsExtractor.module, config.metricsExtractor.exportName, baseDir);
|
|
150
|
+
logger.info(`Metrics extractor loaded from ${config.metricsExtractor.module}`);
|
|
151
|
+
// Create executor
|
|
152
|
+
const executor = createExecutor(executorConfig);
|
|
153
|
+
// Plan runs
|
|
154
|
+
logger.subheader("Planning execution...");
|
|
155
|
+
const plannedRuns = executor.plan(sutDefinitions, caseDefinitions);
|
|
156
|
+
logger.info(`Planned ${plannedRuns.length} runs`);
|
|
157
|
+
// Dry run - just show plan and exit
|
|
158
|
+
if (options.dryRun) {
|
|
159
|
+
logger.info("");
|
|
160
|
+
logger.subheader("Dry run - not executing");
|
|
161
|
+
logger.info(`SUTs: ${sutDefinitions.map((s) => s.id).join(", ")}`);
|
|
162
|
+
logger.info(`Cases: ${caseDefinitions.map((c) => c.case.caseId).join(", ")}`);
|
|
163
|
+
logger.info(`Total runs: ${plannedRuns.length}`);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
// Execute
|
|
167
|
+
logger.subheader("Executing...");
|
|
168
|
+
logger.setProgress(true);
|
|
169
|
+
const startTime = Date.now();
|
|
170
|
+
const summary = await executor.execute(sutDefinitions, caseDefinitions, metricsExtractor, undefined);
|
|
171
|
+
const elapsed = Date.now() - startTime;
|
|
172
|
+
logger.setProgress(false);
|
|
173
|
+
logger.info("");
|
|
174
|
+
// Merge checkpoint shards from workers if not in unsafe in-process mode
|
|
175
|
+
if (!options.unsafeInProcess) {
|
|
176
|
+
await mergeCheckpointShards(baseDir, logger);
|
|
177
|
+
}
|
|
178
|
+
// Report results
|
|
179
|
+
logger.subheader("Execution Summary");
|
|
180
|
+
logger.info(`Total runs: ${summary.totalRuns}`);
|
|
181
|
+
logger.info(`Successful: ${summary.successfulRuns}`);
|
|
182
|
+
logger.info(`Failed: ${summary.failedRuns}`);
|
|
183
|
+
logger.info(`Elapsed time: ${(elapsed / 1000).toFixed(2)}s`);
|
|
184
|
+
if (summary.errors.length > 0) {
|
|
185
|
+
logger.warn(`Errors encountered: ${summary.errors.length}`);
|
|
186
|
+
for (const error of summary.errors.slice(0, 5)) {
|
|
187
|
+
logger.warn(` - ${error.runId}: ${error.error}`);
|
|
188
|
+
}
|
|
189
|
+
if (summary.errors.length > 5) {
|
|
190
|
+
logger.warn(` ... and ${summary.errors.length - 5} more`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// Determine output settings
|
|
194
|
+
const outputPath = options.output ?? config.output.path ?? "./results";
|
|
195
|
+
const format = options.format ?? config.output.format ?? "json-pretty";
|
|
196
|
+
const shouldAggregate = options.noAggregate !== true && config.output.aggregate !== false;
|
|
197
|
+
// Write results
|
|
198
|
+
logger.subheader("Writing results...");
|
|
199
|
+
const resultsFilename = outputWriter.generateOutputFilename(config.experiment.name, "results");
|
|
200
|
+
const resultsPath = `${outputPath}/${resultsFilename}`;
|
|
201
|
+
await outputWriter.writeResults(summary.results, resultsPath, format);
|
|
202
|
+
logger.info(`Results written to: ${resultsPath}`);
|
|
203
|
+
// Aggregate if requested
|
|
204
|
+
if (shouldAggregate && summary.results.length > 0) {
|
|
205
|
+
logger.subheader("Aggregating results...");
|
|
206
|
+
const aggregates = aggregator.aggregateResults(summary.results, {
|
|
207
|
+
groupByCaseClass: true,
|
|
208
|
+
computeComparisons: true,
|
|
209
|
+
});
|
|
210
|
+
const aggregationOutput = aggregator.createAggregationOutput(aggregates, summary.results);
|
|
211
|
+
const aggregatesFilename = outputWriter.generateOutputFilename(config.experiment.name, "aggregates");
|
|
212
|
+
const aggregatesPath = `${outputPath}/${aggregatesFilename}`;
|
|
213
|
+
await outputWriter.writeAggregates(aggregationOutput, aggregatesPath, format);
|
|
214
|
+
logger.info(`Aggregates written to: ${aggregatesPath}`);
|
|
215
|
+
logger.info("");
|
|
216
|
+
logger.subheader("Aggregation Summary");
|
|
217
|
+
for (const agg of aggregates) {
|
|
218
|
+
const caseClassSuffix = agg.caseClass ? ` (${agg.caseClass})` : "";
|
|
219
|
+
logger.info(`${agg.sut}${caseClassSuffix}:`);
|
|
220
|
+
logger.info(` Runs: ${agg.group.runCount}`);
|
|
221
|
+
logger.info(` Cases: ${agg.group.caseCount}`);
|
|
222
|
+
for (const [metric, stats] of Object.entries(agg.metrics)) {
|
|
223
|
+
const std = stats.std ?? 0;
|
|
224
|
+
logger.info(` ${metric}: mean=${stats.mean.toFixed(2)}, std=${std.toFixed(2)}`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
logger.info("");
|
|
229
|
+
logger.info("Experiment completed successfully!");
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
logger.setProgress(false);
|
|
233
|
+
if (error instanceof Error) {
|
|
234
|
+
logger.error(error.message);
|
|
235
|
+
if (options.verbose) {
|
|
236
|
+
console.error(error.stack);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
logger.error(String(error));
|
|
241
|
+
}
|
|
242
|
+
processExit(1);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Register the run command.
|
|
247
|
+
*
|
|
248
|
+
* @param program - Commander program instance
|
|
249
|
+
*/
|
|
250
|
+
export function registerRunCommand(program) {
|
|
251
|
+
program
|
|
252
|
+
.command("run")
|
|
253
|
+
.description("Run experiments from a configuration file")
|
|
254
|
+
.argument("<config-file>", "Path to experiment configuration JSON file")
|
|
255
|
+
.option("-o, --output <path>", "Output directory")
|
|
256
|
+
.option("-f, --format <format>", "Output format (json or json-pretty)", "json-pretty")
|
|
257
|
+
.option("--no-aggregate", "Skip aggregation")
|
|
258
|
+
.option("-j, --jobs <number>", "Override concurrency", (value) => Number.parseInt(value, 10))
|
|
259
|
+
.option("-v, --verbose", "Verbose logging")
|
|
260
|
+
.option("-q, --quiet", "Suppress output")
|
|
261
|
+
.option("--dry-run", "Plan without running")
|
|
262
|
+
.option("--unsafe-in-process", "Run in-process without worker thread isolation (SUT crashes can crash CLI)")
|
|
263
|
+
.action(async (configFile, options) => {
|
|
264
|
+
const { createLogger } = await import("../logger.js");
|
|
265
|
+
const logger = createLogger(options);
|
|
266
|
+
await executeRun(configFile, options, {
|
|
267
|
+
logger,
|
|
268
|
+
configLoader: { loadAndValidateConfig },
|
|
269
|
+
moduleLoader: { loadSutFactory, loadCaseDefinition, loadMetricsExtractor },
|
|
270
|
+
createExecutor: (config) => new Executor(config),
|
|
271
|
+
aggregator: { aggregateResults, createAggregationOutput },
|
|
272
|
+
outputWriter: { generateOutputFilename, writeResults, writeAggregates },
|
|
273
|
+
processExit: (code) => process.exit(code),
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/cli/commands/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate Command
|
|
3
|
+
*
|
|
4
|
+
* Validates experiment configuration files without running experiments.
|
|
5
|
+
*/
|
|
6
|
+
import type { Command } from "commander";
|
|
7
|
+
import type { IConfigLoader, ICommandLogger } from "../command-deps.js";
|
|
8
|
+
/**
|
|
9
|
+
* Execute validate command with injected dependencies.
|
|
10
|
+
*
|
|
11
|
+
* This function is exported for testing.
|
|
12
|
+
*
|
|
13
|
+
* @param configFile - Path to config file
|
|
14
|
+
* @param dependencies - Injected dependencies
|
|
15
|
+
*/
|
|
16
|
+
export declare function executeValidate(configFile: string, dependencies: {
|
|
17
|
+
logger: ICommandLogger;
|
|
18
|
+
configLoader: IConfigLoader;
|
|
19
|
+
processExit: (code: number) => never;
|
|
20
|
+
}): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Register the validate command.
|
|
23
|
+
*
|
|
24
|
+
* @param program - Commander program instance
|
|
25
|
+
*/
|
|
26
|
+
export declare function registerValidateCommand(program: Command): void;
|
|
27
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/validate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAIxE;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACpC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE;IACb,MAAM,EAAE,cAAc,CAAC;IACvB,YAAY,EAAE,aAAa,CAAC;IAC5B,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC;CACrC,GACC,OAAO,CAAC,IAAI,CAAC,CA0Df;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgB9D"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate Command
|
|
3
|
+
*
|
|
4
|
+
* Validates experiment configuration files without running experiments.
|
|
5
|
+
*/
|
|
6
|
+
import { loadAndValidateConfig } from "../config-loader.js";
|
|
7
|
+
// Note: createLogger imported lazily in action handler to avoid circular dependency
|
|
8
|
+
/**
|
|
9
|
+
* Execute validate command with injected dependencies.
|
|
10
|
+
*
|
|
11
|
+
* This function is exported for testing.
|
|
12
|
+
*
|
|
13
|
+
* @param configFile - Path to config file
|
|
14
|
+
* @param dependencies - Injected dependencies
|
|
15
|
+
*/
|
|
16
|
+
export async function executeValidate(configFile, dependencies) {
|
|
17
|
+
const { logger, configLoader, processExit } = dependencies;
|
|
18
|
+
try {
|
|
19
|
+
logger.header("Configuration Validation");
|
|
20
|
+
const loaded = await configLoader.loadAndValidateConfig(configFile);
|
|
21
|
+
logger.info(`Configuration file: ${loaded.configPath}`);
|
|
22
|
+
logger.info(`Base directory: ${loaded.baseDir}`);
|
|
23
|
+
logger.info(`Experiment: ${loaded.config.experiment.name}`);
|
|
24
|
+
if (loaded.config.experiment.description) {
|
|
25
|
+
logger.info(`Description: ${loaded.config.experiment.description}`);
|
|
26
|
+
}
|
|
27
|
+
if (loaded.config.experiment.version) {
|
|
28
|
+
logger.info(`Version: ${loaded.config.experiment.version}`);
|
|
29
|
+
}
|
|
30
|
+
logger.subheader("SUTs");
|
|
31
|
+
for (const sut of loaded.config.suts) {
|
|
32
|
+
logger.info(` - ${sut.id} (${sut.registration.name} v${sut.registration.version})`);
|
|
33
|
+
logger.info(` Module: ${sut.module} -> ${sut.exportName}`);
|
|
34
|
+
logger.info(` Role: ${sut.registration.role}`);
|
|
35
|
+
}
|
|
36
|
+
logger.subheader("Cases");
|
|
37
|
+
for (const testCase of loaded.config.cases) {
|
|
38
|
+
logger.info(` - ${testCase.id}`);
|
|
39
|
+
logger.info(` Module: ${testCase.module} -> ${testCase.exportName}`);
|
|
40
|
+
}
|
|
41
|
+
logger.subheader("Executor");
|
|
42
|
+
const executor = loaded.config.executor;
|
|
43
|
+
logger.info(` Repetitions: ${executor.repetitions ?? "default"}`);
|
|
44
|
+
logger.info(` Seed base: ${executor.seedBase ?? "default"}`);
|
|
45
|
+
logger.info(` Timeout: ${executor.timeoutMs ?? "default"}ms`);
|
|
46
|
+
logger.info(` Concurrency: ${executor.concurrency ?? "sequential"}`);
|
|
47
|
+
logger.info(` Continue on error: ${executor.continueOnError ?? "default"}`);
|
|
48
|
+
logger.info(` Collect provenance: ${executor.collectProvenance ?? "default"}`);
|
|
49
|
+
logger.subheader("Output");
|
|
50
|
+
const output = loaded.config.output;
|
|
51
|
+
logger.info(` Path: ${output.path ?? "./results"}`);
|
|
52
|
+
logger.info(` Format: ${output.format ?? "json-pretty"}`);
|
|
53
|
+
logger.info(` Aggregate: ${output.aggregate ?? "true"}`);
|
|
54
|
+
logger.info("");
|
|
55
|
+
logger.info("Configuration is valid!");
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
if (error instanceof Error) {
|
|
59
|
+
logger.error(error.message);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
logger.error(String(error));
|
|
63
|
+
}
|
|
64
|
+
processExit(1);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Register the validate command.
|
|
69
|
+
*
|
|
70
|
+
* @param program - Commander program instance
|
|
71
|
+
*/
|
|
72
|
+
export function registerValidateCommand(program) {
|
|
73
|
+
program
|
|
74
|
+
.command("validate")
|
|
75
|
+
.description("Validate an experiment configuration file")
|
|
76
|
+
.argument("<config-file>", "Path to experiment configuration JSON file")
|
|
77
|
+
.action(async (configFile) => {
|
|
78
|
+
// Import dependencies lazily to avoid circular imports
|
|
79
|
+
const { createLogger } = await import("../logger.js");
|
|
80
|
+
const logger = createLogger();
|
|
81
|
+
await executeValidate(configFile, {
|
|
82
|
+
logger,
|
|
83
|
+
configLoader: { loadAndValidateConfig },
|
|
84
|
+
processExit: (code) => process.exit(code),
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/cli/commands/validate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config Loader
|
|
3
|
+
*
|
|
4
|
+
* Loads and validates experiment configuration from JSON files.
|
|
5
|
+
*/
|
|
6
|
+
import type { ExperimentConfig, LoadedConfig, ValidationResult } from "./types.js";
|
|
7
|
+
/**
|
|
8
|
+
* Load and parse experiment configuration from a JSON file.
|
|
9
|
+
*
|
|
10
|
+
* @param configPath - Path to config file (can be absolute or relative)
|
|
11
|
+
* @returns Loaded configuration with base directory
|
|
12
|
+
* @throws Error if file cannot be read or parsed
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadConfig(configPath: string): Promise<LoadedConfig>;
|
|
15
|
+
/**
|
|
16
|
+
* Validate experiment configuration.
|
|
17
|
+
*
|
|
18
|
+
* @param config - Configuration to validate
|
|
19
|
+
* @returns Validation result with errors and warnings
|
|
20
|
+
*/
|
|
21
|
+
export declare function validateConfig(config: ExperimentConfig): ValidationResult;
|
|
22
|
+
/**
|
|
23
|
+
* Load and validate experiment configuration.
|
|
24
|
+
*
|
|
25
|
+
* @param configPath - Path to config file
|
|
26
|
+
* @returns Loaded and validated configuration
|
|
27
|
+
* @throws Error if validation fails
|
|
28
|
+
*/
|
|
29
|
+
export declare function loadAndValidateConfig(configPath: string): Promise<LoadedConfig>;
|
|
30
|
+
//# sourceMappingURL=config-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/cli/config-loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnF;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAgB1E;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,CA+HzE;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAkBrF"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config Loader
|
|
3
|
+
*
|
|
4
|
+
* Loads and validates experiment configuration from JSON files.
|
|
5
|
+
*/
|
|
6
|
+
import { readFile } from "node:fs/promises";
|
|
7
|
+
import { resolve, dirname } from "node:path";
|
|
8
|
+
/**
|
|
9
|
+
* Load and parse experiment configuration from a JSON file.
|
|
10
|
+
*
|
|
11
|
+
* @param configPath - Path to config file (can be absolute or relative)
|
|
12
|
+
* @returns Loaded configuration with base directory
|
|
13
|
+
* @throws Error if file cannot be read or parsed
|
|
14
|
+
*/
|
|
15
|
+
export async function loadConfig(configPath) {
|
|
16
|
+
// Resolve absolute path
|
|
17
|
+
const absolutePath = resolve(configPath);
|
|
18
|
+
// Read and parse JSON
|
|
19
|
+
const content = await readFile(absolutePath, "utf-8");
|
|
20
|
+
const config = JSON.parse(content);
|
|
21
|
+
// Get base directory (for resolving module paths)
|
|
22
|
+
const baseDir = dirname(absolutePath);
|
|
23
|
+
return {
|
|
24
|
+
config,
|
|
25
|
+
baseDir,
|
|
26
|
+
configPath: absolutePath,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Validate experiment configuration.
|
|
31
|
+
*
|
|
32
|
+
* @param config - Configuration to validate
|
|
33
|
+
* @returns Validation result with errors and warnings
|
|
34
|
+
*/
|
|
35
|
+
export function validateConfig(config) {
|
|
36
|
+
const errors = [];
|
|
37
|
+
const warnings = [];
|
|
38
|
+
// Validate experiment metadata
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
40
|
+
if (!config.experiment?.name) {
|
|
41
|
+
errors.push("experiment.name is required");
|
|
42
|
+
}
|
|
43
|
+
// Validate executor config
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
45
|
+
if (!config.executor) {
|
|
46
|
+
errors.push("executor configuration is required");
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
if (config.executor.repetitions !== undefined && config.executor.repetitions < 1) {
|
|
50
|
+
errors.push("executor.repetitions must be at least 1");
|
|
51
|
+
}
|
|
52
|
+
if (config.executor.seedBase !== undefined && config.executor.seedBase < 0) {
|
|
53
|
+
errors.push("executor.seedBase must be non-negative");
|
|
54
|
+
}
|
|
55
|
+
if (config.executor.timeoutMs !== undefined && config.executor.timeoutMs < 0) {
|
|
56
|
+
errors.push("executor.timeoutMs must be non-negative");
|
|
57
|
+
}
|
|
58
|
+
if (config.executor.concurrency !== undefined && config.executor.concurrency < 1) {
|
|
59
|
+
errors.push("executor.concurrency must be at least 1");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Validate SUTs
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
64
|
+
if (!config.suts || config.suts.length === 0) {
|
|
65
|
+
warnings.push("No SUTs configured - experiment will have nothing to execute");
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
for (let i = 0; i < config.suts.length; i++) {
|
|
69
|
+
const sut = config.suts[i];
|
|
70
|
+
if (!sut.id) {
|
|
71
|
+
errors.push(`suts[${i}].id is required`);
|
|
72
|
+
}
|
|
73
|
+
if (!sut.module) {
|
|
74
|
+
errors.push(`suts[${i}].module is required`);
|
|
75
|
+
}
|
|
76
|
+
if (!sut.exportName) {
|
|
77
|
+
errors.push(`suts[${i}].exportName is required`);
|
|
78
|
+
}
|
|
79
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
80
|
+
if (!sut.registration?.name) {
|
|
81
|
+
errors.push(`suts[${i}].registration.name is required`);
|
|
82
|
+
}
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
84
|
+
if (!sut.registration?.version) {
|
|
85
|
+
errors.push(`suts[${i}].registration.version is required`);
|
|
86
|
+
}
|
|
87
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
88
|
+
if (!sut.registration?.role) {
|
|
89
|
+
errors.push(`suts[${i}].registration.role is required`);
|
|
90
|
+
}
|
|
91
|
+
else if (!["primary", "baseline", "oracle"].includes(sut.registration.role)) {
|
|
92
|
+
errors.push(`suts[${i}].registration.role must be one of: primary, baseline, oracle`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Check for duplicate SUT IDs
|
|
96
|
+
const sutIds = new Set();
|
|
97
|
+
for (const sut of config.suts) {
|
|
98
|
+
if (sut.id && sutIds.has(sut.id)) {
|
|
99
|
+
errors.push(`Duplicate SUT ID: ${sut.id}`);
|
|
100
|
+
}
|
|
101
|
+
sutIds.add(sut.id);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// Validate cases
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
106
|
+
if (!config.cases || config.cases.length === 0) {
|
|
107
|
+
warnings.push("No cases configured - experiment will have nothing to execute");
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
for (let i = 0; i < config.cases.length; i++) {
|
|
111
|
+
const testCase = config.cases[i];
|
|
112
|
+
if (!testCase.id) {
|
|
113
|
+
errors.push(`cases[${i}].id is required`);
|
|
114
|
+
}
|
|
115
|
+
if (!testCase.module) {
|
|
116
|
+
errors.push(`cases[${i}].module is required`);
|
|
117
|
+
}
|
|
118
|
+
if (!testCase.exportName) {
|
|
119
|
+
errors.push(`cases[${i}].exportName is required`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Check for duplicate case IDs
|
|
123
|
+
const caseIds = new Set();
|
|
124
|
+
for (const testCase of config.cases) {
|
|
125
|
+
if (testCase.id && caseIds.has(testCase.id)) {
|
|
126
|
+
errors.push(`Duplicate case ID: ${testCase.id}`);
|
|
127
|
+
}
|
|
128
|
+
caseIds.add(testCase.id);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Validate metrics extractor
|
|
132
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
133
|
+
if (!config.metricsExtractor) {
|
|
134
|
+
errors.push("metricsExtractor configuration is required");
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
if (!config.metricsExtractor.module) {
|
|
138
|
+
errors.push("metricsExtractor.module is required");
|
|
139
|
+
}
|
|
140
|
+
if (!config.metricsExtractor.exportName) {
|
|
141
|
+
errors.push("metricsExtractor.exportName is required");
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// Validate output config
|
|
145
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
146
|
+
if (!config.output) {
|
|
147
|
+
warnings.push("No output configuration specified - using defaults");
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
if (config.output.format && !["json", "json-pretty"].includes(config.output.format)) {
|
|
151
|
+
errors.push('output.format must be one of: "json", "json-pretty"');
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
valid: errors.length === 0,
|
|
156
|
+
errors,
|
|
157
|
+
warnings,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Load and validate experiment configuration.
|
|
162
|
+
*
|
|
163
|
+
* @param configPath - Path to config file
|
|
164
|
+
* @returns Loaded and validated configuration
|
|
165
|
+
* @throws Error if validation fails
|
|
166
|
+
*/
|
|
167
|
+
export async function loadAndValidateConfig(configPath) {
|
|
168
|
+
const loaded = await loadConfig(configPath);
|
|
169
|
+
const validation = validateConfig(loaded.config);
|
|
170
|
+
if (!validation.valid) {
|
|
171
|
+
throw new Error(`Configuration validation failed:\n${validation.errors.map((e) => ` - ${e}`).join("\n")}`);
|
|
172
|
+
}
|
|
173
|
+
// Print warnings if any
|
|
174
|
+
if (validation.warnings.length > 0) {
|
|
175
|
+
for (const warning of validation.warnings) {
|
|
176
|
+
console.warn(`Warning: ${warning}`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return loaded;
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=config-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-loader.js","sourceRoot":"","sources":["../../src/cli/config-loader.ts"],"names":[],"mappings":"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"}
|