@brainbase-labs/cli 0.25.0-eng1209.5 → 0.25.0-eng1209.7
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 +68 -33
- 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.7",
|
|
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), {
|
|
@@ -80021,11 +80035,18 @@ async function runCommand(command, root, spec, context, additions = {}) {
|
|
|
80021
80035
|
};
|
|
80022
80036
|
child.stdout?.on("data", (chunk2) => capture(stdout, chunk2));
|
|
80023
80037
|
child.stderr?.on("data", (chunk2) => capture(stderr, chunk2));
|
|
80038
|
+
child.once("exit", () => {
|
|
80039
|
+
terminate(child);
|
|
80040
|
+
});
|
|
80024
80041
|
child.on("error", (error2) => {
|
|
80025
|
-
fail(new
|
|
80042
|
+
fail(new BenchmarkCommandExecutionError("command_start_failed", `failed to start ${command.id}: ${error2.message}`, Buffer.concat(stdout), Buffer.concat(stderr), Date.now() - started));
|
|
80026
80043
|
});
|
|
80027
80044
|
timer = setTimeout(() => {
|
|
80028
|
-
|
|
80045
|
+
if (reachesPhaseDeadline) {
|
|
80046
|
+
fail(new BenchmarkPhaseError("phase_timeout", "phase budget expired"));
|
|
80047
|
+
return;
|
|
80048
|
+
}
|
|
80049
|
+
fail(new BenchmarkCommandExecutionError("command_timeout", `command timed out: ${command.id}`, Buffer.concat(stdout), Buffer.concat(stderr), Date.now() - started));
|
|
80029
80050
|
}, timeoutMs2);
|
|
80030
80051
|
child.on("close", (code, signal) => {
|
|
80031
80052
|
if (settled)
|
|
@@ -80033,7 +80054,7 @@ async function runCommand(command, root, spec, context, additions = {}) {
|
|
|
80033
80054
|
settled = true;
|
|
80034
80055
|
clearTimeout(timer);
|
|
80035
80056
|
if (code === null) {
|
|
80036
|
-
reject2(new
|
|
80057
|
+
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
80058
|
return;
|
|
80038
80059
|
}
|
|
80039
80060
|
resolve({
|
|
@@ -80395,13 +80416,13 @@ async function copyCandidateOutput(output, manifest, spec, context) {
|
|
|
80395
80416
|
}
|
|
80396
80417
|
return copied;
|
|
80397
80418
|
}
|
|
80398
|
-
async function copyFrozenWorkspace(manifest, spec, context) {
|
|
80419
|
+
async function copyFrozenWorkspace(manifest, spec, context, sourceRoot = spec.workspace_root, preserveUnsafeSymlinks = false) {
|
|
80399
80420
|
const destinationRoot = fs81.mkdtempSync(path88.join(os16.tmpdir(), "brainbase-benchmark-workspace-"));
|
|
80400
80421
|
fs81.chmodSync(destinationRoot, 448);
|
|
80401
80422
|
context.temporaryRoots.add(destinationRoot);
|
|
80402
80423
|
for (const frozenFile of manifest) {
|
|
80403
80424
|
assertBudget(context);
|
|
80404
|
-
const source = path88.resolve(
|
|
80425
|
+
const source = path88.resolve(sourceRoot, safeRelPath(frozenFile.path));
|
|
80405
80426
|
const destination = path88.resolve(destinationRoot, safeRelPath(frozenFile.path));
|
|
80406
80427
|
if (frozenFile.kind === "symlink") {
|
|
80407
80428
|
const stat = fs81.lstatSync(source);
|
|
@@ -80409,18 +80430,18 @@ async function copyFrozenWorkspace(manifest, spec, context) {
|
|
|
80409
80430
|
if (target === null || Buffer.byteLength(target) !== frozenFile.size || sha256(target) !== frozenFile.sha256) {
|
|
80410
80431
|
throw new BenchmarkPhaseError("evidence_tampered", `workspace changed after it was frozen: ${frozenFile.path}`);
|
|
80411
80432
|
}
|
|
80412
|
-
if (path88.isAbsolute(target)) {
|
|
80433
|
+
if (!preserveUnsafeSymlinks && path88.isAbsolute(target)) {
|
|
80413
80434
|
throw new BenchmarkPhaseError("unsafe_workspace_symlink", `sandbox evaluator workspace cannot reproduce an absolute symlink: ${frozenFile.path}`);
|
|
80414
80435
|
}
|
|
80415
80436
|
const resolvedTarget = path88.resolve(path88.dirname(source), target);
|
|
80416
|
-
if (!isWithin(
|
|
80437
|
+
if (!preserveUnsafeSymlinks && !isWithin(sourceRoot, resolvedTarget)) {
|
|
80417
80438
|
throw new BenchmarkPhaseError("unsafe_workspace_symlink", `sandbox evaluator workspace symlink escapes the workspace: ${frozenFile.path}`);
|
|
80418
80439
|
}
|
|
80419
80440
|
fs81.mkdirSync(path88.dirname(destination), { recursive: true, mode: 448 });
|
|
80420
80441
|
fs81.symlinkSync(target, destination);
|
|
80421
80442
|
continue;
|
|
80422
80443
|
}
|
|
80423
|
-
await atomicCopy(source, destination, frozenFile.mode,
|
|
80444
|
+
await atomicCopy(source, destination, frozenFile.mode, sourceRoot);
|
|
80424
80445
|
const copied = await recordFile(destinationRoot, destination, "workspace");
|
|
80425
80446
|
if (copied.sha256 !== frozenFile.sha256 || copied.size !== frozenFile.size || copied.mode !== frozenFile.mode) {
|
|
80426
80447
|
throw new BenchmarkPhaseError("evidence_tampered", `workspace changed after it was frozen: ${frozenFile.path}`);
|
|
@@ -80495,7 +80516,7 @@ var CriterionResultSchema = exports_external.object({
|
|
|
80495
80516
|
var CriteriaResultFileSchema = exports_external.object({
|
|
80496
80517
|
criteria: exports_external.array(CriterionResultSchema).max(MAX_CRITERIA_PER_EVALUATOR)
|
|
80497
80518
|
}).strict();
|
|
80498
|
-
function readCriterionResults(resultPath, criterionKeys, allowedEvidenceIds) {
|
|
80519
|
+
function readCriterionResults(resultPath, criterionKeys, allowedEvidenceIds, spec) {
|
|
80499
80520
|
let opened;
|
|
80500
80521
|
try {
|
|
80501
80522
|
opened = openRegularFileNoFollow(resultPath, "criterion result", path88.dirname(resultPath));
|
|
@@ -80539,7 +80560,13 @@ function readCriterionResults(resultPath, criterionKeys, allowedEvidenceIds) {
|
|
|
80539
80560
|
if (unknownEvidenceIds.length > 0) {
|
|
80540
80561
|
throw new BenchmarkPhaseError("invalid_criterion_result", "criterion result cites evidence outside the evaluator plan", { unknown_evidence_ids: unknownEvidenceIds });
|
|
80541
80562
|
}
|
|
80542
|
-
return criterionKeys.map((key2) =>
|
|
80563
|
+
return criterionKeys.map((key2) => {
|
|
80564
|
+
const criterion = byKey.get(key2);
|
|
80565
|
+
return {
|
|
80566
|
+
...criterion,
|
|
80567
|
+
explanation: redactCommandOutput(Buffer.from(criterion.explanation), spec).toString("utf8")
|
|
80568
|
+
};
|
|
80569
|
+
});
|
|
80543
80570
|
} finally {
|
|
80544
80571
|
fs81.closeSync(opened.fd);
|
|
80545
80572
|
}
|
|
@@ -80562,7 +80589,7 @@ function eventType(event) {
|
|
|
80562
80589
|
}
|
|
80563
80590
|
return;
|
|
80564
80591
|
}
|
|
80565
|
-
async function evaluateOne(evaluator, spec, manifest, finalOutput, trajectory, frozenEvidence, context) {
|
|
80592
|
+
async function evaluateOne(evaluator, spec, manifest, frozenWorkspaceRoot, finalOutput, trajectory, frozenEvidence, context) {
|
|
80566
80593
|
const started = Date.now();
|
|
80567
80594
|
const base2 = {
|
|
80568
80595
|
id: evaluator.id,
|
|
@@ -80635,8 +80662,8 @@ async function evaluateOne(evaluator, spec, manifest, finalOutput, trajectory, f
|
|
|
80635
80662
|
}
|
|
80636
80663
|
if (evaluator.type === "workspace_assertion") {
|
|
80637
80664
|
const relative = workspaceRel(evaluator.path);
|
|
80638
|
-
assertNoSymlinkTraversal(
|
|
80639
|
-
const candidate = path88.resolve(
|
|
80665
|
+
assertNoSymlinkTraversal(frozenWorkspaceRoot, relative);
|
|
80666
|
+
const candidate = path88.resolve(frozenWorkspaceRoot, relative);
|
|
80640
80667
|
let stat = null;
|
|
80641
80668
|
try {
|
|
80642
80669
|
stat = fs81.lstatSync(candidate);
|
|
@@ -80657,7 +80684,7 @@ async function evaluateOne(evaluator, spec, manifest, finalOutput, trajectory, f
|
|
|
80657
80684
|
verdict = !exists2;
|
|
80658
80685
|
if (evaluator.assertion.operator === "sha256") {
|
|
80659
80686
|
if (stat?.isFile()) {
|
|
80660
|
-
const opened = openRegularFileNoFollow(candidate, `workspace assertion ${relative}`,
|
|
80687
|
+
const opened = openRegularFileNoFollow(candidate, `workspace assertion ${relative}`, frozenWorkspaceRoot);
|
|
80661
80688
|
try {
|
|
80662
80689
|
actualSha256 = await sha256OfDescriptor(opened.fd);
|
|
80663
80690
|
verdict = actualSha256 === evaluator.assertion.expected;
|
|
@@ -80668,7 +80695,7 @@ async function evaluateOne(evaluator, spec, manifest, finalOutput, trajectory, f
|
|
|
80668
80695
|
}
|
|
80669
80696
|
if (evaluator.assertion.operator === "contains") {
|
|
80670
80697
|
if (stat?.isFile()) {
|
|
80671
|
-
const opened = openRegularFileNoFollow(candidate, `workspace assertion ${relative}`,
|
|
80698
|
+
const opened = openRegularFileNoFollow(candidate, `workspace assertion ${relative}`, frozenWorkspaceRoot);
|
|
80672
80699
|
try {
|
|
80673
80700
|
verdict = readDescriptor(opened.fd).toString("utf8").includes(evaluator.assertion.expected);
|
|
80674
80701
|
} finally {
|
|
@@ -80697,7 +80724,7 @@ async function evaluateOne(evaluator, spec, manifest, finalOutput, trajectory, f
|
|
|
80697
80724
|
let isolatedTestsRoot;
|
|
80698
80725
|
let privateResultRoot;
|
|
80699
80726
|
try {
|
|
80700
|
-
const evaluatorWorkspace = await copyFrozenWorkspace(manifest, spec, context);
|
|
80727
|
+
const evaluatorWorkspace = await copyFrozenWorkspace(manifest, spec, context, frozenWorkspaceRoot);
|
|
80701
80728
|
isolatedWorkspace = evaluatorWorkspace;
|
|
80702
80729
|
isolatedTestsRoot = await copyEvaluatorTests(spec, context);
|
|
80703
80730
|
const testsPath = evaluatorTestsPath(evaluator, isolatedTestsRoot);
|
|
@@ -80723,7 +80750,7 @@ async function evaluateOne(evaluator, spec, manifest, finalOutput, trajectory, f
|
|
|
80723
80750
|
const stderr = await writeLog(spec.logs_root, `${evaluator.id}.stderr.log`, result2.stderr, spec);
|
|
80724
80751
|
let criterionResults;
|
|
80725
80752
|
try {
|
|
80726
|
-
criterionResults = evaluator.criterion_keys && criterionResultPath ? readCriterionResults(criterionResultPath, evaluator.criterion_keys, evaluator.allowed_evidence_ids ?? []) : undefined;
|
|
80753
|
+
criterionResults = evaluator.criterion_keys && criterionResultPath ? readCriterionResults(criterionResultPath, evaluator.criterion_keys, evaluator.allowed_evidence_ids ?? [], spec) : undefined;
|
|
80727
80754
|
} catch (error2) {
|
|
80728
80755
|
const normalized = stableError(error2);
|
|
80729
80756
|
return {
|
|
@@ -80855,21 +80882,20 @@ async function executeEvaluate(spec, context) {
|
|
|
80855
80882
|
assertEvaluateOutputBudget(spec, context);
|
|
80856
80883
|
}
|
|
80857
80884
|
await verifyRecordsUnchanged(manifest, spec);
|
|
80885
|
+
const frozenWorkspaceRoot = await copyFrozenWorkspace(manifest, spec, context, spec.workspace_root, true);
|
|
80858
80886
|
for (const reference of spec.references) {
|
|
80859
80887
|
const referenceOutputs = await copyMaterial(reference, spec.staging_root, spec.tests_root, "tests", false, context);
|
|
80860
80888
|
outputs.push(...referenceOutputs);
|
|
80861
80889
|
context.outputs.push(...referenceOutputs);
|
|
80862
80890
|
}
|
|
80863
|
-
const frozenOutputCount = context.outputs.length;
|
|
80864
80891
|
const evaluators = [];
|
|
80865
80892
|
const evaluatorOrder = new Map(spec.evaluators.map((evaluator, index) => [evaluator.id, index]));
|
|
80866
80893
|
const executionOrder = [...spec.evaluators].sort((left, right) => Number(left.type === "sandbox_command") - Number(right.type === "sandbox_command"));
|
|
80867
80894
|
for (const evaluator of executionOrder) {
|
|
80868
80895
|
assertBudget(context);
|
|
80869
80896
|
const started = Date.now();
|
|
80870
|
-
let requiredResultError;
|
|
80871
80897
|
try {
|
|
80872
|
-
const evaluated = await evaluateOne(evaluator, spec, manifest, finalOutput.buffer.toString("utf8"), trajectory, { finalOutputPath, trajectoryPath }, context);
|
|
80898
|
+
const evaluated = await evaluateOne(evaluator, spec, manifest, frozenWorkspaceRoot, finalOutput.buffer.toString("utf8"), trajectory, { finalOutputPath, trajectoryPath }, context);
|
|
80873
80899
|
assertBudget(context);
|
|
80874
80900
|
evaluators.push(evaluated);
|
|
80875
80901
|
context.evaluators.push(evaluated);
|
|
@@ -80881,13 +80907,14 @@ async function executeEvaluate(spec, context) {
|
|
|
80881
80907
|
outputs.push(evaluated.stderr);
|
|
80882
80908
|
context.outputs.push(evaluated.stderr);
|
|
80883
80909
|
}
|
|
80884
|
-
if (evaluated.status === "errored" && evaluator.required) {
|
|
80885
|
-
const errorCode = typeof evaluated.details?.error_code === "string" ? evaluated.details.error_code : "evaluator_execution_failed";
|
|
80886
|
-
const errorMessage2 = typeof evaluated.details?.error_message === "string" ? evaluated.details.error_message : "required evaluator execution failed";
|
|
80887
|
-
requiredResultError = new BenchmarkPhaseError(errorCode, errorMessage2);
|
|
80888
|
-
}
|
|
80889
80910
|
} catch (error2) {
|
|
80890
80911
|
const normalized = stableError(error2);
|
|
80912
|
+
let stdout;
|
|
80913
|
+
let stderr;
|
|
80914
|
+
if (error2 instanceof BenchmarkCommandExecutionError) {
|
|
80915
|
+
stdout = await writeLog(spec.logs_root, `${evaluator.id}.stdout.log`, error2.stdout, spec);
|
|
80916
|
+
stderr = await writeLog(spec.logs_root, `${evaluator.id}.stderr.log`, error2.stderr, spec);
|
|
80917
|
+
}
|
|
80891
80918
|
const errored = {
|
|
80892
80919
|
id: evaluator.id,
|
|
80893
80920
|
type: evaluator.type,
|
|
@@ -80897,25 +80924,33 @@ async function executeEvaluate(spec, context) {
|
|
|
80897
80924
|
verdict: null,
|
|
80898
80925
|
engine: "brainbase-cli",
|
|
80899
80926
|
engine_version: VERSION,
|
|
80900
|
-
duration_ms: Date.now() - started,
|
|
80927
|
+
duration_ms: error2 instanceof BenchmarkCommandExecutionError ? error2.durationMs : Date.now() - started,
|
|
80901
80928
|
details: {
|
|
80902
80929
|
error_code: normalized?.code ?? "phase_failed",
|
|
80903
80930
|
error_message: normalized?.message ?? "evaluator execution failed"
|
|
80904
|
-
}
|
|
80931
|
+
},
|
|
80932
|
+
...stdout ? { stdout } : {},
|
|
80933
|
+
...stderr ? { stderr } : {}
|
|
80905
80934
|
};
|
|
80906
80935
|
evaluators.push(errored);
|
|
80907
80936
|
context.evaluators.push(errored);
|
|
80908
|
-
if (
|
|
80937
|
+
if (stdout) {
|
|
80938
|
+
outputs.push(stdout);
|
|
80939
|
+
context.outputs.push(stdout);
|
|
80940
|
+
}
|
|
80941
|
+
if (stderr) {
|
|
80942
|
+
outputs.push(stderr);
|
|
80943
|
+
context.outputs.push(stderr);
|
|
80944
|
+
}
|
|
80945
|
+
if (!(error2 instanceof BenchmarkCommandExecutionError))
|
|
80909
80946
|
throw error2;
|
|
80910
80947
|
assertBudget(context);
|
|
80911
80948
|
}
|
|
80912
|
-
if (requiredResultError)
|
|
80913
|
-
throw requiredResultError;
|
|
80914
80949
|
if (evaluator.type === "sandbox_command") {
|
|
80915
80950
|
assertEvaluateOutputBudget(spec, context);
|
|
80916
80951
|
}
|
|
80917
80952
|
}
|
|
80918
|
-
await verifyRecordsUnchanged([...context.inputs, ...context.outputs
|
|
80953
|
+
await verifyRecordsUnchanged([...context.inputs, ...context.outputs], spec);
|
|
80919
80954
|
if (!verifyOwnedDirectory(spec.tests_root, "tests", spec) || !verifyOwnedDirectory(spec.logs_root, "logs", spec)) {
|
|
80920
80955
|
throw new BenchmarkPhaseError("evidence_tampered", "benchmark evaluator changed an owned phase directory marker");
|
|
80921
80956
|
}
|