@brainbase-labs/cli 0.25.0-eng1209.4 → 0.25.0-eng1209.6
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/dist/index.js +145 -24
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -36008,7 +36008,7 @@ function padStart(s, n) {
|
|
|
36008
36008
|
// package.json
|
|
36009
36009
|
var package_default = {
|
|
36010
36010
|
name: "@brainbase-labs/cli",
|
|
36011
|
-
version: "0.25.0-eng1209.
|
|
36011
|
+
version: "0.25.0-eng1209.6",
|
|
36012
36012
|
description: "Pack, share, and install agent templates across harnesses (Claude Code, Codex, ...).",
|
|
36013
36013
|
type: "module",
|
|
36014
36014
|
bin: {
|
|
@@ -78882,6 +78882,19 @@ class BenchmarkPhaseError extends Error {
|
|
|
78882
78882
|
this.name = "BenchmarkPhaseError";
|
|
78883
78883
|
}
|
|
78884
78884
|
}
|
|
78885
|
+
|
|
78886
|
+
class BenchmarkCommandExecutionError extends BenchmarkPhaseError {
|
|
78887
|
+
stdout;
|
|
78888
|
+
stderr;
|
|
78889
|
+
durationMs;
|
|
78890
|
+
constructor(code, message, stdout, stderr, durationMs) {
|
|
78891
|
+
super(code, message);
|
|
78892
|
+
this.stdout = stdout;
|
|
78893
|
+
this.stderr = stderr;
|
|
78894
|
+
this.durationMs = durationMs;
|
|
78895
|
+
this.name = "BenchmarkCommandExecutionError";
|
|
78896
|
+
}
|
|
78897
|
+
}
|
|
78885
78898
|
var ZIP_EOCD_SIGNATURE = 101010256;
|
|
78886
78899
|
var ZIP_CENTRAL_SIGNATURE = 33639248;
|
|
78887
78900
|
var ZIP_LOCAL_SIGNATURE = 67324752;
|
|
@@ -79985,7 +79998,8 @@ async function runCommand(command, root, spec, context, additions = {}) {
|
|
|
79985
79998
|
const remainingMs = context.deadline - Date.now();
|
|
79986
79999
|
if (remainingMs <= 0)
|
|
79987
80000
|
throw new BenchmarkPhaseError("phase_timeout", "phase budget expired");
|
|
79988
|
-
const
|
|
80001
|
+
const reachesPhaseDeadline = command.timeout_ms === undefined || command.timeout_ms >= remainingMs;
|
|
80002
|
+
const timeoutMs2 = reachesPhaseDeadline ? remainingMs : command.timeout_ms;
|
|
79989
80003
|
const started = Date.now();
|
|
79990
80004
|
return await new Promise((resolve, reject2) => {
|
|
79991
80005
|
const child = spawn4(command.argv[0], command.argv.slice(1), {
|
|
@@ -80022,10 +80036,14 @@ async function runCommand(command, root, spec, context, additions = {}) {
|
|
|
80022
80036
|
child.stdout?.on("data", (chunk2) => capture(stdout, chunk2));
|
|
80023
80037
|
child.stderr?.on("data", (chunk2) => capture(stderr, chunk2));
|
|
80024
80038
|
child.on("error", (error2) => {
|
|
80025
|
-
fail(new
|
|
80039
|
+
fail(new BenchmarkCommandExecutionError("command_start_failed", `failed to start ${command.id}: ${error2.message}`, Buffer.concat(stdout), Buffer.concat(stderr), Date.now() - started));
|
|
80026
80040
|
});
|
|
80027
80041
|
timer = setTimeout(() => {
|
|
80028
|
-
|
|
80042
|
+
if (reachesPhaseDeadline) {
|
|
80043
|
+
fail(new BenchmarkPhaseError("phase_timeout", "phase budget expired"));
|
|
80044
|
+
return;
|
|
80045
|
+
}
|
|
80046
|
+
fail(new BenchmarkCommandExecutionError("command_timeout", `command timed out: ${command.id}`, Buffer.concat(stdout), Buffer.concat(stderr), Date.now() - started));
|
|
80029
80047
|
}, timeoutMs2);
|
|
80030
80048
|
child.on("close", (code, signal) => {
|
|
80031
80049
|
if (settled)
|
|
@@ -80033,7 +80051,7 @@ async function runCommand(command, root, spec, context, additions = {}) {
|
|
|
80033
80051
|
settled = true;
|
|
80034
80052
|
clearTimeout(timer);
|
|
80035
80053
|
if (code === null) {
|
|
80036
|
-
reject2(new
|
|
80054
|
+
reject2(new BenchmarkCommandExecutionError("command_terminated", `command was terminated by ${signal ?? "an unknown signal"}: ${command.id}`, Buffer.concat(stdout), Buffer.concat(stderr), Date.now() - started));
|
|
80037
80055
|
return;
|
|
80038
80056
|
}
|
|
80039
80057
|
resolve({
|
|
@@ -80234,6 +80252,42 @@ async function workspaceManifest(spec, context) {
|
|
|
80234
80252
|
}
|
|
80235
80253
|
return records.sort((a3, b4) => a3.path.localeCompare(b4.path));
|
|
80236
80254
|
}
|
|
80255
|
+
function treeBytes(root, context) {
|
|
80256
|
+
let totalBytes = 0;
|
|
80257
|
+
const stack = [path88.resolve(root)];
|
|
80258
|
+
while (stack.length > 0) {
|
|
80259
|
+
const directory = stack.pop();
|
|
80260
|
+
const entries = fs81.readdirSync(directory, { withFileTypes: true });
|
|
80261
|
+
for (const entry of entries) {
|
|
80262
|
+
assertBudget(context);
|
|
80263
|
+
const candidate = path88.join(directory, entry.name);
|
|
80264
|
+
const stat = fs81.lstatSync(candidate);
|
|
80265
|
+
if (stat.isDirectory()) {
|
|
80266
|
+
stack.push(candidate);
|
|
80267
|
+
continue;
|
|
80268
|
+
}
|
|
80269
|
+
if (stat.isFile()) {
|
|
80270
|
+
totalBytes += stat.size;
|
|
80271
|
+
continue;
|
|
80272
|
+
}
|
|
80273
|
+
if (stat.isSymbolicLink()) {
|
|
80274
|
+
totalBytes += Buffer.byteLength(fs81.readlinkSync(candidate));
|
|
80275
|
+
continue;
|
|
80276
|
+
}
|
|
80277
|
+
throw new BenchmarkPhaseError("unsafe_path", `evaluate output contains an unsupported filesystem entry: ${path88.relative(root, candidate)}`);
|
|
80278
|
+
}
|
|
80279
|
+
}
|
|
80280
|
+
return totalBytes;
|
|
80281
|
+
}
|
|
80282
|
+
function assertEvaluateOutputBudget(spec, context, additionalBytes = 0) {
|
|
80283
|
+
const actual = treeBytes(spec.logs_root, context) + additionalBytes;
|
|
80284
|
+
if (actual > spec.workspace_limits.max_total_bytes) {
|
|
80285
|
+
throw new BenchmarkPhaseError("workspace_limit_exceeded", "evaluate output bytes exceed the workspace byte limit", {
|
|
80286
|
+
actual,
|
|
80287
|
+
max_total_bytes: spec.workspace_limits.max_total_bytes
|
|
80288
|
+
});
|
|
80289
|
+
}
|
|
80290
|
+
}
|
|
80237
80291
|
function candidateGlob(pattern) {
|
|
80238
80292
|
let source = "^";
|
|
80239
80293
|
for (let index = 0;index < pattern.length; index += 1) {
|
|
@@ -80392,13 +80446,48 @@ async function copyFrozenWorkspace(manifest, spec, context) {
|
|
|
80392
80446
|
}
|
|
80393
80447
|
return destinationRoot;
|
|
80394
80448
|
}
|
|
80395
|
-
function
|
|
80449
|
+
async function copyEvaluatorTests(spec, context) {
|
|
80450
|
+
const destinationRoot = fs81.mkdtempSync(path88.join(os16.tmpdir(), "brainbase-benchmark-tests-"));
|
|
80451
|
+
fs81.chmodSync(destinationRoot, 448);
|
|
80452
|
+
context.temporaryRoots.add(destinationRoot);
|
|
80453
|
+
const stack = [{ source: spec.tests_root, destination: destinationRoot }];
|
|
80454
|
+
while (stack.length > 0) {
|
|
80455
|
+
assertBudget(context);
|
|
80456
|
+
const current = stack.pop();
|
|
80457
|
+
const entries = fs81.readdirSync(current.source, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
|
|
80458
|
+
for (const entry of entries) {
|
|
80459
|
+
assertBudget(context);
|
|
80460
|
+
const source = path88.join(current.source, entry.name);
|
|
80461
|
+
const destination = path88.join(current.destination, entry.name);
|
|
80462
|
+
const stat = fs81.lstatSync(source);
|
|
80463
|
+
if (stat.isSymbolicLink()) {
|
|
80464
|
+
throw new BenchmarkPhaseError("unsafe_path", `evaluator reference tree contains a symlink: ${path88.relative(spec.tests_root, source)}`);
|
|
80465
|
+
}
|
|
80466
|
+
if (stat.isDirectory()) {
|
|
80467
|
+
fs81.mkdirSync(destination, { recursive: true, mode: stat.mode & 511 });
|
|
80468
|
+
stack.push({ source, destination });
|
|
80469
|
+
continue;
|
|
80470
|
+
}
|
|
80471
|
+
if (!stat.isFile()) {
|
|
80472
|
+
throw new BenchmarkPhaseError("unsafe_path", `evaluator reference tree contains an unsupported filesystem entry: ${path88.relative(spec.tests_root, source)}`);
|
|
80473
|
+
}
|
|
80474
|
+
await atomicCopy(source, destination, stat.mode & 511, spec.tests_root);
|
|
80475
|
+
const sourceRecord = await recordFile(spec.tests_root, source, "tests");
|
|
80476
|
+
const copiedRecord = await recordFile(destinationRoot, destination, "tests");
|
|
80477
|
+
if (copiedRecord.path !== sourceRecord.path || copiedRecord.sha256 !== sourceRecord.sha256 || copiedRecord.size !== sourceRecord.size || copiedRecord.mode !== sourceRecord.mode) {
|
|
80478
|
+
throw new BenchmarkPhaseError("evidence_tampered", `evaluator reference changed while it was copied: ${sourceRecord.path}`);
|
|
80479
|
+
}
|
|
80480
|
+
}
|
|
80481
|
+
}
|
|
80482
|
+
return destinationRoot;
|
|
80483
|
+
}
|
|
80484
|
+
function evaluatorTestsPath(evaluator, testsRoot) {
|
|
80396
80485
|
if (!evaluator.tests_path)
|
|
80397
|
-
return
|
|
80486
|
+
return testsRoot;
|
|
80398
80487
|
const relative = normalizedRootRelative(evaluator.tests_path);
|
|
80399
|
-
assertNoSymlinkTraversal(
|
|
80400
|
-
const candidate = path88.resolve(
|
|
80401
|
-
if (!isWithin(
|
|
80488
|
+
assertNoSymlinkTraversal(testsRoot, relative);
|
|
80489
|
+
const candidate = path88.resolve(testsRoot, relative);
|
|
80490
|
+
if (!isWithin(testsRoot, candidate) || !fs81.existsSync(candidate)) {
|
|
80402
80491
|
throw new BenchmarkPhaseError("invalid_tests_path", `evaluator tests_path does not exist: ${evaluator.tests_path}`);
|
|
80403
80492
|
}
|
|
80404
80493
|
const stat = fs81.lstatSync(candidate);
|
|
@@ -80623,12 +80712,14 @@ async function evaluateOne(evaluator, spec, manifest, finalOutput, trajectory, f
|
|
|
80623
80712
|
};
|
|
80624
80713
|
}
|
|
80625
80714
|
let isolatedWorkspace;
|
|
80715
|
+
let isolatedTestsRoot;
|
|
80626
80716
|
let privateResultRoot;
|
|
80627
80717
|
try {
|
|
80628
80718
|
const evaluatorWorkspace = await copyFrozenWorkspace(manifest, spec, context);
|
|
80629
80719
|
isolatedWorkspace = evaluatorWorkspace;
|
|
80630
|
-
|
|
80631
|
-
const
|
|
80720
|
+
isolatedTestsRoot = await copyEvaluatorTests(spec, context);
|
|
80721
|
+
const testsPath = evaluatorTestsPath(evaluator, isolatedTestsRoot);
|
|
80722
|
+
const commandRoot = evaluator.root === "workspace" ? evaluatorWorkspace : isolatedTestsRoot;
|
|
80632
80723
|
const command = { id: evaluator.id, ...evaluator.command };
|
|
80633
80724
|
const environment = {
|
|
80634
80725
|
BRAINBASE_BENCHMARK_WORKSPACE: evaluatorWorkspace,
|
|
@@ -80679,7 +80770,7 @@ async function evaluateOne(evaluator, spec, manifest, finalOutput, trajectory, f
|
|
|
80679
80770
|
...criterionResults ? { criterion_results: criterionResults } : {}
|
|
80680
80771
|
};
|
|
80681
80772
|
} finally {
|
|
80682
|
-
for (const temporary of [privateResultRoot, isolatedWorkspace]) {
|
|
80773
|
+
for (const temporary of [privateResultRoot, isolatedTestsRoot, isolatedWorkspace]) {
|
|
80683
80774
|
if (!temporary)
|
|
80684
80775
|
continue;
|
|
80685
80776
|
fs81.rmSync(temporary, { recursive: true, force: true });
|
|
@@ -80728,6 +80819,7 @@ async function executeEvaluate(spec, context) {
|
|
|
80728
80819
|
];
|
|
80729
80820
|
outputs.push(...frozenEvidenceRecords);
|
|
80730
80821
|
context.outputs.push(...frozenEvidenceRecords);
|
|
80822
|
+
assertEvaluateOutputBudget(spec, context);
|
|
80731
80823
|
assertBudget(context);
|
|
80732
80824
|
const manifest = await workspaceManifest(spec, context);
|
|
80733
80825
|
const manifestPath2 = path88.join(spec.logs_root, "candidate-workspace-manifest.json");
|
|
@@ -80740,6 +80832,7 @@ async function executeEvaluate(spec, context) {
|
|
|
80740
80832
|
const manifestRecord = await recordFile(spec.logs_root, manifestPath2, "logs");
|
|
80741
80833
|
outputs.push(manifestRecord);
|
|
80742
80834
|
context.outputs.push(manifestRecord);
|
|
80835
|
+
assertEvaluateOutputBudget(spec, context);
|
|
80743
80836
|
for (const artifactRelInput of spec.candidate_artifacts) {
|
|
80744
80837
|
const artifactRel = workspaceRel(artifactRelInput);
|
|
80745
80838
|
assertNoSymlinkTraversal(spec.workspace_root, artifactRel);
|
|
@@ -80757,11 +80850,13 @@ async function executeEvaluate(spec, context) {
|
|
|
80757
80850
|
outputs.push(artifact);
|
|
80758
80851
|
context.outputs.push(artifact);
|
|
80759
80852
|
}
|
|
80853
|
+
assertEvaluateOutputBudget(spec, context);
|
|
80760
80854
|
for (const candidateOutput of spec.candidate_outputs) {
|
|
80761
80855
|
const copied = await copyCandidateOutput(candidateOutput, manifest, spec, context);
|
|
80762
80856
|
outputs.push(...copied);
|
|
80763
80857
|
context.outputs.push(...copied);
|
|
80764
80858
|
}
|
|
80859
|
+
assertEvaluateOutputBudget(spec, context);
|
|
80765
80860
|
if (spec.capture_workspace_archive) {
|
|
80766
80861
|
const regularFiles = manifest.filter((entry) => entry.kind !== "symlink").map((entry) => entry.path);
|
|
80767
80862
|
const archive = path88.join(spec.logs_root, "candidate-workspace.tar.gz");
|
|
@@ -80775,6 +80870,7 @@ async function executeEvaluate(spec, context) {
|
|
|
80775
80870
|
const archiveRecord = await recordFile(spec.logs_root, archive, "logs");
|
|
80776
80871
|
outputs.push(archiveRecord);
|
|
80777
80872
|
context.outputs.push(archiveRecord);
|
|
80873
|
+
assertEvaluateOutputBudget(spec, context);
|
|
80778
80874
|
}
|
|
80779
80875
|
await verifyRecordsUnchanged(manifest, spec);
|
|
80780
80876
|
for (const reference of spec.references) {
|
|
@@ -80789,7 +80885,6 @@ async function executeEvaluate(spec, context) {
|
|
|
80789
80885
|
for (const evaluator of executionOrder) {
|
|
80790
80886
|
assertBudget(context);
|
|
80791
80887
|
const started = Date.now();
|
|
80792
|
-
let requiredResultError;
|
|
80793
80888
|
try {
|
|
80794
80889
|
const evaluated = await evaluateOne(evaluator, spec, manifest, finalOutput.buffer.toString("utf8"), trajectory, { finalOutputPath, trajectoryPath }, context);
|
|
80795
80890
|
assertBudget(context);
|
|
@@ -80803,13 +80898,14 @@ async function executeEvaluate(spec, context) {
|
|
|
80803
80898
|
outputs.push(evaluated.stderr);
|
|
80804
80899
|
context.outputs.push(evaluated.stderr);
|
|
80805
80900
|
}
|
|
80806
|
-
if (evaluated.status === "errored" && evaluator.required) {
|
|
80807
|
-
const errorCode = typeof evaluated.details?.error_code === "string" ? evaluated.details.error_code : "evaluator_execution_failed";
|
|
80808
|
-
const errorMessage2 = typeof evaluated.details?.error_message === "string" ? evaluated.details.error_message : "required evaluator execution failed";
|
|
80809
|
-
requiredResultError = new BenchmarkPhaseError(errorCode, errorMessage2);
|
|
80810
|
-
}
|
|
80811
80901
|
} catch (error2) {
|
|
80812
80902
|
const normalized = stableError(error2);
|
|
80903
|
+
let stdout;
|
|
80904
|
+
let stderr;
|
|
80905
|
+
if (error2 instanceof BenchmarkCommandExecutionError) {
|
|
80906
|
+
stdout = await writeLog(spec.logs_root, `${evaluator.id}.stdout.log`, error2.stdout, spec);
|
|
80907
|
+
stderr = await writeLog(spec.logs_root, `${evaluator.id}.stderr.log`, error2.stderr, spec);
|
|
80908
|
+
}
|
|
80813
80909
|
const errored = {
|
|
80814
80910
|
id: evaluator.id,
|
|
80815
80911
|
type: evaluator.type,
|
|
@@ -80819,26 +80915,38 @@ async function executeEvaluate(spec, context) {
|
|
|
80819
80915
|
verdict: null,
|
|
80820
80916
|
engine: "brainbase-cli",
|
|
80821
80917
|
engine_version: VERSION,
|
|
80822
|
-
duration_ms: Date.now() - started,
|
|
80918
|
+
duration_ms: error2 instanceof BenchmarkCommandExecutionError ? error2.durationMs : Date.now() - started,
|
|
80823
80919
|
details: {
|
|
80824
80920
|
error_code: normalized?.code ?? "phase_failed",
|
|
80825
80921
|
error_message: normalized?.message ?? "evaluator execution failed"
|
|
80826
|
-
}
|
|
80922
|
+
},
|
|
80923
|
+
...stdout ? { stdout } : {},
|
|
80924
|
+
...stderr ? { stderr } : {}
|
|
80827
80925
|
};
|
|
80828
80926
|
evaluators.push(errored);
|
|
80829
80927
|
context.evaluators.push(errored);
|
|
80830
|
-
if (
|
|
80928
|
+
if (stdout) {
|
|
80929
|
+
outputs.push(stdout);
|
|
80930
|
+
context.outputs.push(stdout);
|
|
80931
|
+
}
|
|
80932
|
+
if (stderr) {
|
|
80933
|
+
outputs.push(stderr);
|
|
80934
|
+
context.outputs.push(stderr);
|
|
80935
|
+
}
|
|
80936
|
+
if (!(error2 instanceof BenchmarkCommandExecutionError))
|
|
80831
80937
|
throw error2;
|
|
80832
80938
|
assertBudget(context);
|
|
80833
80939
|
}
|
|
80834
|
-
if (
|
|
80835
|
-
|
|
80940
|
+
if (evaluator.type === "sandbox_command") {
|
|
80941
|
+
assertEvaluateOutputBudget(spec, context);
|
|
80942
|
+
}
|
|
80836
80943
|
}
|
|
80837
80944
|
await verifyRecordsUnchanged([...context.inputs, ...context.outputs.slice(0, frozenOutputCount)], spec);
|
|
80838
80945
|
if (!verifyOwnedDirectory(spec.tests_root, "tests", spec) || !verifyOwnedDirectory(spec.logs_root, "logs", spec)) {
|
|
80839
80946
|
throw new BenchmarkPhaseError("evidence_tampered", "benchmark evaluator changed an owned phase directory marker");
|
|
80840
80947
|
}
|
|
80841
80948
|
assertBudget(context);
|
|
80949
|
+
assertEvaluateOutputBudget(spec, context);
|
|
80842
80950
|
evaluators.sort((left, right) => evaluatorOrder.get(left.id) - evaluatorOrder.get(right.id));
|
|
80843
80951
|
return { outputs, evaluators };
|
|
80844
80952
|
}
|
|
@@ -81024,6 +81132,7 @@ async function runBenchmarkPhase(specPathInput, resultPathInput, expectedPhase,
|
|
|
81024
81132
|
let status = "failed";
|
|
81025
81133
|
let error2;
|
|
81026
81134
|
let context;
|
|
81135
|
+
let validatedSpec;
|
|
81027
81136
|
let resultPathValidated = false;
|
|
81028
81137
|
try {
|
|
81029
81138
|
let bytes;
|
|
@@ -81043,6 +81152,7 @@ async function runBenchmarkPhase(specPathInput, resultPathInput, expectedPhase,
|
|
|
81043
81152
|
}
|
|
81044
81153
|
identity2 = rawIdentity(raw);
|
|
81045
81154
|
const spec = BenchmarkSpecSchema.parse(raw);
|
|
81155
|
+
validatedSpec = spec;
|
|
81046
81156
|
if (expectedPhase && spec.phase !== expectedPhase) {
|
|
81047
81157
|
throw new BenchmarkPhaseError("phase_mismatch", `the ${expectedPhase} command cannot execute a ${spec.phase} spec`);
|
|
81048
81158
|
}
|
|
@@ -81122,6 +81232,17 @@ async function runBenchmarkPhase(specPathInput, resultPathInput, expectedPhase,
|
|
|
81122
81232
|
if (!resultPathValidated || !context?.logsOwned) {
|
|
81123
81233
|
return { exitCode: status === "succeeded" ? 0 : 1, result: result2 };
|
|
81124
81234
|
}
|
|
81235
|
+
if (status === "succeeded" && validatedSpec?.phase === "evaluate") {
|
|
81236
|
+
try {
|
|
81237
|
+
const resultBytes = Buffer.byteLength(`${JSON.stringify(result2, null, 2)}
|
|
81238
|
+
`);
|
|
81239
|
+
assertEvaluateOutputBudget(validatedSpec, context, resultBytes);
|
|
81240
|
+
} catch (budgetError) {
|
|
81241
|
+
status = "failed";
|
|
81242
|
+
result2.status = "failed";
|
|
81243
|
+
result2.error = stableError(budgetError);
|
|
81244
|
+
}
|
|
81245
|
+
}
|
|
81125
81246
|
try {
|
|
81126
81247
|
writeJsonAtomic(resultPath, result2);
|
|
81127
81248
|
} catch (writeError) {
|