@arjunkhera/atlas 0.3.36 → 0.3.38
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/.claude-plugin/plugin.json +1 -1
- package/door/kit-releases.json +8 -0
- package/package.json +1 -1
- package/tests/contract.mjs +10 -2
- package/tests/model.mjs +6 -3
package/door/kit-releases.json
CHANGED
|
@@ -32,6 +32,14 @@
|
|
|
32
32
|
{
|
|
33
33
|
"kit_sha256": "c4a506ec261d2d2fd7884943c9d317fb7b522704f4f63669b5bd37d32326bde5",
|
|
34
34
|
"first_package": "0.3.32"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"kit_sha256": "b5c36f685ba476e09a54e3207e2444b098cc6a26dded8dca65b01e751fe2cbe4",
|
|
38
|
+
"first_package": "0.3.34"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"kit_sha256": "c00e87170dd5f1b477d144eca976db76580d94ede6104d76609aac040851d488",
|
|
42
|
+
"first_package": "0.3.37"
|
|
35
43
|
}
|
|
36
44
|
]
|
|
37
45
|
}
|
package/package.json
CHANGED
package/tests/contract.mjs
CHANGED
|
@@ -117,6 +117,12 @@ function load(path, options) {
|
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
const listOf = (x) => (Array.isArray(x) ? x.map(String) : x === undefined ? [] : [String(x)]);
|
|
120
|
+
const oneLine = (t) => String(t ?? '').replace(/\s+/g, ' ').trim();
|
|
121
|
+
// The reason of each run of a repeat that did not pass, for the log: "; run 2: ..., run 3: ...".
|
|
122
|
+
const whyNot = (list) => {
|
|
123
|
+
const lines = list.filter((r) => r.result !== 'pass' && r.result !== 'not here').map((r) => `run ${r.run}: ${oneLine(r.error ?? r.why ?? r.stopped ?? r.result).slice(0, 240)}`);
|
|
124
|
+
return lines.length ? `; ${lines.join('; ')}` : '';
|
|
125
|
+
};
|
|
120
126
|
|
|
121
127
|
export function scenario(path, body, options = {}) {
|
|
122
128
|
const ctx = load(path, options);
|
|
@@ -238,7 +244,7 @@ export function scenario(path, body, options = {}) {
|
|
|
238
244
|
a.result = blocked ? 'blocked' : ok ? 'pass' : unsure && passed + unsure >= repeat.pass ? 'unsure' : 'fail';
|
|
239
245
|
a.proof = {
|
|
240
246
|
repeat: { runs: repeat.runs, pass: repeat.pass, passed }, runs: list,
|
|
241
|
-
...(blocked ? { why: `the repeat stopped in run ${list.length}: ${state.redactor.text(error.message)}` } : ok ? {} : { error: `passed in ${passed} of ${list.length} runs; the rule is ${repeat.pass} of ${repeat.runs}` }),
|
|
247
|
+
...(blocked ? { why: `the repeat stopped in run ${list.length}: ${state.redactor.text(error.message)}` } : ok ? {} : { error: `passed in ${passed} of ${list.length} runs; the rule is ${repeat.pass} of ${repeat.runs}${whyNot(list)}` }),
|
|
242
248
|
};
|
|
243
249
|
}
|
|
244
250
|
ev.write();
|
|
@@ -454,7 +460,9 @@ function makeRun({ ctx, state, way, env, ev, adapter, round = null }) {
|
|
|
454
460
|
if (!key) throw new Blocked(`the judge "${names[0]}" needs the key ${keyName}: list it in secrets of tests.yaml, and give its value`);
|
|
455
461
|
const out = await askJudge({ name: names[0], judge, words: a.words, evidence, key, meter: state.meter, redactor: state.redactor });
|
|
456
462
|
open('run.judge');
|
|
457
|
-
|
|
463
|
+
// A judge that did not pass says why in its own words: the first answer that is not YES.
|
|
464
|
+
const doubt = out.answers.find((x) => x.answer !== 'YES')?.reply;
|
|
465
|
+
ev.setResult(a.fullId, target, out.result, { judge: names[0], answers: out.answers, cost: out.cost, calls, settled_by: way, ...(out.result === 'pass' ? {} : { error: doubt ? `${out.why}: ${state.redactor.text(oneLine(doubt)).slice(0, 200)}` : out.why }) });
|
|
458
466
|
},
|
|
459
467
|
// Money that a product's own model call spent (the router, say), read from its answer.
|
|
460
468
|
// It counts against budget.money with the judge and the agent calls.
|
package/tests/model.mjs
CHANGED
|
@@ -289,11 +289,14 @@ export async function runClaude({ prompt, args = [], key, cwd, meter, what, reda
|
|
|
289
289
|
// A call with no cost in its answer counts its whole hold: the meter never guesses low. The hold is at
|
|
290
290
|
// most a quarter of the cap, so one bad call does not end the night.
|
|
291
291
|
meter.add(Number.isFinite(cost) ? cost : left, what, id);
|
|
292
|
-
if (!envelope) throw new Error(`${what}: the model command gave no answer (exit ${out.exit}): ${(redactor ? redactor.text(out.stderr || out.stdout) : out.stderr || out.stdout).slice(0, 400)}`);
|
|
293
292
|
const clean = (t) => (redactor ? redactor.text(t) : t);
|
|
293
|
+
// No answer at all: the command could not run (a missing binary, say). That is no product result
|
|
294
|
+
// either, so it reads blocked, and the log shows what the command printed.
|
|
295
|
+
if (!envelope) throw new Blocked(`${what}: the model command gave no answer (exit ${out.exit}): ${clean(String(out.stderr || out.stdout).trim()).slice(0, 400)}`);
|
|
294
296
|
// An error answer with no cost never reached the model: a refused sign-in, no credit, a bad model
|
|
295
|
-
// name. The scenario cannot pass or fail on it, so it
|
|
296
|
-
|
|
297
|
+
// name. Newer claude commands give a cost of 0 there. The scenario cannot pass or fail on it, so it
|
|
298
|
+
// reads blocked, with the reason.
|
|
299
|
+
if (envelope.is_error && !(cost > 0)) throw new Blocked(`${what}: the model call failed before the model answered: ${clean(String(envelope.result ?? envelope.error ?? (out.stderr || out.stdout))).slice(0, 400)}`);
|
|
297
300
|
if (out.signal === 'SIGKILL') throw new Error(`${what}: the model call ran past ${Math.round(timeoutMs / 1000)} seconds and was stopped`);
|
|
298
301
|
return { exit: out.exit, stdout: clean(out.stdout), stderr: clean(out.stderr), envelope, events, cost: Number.isFinite(cost) ? cost : null };
|
|
299
302
|
} finally {
|