@rulvar/evals 1.238.0 → 1.239.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/dist/index.js +552 -309
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { join } from "node:path";
|
|
|
7
7
|
import { ANTHROPIC_PRICING, anthropic } from "@rulvar/anthropic";
|
|
8
8
|
import { reconcileStatement } from "@rulvar/openai";
|
|
9
9
|
import { orchestratePlanned } from "@rulvar/plan";
|
|
10
|
-
import { FAKE_MODEL_REF, FakeAdapter, fakeToolCalls } from "@rulvar/testing";
|
|
10
|
+
import { FAKE_MODEL_REF, FakeAdapter, fakeToolCalls, fakeWireError } from "@rulvar/testing";
|
|
11
11
|
//#region src/envelope.ts
|
|
12
12
|
/**
|
|
13
13
|
* The debit-only aggregate spend envelope (v1.16.2 review P1-2). A
|
|
@@ -3107,305 +3107,171 @@ const scriptedCaps = () => ({
|
|
|
3107
3107
|
outputUsdPerMTok: 10
|
|
3108
3108
|
}
|
|
3109
3109
|
});
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
const runArm = async (mode) => {
|
|
3140
|
-
const calls = [];
|
|
3141
|
-
const adapter = {
|
|
3142
|
-
id: "fake",
|
|
3143
|
-
calls,
|
|
3144
|
-
caps: scriptedCaps,
|
|
3145
|
-
async *stream(req) {
|
|
3146
|
-
const call = calls.length;
|
|
3147
|
-
calls.push(req);
|
|
3148
|
-
await Promise.resolve();
|
|
3149
|
-
if (scriptedAgentType(req) !== "") {
|
|
3150
|
-
yield {
|
|
3151
|
-
type: "text-delta",
|
|
3152
|
-
text: "settled evidence"
|
|
3153
|
-
};
|
|
3154
|
-
yield {
|
|
3155
|
-
type: "finish",
|
|
3156
|
-
finish: { reason: "stop" },
|
|
3157
|
-
usage: {
|
|
3158
|
-
inputTokens: 10,
|
|
3159
|
-
outputTokens: 5,
|
|
3160
|
-
cacheReadTokens: 0,
|
|
3161
|
-
cacheWriteTokens: 0
|
|
3162
|
-
}
|
|
3163
|
-
};
|
|
3164
|
-
return;
|
|
3165
|
-
}
|
|
3166
|
-
if (!(req.tools ?? []).some((tool) => tool.name === "spawn_agent")) {
|
|
3167
|
-
for (const event of scriptedToolEvents("finish", { result: "the redeemed synthesis" }, `id-${String(call)}-0`)) yield event;
|
|
3168
|
-
yield {
|
|
3169
|
-
type: "finish",
|
|
3170
|
-
finish: { reason: "tool-calls" },
|
|
3171
|
-
usage: {
|
|
3172
|
-
inputTokens: 12,
|
|
3173
|
-
outputTokens: 8,
|
|
3174
|
-
cacheReadTokens: 0,
|
|
3175
|
-
cacheWriteTokens: 0
|
|
3176
|
-
}
|
|
3177
|
-
};
|
|
3178
|
-
return;
|
|
3179
|
-
}
|
|
3180
|
-
const turn = calls.filter((prior) => scriptedAgentType(prior) === "" && (prior.tools ?? []).some((tool) => tool.name === "spawn_agent")).length === 1 ? scriptedToolEvents("spawn_agent", {
|
|
3181
|
-
agentType: "worker",
|
|
3182
|
-
prompt: "gather A"
|
|
3183
|
-
}, `id-${String(call)}-0`).concat(scriptedToolEvents("spawn_agent", {
|
|
3184
|
-
agentType: "worker",
|
|
3185
|
-
prompt: "gather B"
|
|
3186
|
-
}, `id-${String(call)}-1`)) : scriptedToolEvents("finish", { result: "unreachable" }, `id-${String(call)}-0`);
|
|
3187
|
-
for (const event of turn) yield event;
|
|
3110
|
+
/**
|
|
3111
|
+
* The reserve line and its redemption, in BOTH drive modes (RV2101,
|
|
3112
|
+
* DEF-7). The first paid parity runs died bare exactly here: the
|
|
3113
|
+
* coordination turn whose spent + held synthesis reserve + proposed
|
|
3114
|
+
* crossed the orchestrator cap tore the run down with the reserve
|
|
3115
|
+
* intact and unreachable. The fold is now typed 'budget-floor' and the
|
|
3116
|
+
* held reserve FUNDS the synthesis the run kept it for; the PlanRunner
|
|
3117
|
+
* extension arm must produce the same fold and the same redeemed
|
|
3118
|
+
* result, which is the DEF-7 parity this scenario documents.
|
|
3119
|
+
*/
|
|
3120
|
+
const parityReserveLineRedemption = {
|
|
3121
|
+
name: "parity-reserve-line-redemption",
|
|
3122
|
+
doctrine: "a coordination turn refused at the reserve line folds typed 'budget-floor' and the held synthesis reserve funds the redemption whose result rides the partial envelope (RV2101); the PlanRunner extension arm produces the same fold and the same redeemed result (DEF-7)",
|
|
3123
|
+
async run() {
|
|
3124
|
+
const runArm = async (mode) => {
|
|
3125
|
+
const calls = [];
|
|
3126
|
+
const adapter = {
|
|
3127
|
+
id: "fake",
|
|
3128
|
+
calls,
|
|
3129
|
+
caps: scriptedCaps,
|
|
3130
|
+
async *stream(req) {
|
|
3131
|
+
const call = calls.length;
|
|
3132
|
+
calls.push(req);
|
|
3133
|
+
await Promise.resolve();
|
|
3134
|
+
if (scriptedAgentType(req) !== "") {
|
|
3135
|
+
yield {
|
|
3136
|
+
type: "text-delta",
|
|
3137
|
+
text: "settled evidence"
|
|
3138
|
+
};
|
|
3188
3139
|
yield {
|
|
3189
3140
|
type: "finish",
|
|
3190
|
-
finish: { reason: "
|
|
3141
|
+
finish: { reason: "stop" },
|
|
3191
3142
|
usage: {
|
|
3192
3143
|
inputTokens: 10,
|
|
3193
|
-
outputTokens:
|
|
3144
|
+
outputTokens: 5,
|
|
3194
3145
|
cacheReadTokens: 0,
|
|
3195
3146
|
cacheWriteTokens: 0
|
|
3196
3147
|
}
|
|
3197
3148
|
};
|
|
3149
|
+
return;
|
|
3198
3150
|
}
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
const engine = createEngine({
|
|
3202
|
-
adapters: [adapter],
|
|
3203
|
-
stores: { journal: store },
|
|
3204
|
-
defaults: {
|
|
3205
|
-
routing: {
|
|
3206
|
-
loop: "fake:model",
|
|
3207
|
-
orchestrate: "fake:model",
|
|
3208
|
-
synthesize: "fake:model"
|
|
3209
|
-
},
|
|
3210
|
-
profiles: { worker: { description: "the cheap gatherer" } }
|
|
3211
|
-
}
|
|
3212
|
-
});
|
|
3213
|
-
const opts = {
|
|
3214
|
-
limits: { maxOutputTokensPerTurn: 1e3 },
|
|
3215
|
-
synthesis: {
|
|
3216
|
-
estCost: .006,
|
|
3217
|
-
limits: { maxOutputTokensPerTurn: 500 }
|
|
3218
|
-
},
|
|
3219
|
-
budget: {
|
|
3220
|
-
capUsd: .03,
|
|
3221
|
-
synthesisReserveUsd: .02,
|
|
3222
|
-
finalizeReserveUsd: 0
|
|
3223
|
-
}
|
|
3224
|
-
};
|
|
3225
|
-
const runId = `fault-reserve-line-${mode}`;
|
|
3226
|
-
const outcome = mode === "workflow" ? await engine.run(makeOrchestratorWorkflow("the reserve line shape", opts), void 0, {
|
|
3227
|
-
runId,
|
|
3228
|
-
budgetUsd: 10
|
|
3229
|
-
}).result : await orchestratePlanned(engine, "the reserve line shape", opts, { runId }).result;
|
|
3230
|
-
const entries = await store.load(runId);
|
|
3231
|
-
const fallback = entries.find((entry) => entry.kind === "decision" && entry.value?.decisionType === "orchestrator_finalize_fallback");
|
|
3232
|
-
const settle = entries.some((entry) => entry.kind === "decision" && entry.value?.decisionType === "run_settle");
|
|
3233
|
-
const value = outcome.value;
|
|
3234
|
-
return {
|
|
3235
|
-
status: outcome.status,
|
|
3236
|
-
error: outcome.error?.message,
|
|
3237
|
-
forcedFinishFallback: value?.forcedFinishFallback,
|
|
3238
|
-
completion: value?.completion,
|
|
3239
|
-
result: value?.result,
|
|
3240
|
-
fallbackReason: (fallback?.value)?.reason,
|
|
3241
|
-
rootClassCalls: calls.filter((req) => scriptedAgentType(req) === "").length,
|
|
3242
|
-
workerOkTerminals: entries.filter((entry) => entry.kind === "agent" && entry.status === "ok").length,
|
|
3243
|
-
settleRecorded: settle,
|
|
3244
|
-
entries
|
|
3245
|
-
};
|
|
3246
|
-
};
|
|
3247
|
-
const arms = {
|
|
3248
|
-
workflow: await runArm("workflow"),
|
|
3249
|
-
extension: await runArm("extension")
|
|
3250
|
-
};
|
|
3251
|
-
const armMatched = (arm) => arm.status === "exhausted" && arm.forcedFinishFallback === true && arm.completion === "partial" && arm.result === "the redeemed synthesis" && arm.fallbackReason === "budget-floor" && arm.rootClassCalls === 2 && arm.settleRecorded;
|
|
3252
|
-
return {
|
|
3253
|
-
observation: {
|
|
3254
|
-
matched: armMatched(arms.workflow) && armMatched(arms.extension),
|
|
3255
|
-
detail: `workflow arm '${arms.workflow.status}' reason=${String(arms.workflow.fallbackReason)} result=${JSON.stringify(arms.workflow.result)} rootCalls=${String(arms.workflow.rootClassCalls)}; extension arm '${arms.extension.status}' reason=${String(arms.extension.fallbackReason)} result=${JSON.stringify(arms.extension.result)} rootCalls=${String(arms.extension.rootClassCalls)} (DEF-7 parity: both arms fold 'budget-floor' and both redeem the synthesis from the held reserve)`
|
|
3256
|
-
},
|
|
3257
|
-
artifacts: [
|
|
3258
|
-
jsonArtifact("arms.json", {
|
|
3259
|
-
workflow: {
|
|
3260
|
-
...arms.workflow,
|
|
3261
|
-
entries: void 0
|
|
3262
|
-
},
|
|
3263
|
-
extension: {
|
|
3264
|
-
...arms.extension,
|
|
3265
|
-
entries: void 0
|
|
3266
|
-
}
|
|
3267
|
-
}),
|
|
3268
|
-
jsonArtifact("journal-workflow.json", arms.workflow.entries),
|
|
3269
|
-
jsonArtifact("journal-extension.json", arms.extension.entries)
|
|
3270
|
-
]
|
|
3271
|
-
};
|
|
3272
|
-
}
|
|
3273
|
-
},
|
|
3274
|
-
{
|
|
3275
|
-
name: "resume-spawn-famine",
|
|
3276
|
-
doctrine: "a resume re-admits recovered agents without re-counting them against lifetimeSpawnCap (RV2201): the kill-mid-fan-out journal resumes to the finished dossier at the EXACT cap, with no 'lifetime spawn cap' decline journaled and only the unsettled workers re-paid; the c7 resume starved its judge and synthesis on re-counted admissions",
|
|
3277
|
-
async run() {
|
|
3278
|
-
const makeAdapter = () => {
|
|
3279
|
-
const calls = [];
|
|
3280
|
-
return {
|
|
3281
|
-
id: "fake",
|
|
3282
|
-
calls,
|
|
3283
|
-
caps: scriptedCaps,
|
|
3284
|
-
async *stream(req) {
|
|
3285
|
-
const call = calls.length;
|
|
3286
|
-
calls.push(req);
|
|
3287
|
-
await Promise.resolve();
|
|
3288
|
-
if (scriptedAgentType(req) !== "") {
|
|
3289
|
-
yield {
|
|
3290
|
-
type: "text-delta",
|
|
3291
|
-
text: "gathered evidence"
|
|
3292
|
-
};
|
|
3293
|
-
yield {
|
|
3294
|
-
type: "finish",
|
|
3295
|
-
finish: { reason: "stop" },
|
|
3296
|
-
usage: {
|
|
3297
|
-
inputTokens: 10,
|
|
3298
|
-
outputTokens: 5,
|
|
3299
|
-
cacheReadTokens: 0,
|
|
3300
|
-
cacheWriteTokens: 0
|
|
3301
|
-
}
|
|
3302
|
-
};
|
|
3303
|
-
return;
|
|
3304
|
-
}
|
|
3305
|
-
if (!(req.tools ?? []).some((tool) => tool.name === "spawn_agent")) {
|
|
3306
|
-
for (const event of scriptedToolEvents("finish", { result: "the resumed dossier" }, `id-${String(call)}-0`)) yield event;
|
|
3307
|
-
yield {
|
|
3308
|
-
type: "finish",
|
|
3309
|
-
finish: { reason: "tool-calls" },
|
|
3310
|
-
usage: {
|
|
3311
|
-
inputTokens: 12,
|
|
3312
|
-
outputTokens: 8,
|
|
3313
|
-
cacheReadTokens: 0,
|
|
3314
|
-
cacheWriteTokens: 0
|
|
3315
|
-
}
|
|
3316
|
-
};
|
|
3317
|
-
return;
|
|
3318
|
-
}
|
|
3319
|
-
const turn = calls.filter((prior) => scriptedAgentType(prior) === "" && (prior.tools ?? []).some((tool) => tool.name === "spawn_agent")).length === 1 ? scriptedToolEvents("spawn_agent", {
|
|
3320
|
-
agentType: "worker",
|
|
3321
|
-
prompt: "gather A"
|
|
3322
|
-
}, `id-${String(call)}-0`).concat(scriptedToolEvents("spawn_agent", {
|
|
3323
|
-
agentType: "worker",
|
|
3324
|
-
prompt: "gather B"
|
|
3325
|
-
}, `id-${String(call)}-1`), scriptedToolEvents("spawn_agent", {
|
|
3326
|
-
agentType: "worker",
|
|
3327
|
-
prompt: "gather C"
|
|
3328
|
-
}, `id-${String(call)}-2`)) : scriptedToolEvents("finish", { result: "the coordination draft" }, `id-${String(call)}-0`);
|
|
3329
|
-
for (const event of turn) yield event;
|
|
3151
|
+
if (!(req.tools ?? []).some((tool) => tool.name === "spawn_agent")) {
|
|
3152
|
+
for (const event of scriptedToolEvents("finish", { result: "the redeemed synthesis" }, `id-${String(call)}-0`)) yield event;
|
|
3330
3153
|
yield {
|
|
3331
3154
|
type: "finish",
|
|
3332
3155
|
finish: { reason: "tool-calls" },
|
|
3333
3156
|
usage: {
|
|
3334
|
-
inputTokens:
|
|
3335
|
-
outputTokens:
|
|
3157
|
+
inputTokens: 12,
|
|
3158
|
+
outputTokens: 8,
|
|
3336
3159
|
cacheReadTokens: 0,
|
|
3337
3160
|
cacheWriteTokens: 0
|
|
3338
3161
|
}
|
|
3339
3162
|
};
|
|
3163
|
+
return;
|
|
3340
3164
|
}
|
|
3341
|
-
|
|
3165
|
+
const turn = calls.filter((prior) => scriptedAgentType(prior) === "" && (prior.tools ?? []).some((tool) => tool.name === "spawn_agent")).length === 1 ? scriptedToolEvents("spawn_agent", {
|
|
3166
|
+
agentType: "worker",
|
|
3167
|
+
prompt: "gather A"
|
|
3168
|
+
}, `id-${String(call)}-0`).concat(scriptedToolEvents("spawn_agent", {
|
|
3169
|
+
agentType: "worker",
|
|
3170
|
+
prompt: "gather B"
|
|
3171
|
+
}, `id-${String(call)}-1`)) : scriptedToolEvents("finish", { result: "unreachable" }, `id-${String(call)}-0`);
|
|
3172
|
+
for (const event of turn) yield event;
|
|
3173
|
+
yield {
|
|
3174
|
+
type: "finish",
|
|
3175
|
+
finish: { reason: "tool-calls" },
|
|
3176
|
+
usage: {
|
|
3177
|
+
inputTokens: 10,
|
|
3178
|
+
outputTokens: 1e3,
|
|
3179
|
+
cacheReadTokens: 0,
|
|
3180
|
+
cacheWriteTokens: 0
|
|
3181
|
+
}
|
|
3182
|
+
};
|
|
3183
|
+
}
|
|
3342
3184
|
};
|
|
3343
|
-
const
|
|
3344
|
-
const
|
|
3345
|
-
synthesis: {
|
|
3346
|
-
estCost: .006,
|
|
3347
|
-
limits: { maxOutputTokensPerTurn: 500 }
|
|
3348
|
-
},
|
|
3349
|
-
budget: { finalizeReserveUsd: 0 }
|
|
3350
|
-
});
|
|
3351
|
-
const makeEngine = (adapter, store) => createEngine({
|
|
3185
|
+
const store = new InMemoryStore();
|
|
3186
|
+
const engine = createEngine({
|
|
3352
3187
|
adapters: [adapter],
|
|
3353
3188
|
stores: { journal: store },
|
|
3354
|
-
budgetDefaults: { lifetimeSpawnCap: LIFETIME_SPAWNS },
|
|
3355
3189
|
defaults: {
|
|
3356
3190
|
routing: {
|
|
3357
3191
|
loop: "fake:model",
|
|
3358
3192
|
orchestrate: "fake:model",
|
|
3359
3193
|
synthesize: "fake:model"
|
|
3360
3194
|
},
|
|
3361
|
-
profiles: { worker: { description: "the
|
|
3195
|
+
profiles: { worker: { description: "the cheap gatherer" } }
|
|
3362
3196
|
}
|
|
3363
3197
|
});
|
|
3364
|
-
const
|
|
3365
|
-
|
|
3366
|
-
|
|
3198
|
+
const opts = {
|
|
3199
|
+
limits: { maxOutputTokensPerTurn: 1e3 },
|
|
3200
|
+
synthesis: {
|
|
3201
|
+
estCost: .006,
|
|
3202
|
+
limits: { maxOutputTokensPerTurn: 500 }
|
|
3203
|
+
},
|
|
3204
|
+
budget: {
|
|
3205
|
+
capUsd: .03,
|
|
3206
|
+
synthesisReserveUsd: .02,
|
|
3207
|
+
finalizeReserveUsd: 0
|
|
3208
|
+
}
|
|
3209
|
+
};
|
|
3210
|
+
const runId = `fault-reserve-line-${mode}`;
|
|
3211
|
+
const outcome = mode === "workflow" ? await engine.run(makeOrchestratorWorkflow("the reserve line shape", opts), void 0, {
|
|
3212
|
+
runId,
|
|
3367
3213
|
budgetUsd: 10
|
|
3368
|
-
}).result;
|
|
3369
|
-
|
|
3370
|
-
const
|
|
3371
|
-
const
|
|
3372
|
-
|
|
3373
|
-
const cut = entriesA.slice(0, firstWorkerOk + 1);
|
|
3374
|
-
const storeB = new InMemoryStore();
|
|
3375
|
-
for (const entry of cut) await storeB.append("fault-resume-famine", entry);
|
|
3376
|
-
const resumeAdapter = makeAdapter();
|
|
3377
|
-
const resumed = await makeEngine(resumeAdapter, storeB).resume("fault-resume-famine", wf).result;
|
|
3378
|
-
const entriesB = await storeB.load("fault-resume-famine");
|
|
3379
|
-
const capDeclines = entriesB.filter((entry) => entry.kind === "decision" && JSON.stringify(entry.value ?? {}).includes("lifetime spawn cap"));
|
|
3380
|
-
const redemptionDeclines = entriesB.filter((entry) => entry.kind === "decision" && entry.value?.decisionType === "orchestrator_synthesis_redemption_declined");
|
|
3381
|
-
const liveWorkerCalls = resumeAdapter.calls.filter((req) => scriptedAgentType(req) !== "").length;
|
|
3382
|
-
const distinctAgentScopes = new Set(entriesB.filter((entry) => entry.kind === "agent" && entry.status === "running").map((entry) => `${entry.scope}#${String(entry.key)}`)).size;
|
|
3214
|
+
}).result : await orchestratePlanned(engine, "the reserve line shape", opts, { runId }).result;
|
|
3215
|
+
const entries = await store.load(runId);
|
|
3216
|
+
const fallback = entries.find((entry) => entry.kind === "decision" && entry.value?.decisionType === "orchestrator_finalize_fallback");
|
|
3217
|
+
const settle = entries.some((entry) => entry.kind === "decision" && entry.value?.decisionType === "run_settle");
|
|
3218
|
+
const value = outcome.value;
|
|
3383
3219
|
return {
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
}),
|
|
3395
|
-
jsonArtifact("journal-resumed.json", entriesB)
|
|
3396
|
-
]
|
|
3220
|
+
status: outcome.status,
|
|
3221
|
+
error: outcome.error?.message,
|
|
3222
|
+
forcedFinishFallback: value?.forcedFinishFallback,
|
|
3223
|
+
completion: value?.completion,
|
|
3224
|
+
result: value?.result,
|
|
3225
|
+
fallbackReason: (fallback?.value)?.reason,
|
|
3226
|
+
rootClassCalls: calls.filter((req) => scriptedAgentType(req) === "").length,
|
|
3227
|
+
workerOkTerminals: entries.filter((entry) => entry.kind === "agent" && entry.status === "ok").length,
|
|
3228
|
+
settleRecorded: settle,
|
|
3229
|
+
entries
|
|
3397
3230
|
};
|
|
3398
|
-
}
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3231
|
+
};
|
|
3232
|
+
const arms = {
|
|
3233
|
+
workflow: await runArm("workflow"),
|
|
3234
|
+
extension: await runArm("extension")
|
|
3235
|
+
};
|
|
3236
|
+
const armMatched = (arm) => arm.status === "exhausted" && arm.forcedFinishFallback === true && arm.completion === "partial" && arm.result === "the redeemed synthesis" && arm.fallbackReason === "budget-floor" && arm.rootClassCalls === 2 && arm.settleRecorded;
|
|
3237
|
+
return {
|
|
3238
|
+
observation: {
|
|
3239
|
+
matched: armMatched(arms.workflow) && armMatched(arms.extension),
|
|
3240
|
+
detail: `workflow arm '${arms.workflow.status}' reason=${String(arms.workflow.fallbackReason)} result=${JSON.stringify(arms.workflow.result)} rootCalls=${String(arms.workflow.rootClassCalls)}; extension arm '${arms.extension.status}' reason=${String(arms.extension.fallbackReason)} result=${JSON.stringify(arms.extension.result)} rootCalls=${String(arms.extension.rootClassCalls)} (DEF-7 parity: both arms fold 'budget-floor' and both redeem the synthesis from the held reserve)`
|
|
3241
|
+
},
|
|
3242
|
+
artifacts: [
|
|
3243
|
+
jsonArtifact("arms.json", {
|
|
3244
|
+
workflow: {
|
|
3245
|
+
...arms.workflow,
|
|
3246
|
+
entries: void 0
|
|
3247
|
+
},
|
|
3248
|
+
extension: {
|
|
3249
|
+
...arms.extension,
|
|
3250
|
+
entries: void 0
|
|
3251
|
+
}
|
|
3252
|
+
}),
|
|
3253
|
+
jsonArtifact("journal-workflow.json", arms.workflow.entries),
|
|
3254
|
+
jsonArtifact("journal-extension.json", arms.extension.entries)
|
|
3255
|
+
]
|
|
3256
|
+
};
|
|
3257
|
+
}
|
|
3258
|
+
};
|
|
3259
|
+
/**
|
|
3260
|
+
* The c7 resume famine, closed (RV2201). The kill-mid-fan-out journal
|
|
3261
|
+
* of the seventh subscription run resumed to an ACCEPTED acceptance and
|
|
3262
|
+
* then starved: recovered agents were re-counted against
|
|
3263
|
+
* lifetimeSpawnCap, the judge fell to a typed decline naming the cap,
|
|
3264
|
+
* and the synthesis spawn died exhausted with the money reserve intact.
|
|
3265
|
+
* The counter now counts a scope a single time across the run's whole
|
|
3266
|
+
* life, so the exact-cap resume finishes its dossier.
|
|
3267
|
+
*/
|
|
3268
|
+
const resumeSpawnFamine = {
|
|
3269
|
+
name: "resume-spawn-famine",
|
|
3270
|
+
doctrine: "a resume re-admits recovered agents without re-counting them against lifetimeSpawnCap (RV2201): the kill-mid-fan-out journal resumes to the finished dossier at the EXACT cap, with no 'lifetime spawn cap' decline journaled and only the unsettled workers re-paid; the c7 resume starved its judge and synthesis on re-counted admissions",
|
|
3271
|
+
async run() {
|
|
3272
|
+
const makeAdapter = () => {
|
|
3406
3273
|
const calls = [];
|
|
3407
|
-
|
|
3408
|
-
const adapter = {
|
|
3274
|
+
return {
|
|
3409
3275
|
id: "fake",
|
|
3410
3276
|
calls,
|
|
3411
3277
|
caps: scriptedCaps,
|
|
@@ -3413,66 +3279,443 @@ const SCENARIOS = [
|
|
|
3413
3279
|
const call = calls.length;
|
|
3414
3280
|
calls.push(req);
|
|
3415
3281
|
await Promise.resolve();
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3282
|
+
if (scriptedAgentType(req) !== "") {
|
|
3283
|
+
yield {
|
|
3284
|
+
type: "text-delta",
|
|
3285
|
+
text: "gathered evidence"
|
|
3286
|
+
};
|
|
3287
|
+
yield {
|
|
3288
|
+
type: "finish",
|
|
3289
|
+
finish: { reason: "stop" },
|
|
3290
|
+
usage: {
|
|
3291
|
+
inputTokens: 10,
|
|
3292
|
+
outputTokens: 5,
|
|
3293
|
+
cacheReadTokens: 0,
|
|
3294
|
+
cacheWriteTokens: 0
|
|
3295
|
+
}
|
|
3296
|
+
};
|
|
3297
|
+
return;
|
|
3298
|
+
}
|
|
3299
|
+
if (!(req.tools ?? []).some((tool) => tool.name === "spawn_agent")) {
|
|
3300
|
+
for (const event of scriptedToolEvents("finish", { result: "the resumed dossier" }, `id-${String(call)}-0`)) yield event;
|
|
3301
|
+
yield {
|
|
3302
|
+
type: "finish",
|
|
3303
|
+
finish: { reason: "tool-calls" },
|
|
3304
|
+
usage: {
|
|
3305
|
+
inputTokens: 12,
|
|
3306
|
+
outputTokens: 8,
|
|
3307
|
+
cacheReadTokens: 0,
|
|
3308
|
+
cacheWriteTokens: 0
|
|
3309
|
+
}
|
|
3310
|
+
};
|
|
3311
|
+
return;
|
|
3312
|
+
}
|
|
3313
|
+
const turn = calls.filter((prior) => scriptedAgentType(prior) === "" && (prior.tools ?? []).some((tool) => tool.name === "spawn_agent")).length === 1 ? scriptedToolEvents("spawn_agent", {
|
|
3314
|
+
agentType: "worker",
|
|
3315
|
+
prompt: "gather A"
|
|
3316
|
+
}, `id-${String(call)}-0`).concat(scriptedToolEvents("spawn_agent", {
|
|
3317
|
+
agentType: "worker",
|
|
3318
|
+
prompt: "gather B"
|
|
3319
|
+
}, `id-${String(call)}-1`), scriptedToolEvents("spawn_agent", {
|
|
3320
|
+
agentType: "worker",
|
|
3321
|
+
prompt: "gather C"
|
|
3322
|
+
}, `id-${String(call)}-2`)) : scriptedToolEvents("finish", { result: "the coordination draft" }, `id-${String(call)}-0`);
|
|
3323
|
+
for (const event of turn) yield event;
|
|
3419
3324
|
yield {
|
|
3420
3325
|
type: "finish",
|
|
3421
3326
|
finish: { reason: "tool-calls" },
|
|
3422
3327
|
usage: {
|
|
3423
3328
|
inputTokens: 10,
|
|
3424
|
-
outputTokens:
|
|
3329
|
+
outputTokens: 5,
|
|
3425
3330
|
cacheReadTokens: 0,
|
|
3426
3331
|
cacheWriteTokens: 0
|
|
3427
3332
|
}
|
|
3428
3333
|
};
|
|
3429
3334
|
}
|
|
3430
3335
|
};
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3336
|
+
};
|
|
3337
|
+
const LIFETIME_SPAWNS = 5;
|
|
3338
|
+
const wf = makeOrchestratorWorkflow("the resumable fan-out", {
|
|
3339
|
+
synthesis: {
|
|
3340
|
+
estCost: .006,
|
|
3341
|
+
limits: { maxOutputTokensPerTurn: 500 }
|
|
3342
|
+
},
|
|
3343
|
+
budget: { finalizeReserveUsd: 0 }
|
|
3344
|
+
});
|
|
3345
|
+
const makeEngine = (adapter, store) => createEngine({
|
|
3346
|
+
adapters: [adapter],
|
|
3347
|
+
stores: { journal: store },
|
|
3348
|
+
budgetDefaults: { lifetimeSpawnCap: LIFETIME_SPAWNS },
|
|
3349
|
+
defaults: {
|
|
3350
|
+
routing: {
|
|
3436
3351
|
loop: "fake:model",
|
|
3437
|
-
orchestrate: "fake:model"
|
|
3438
|
-
|
|
3352
|
+
orchestrate: "fake:model",
|
|
3353
|
+
synthesize: "fake:model"
|
|
3354
|
+
},
|
|
3355
|
+
profiles: { worker: { description: "the resumable gatherer" } }
|
|
3356
|
+
}
|
|
3357
|
+
});
|
|
3358
|
+
const storeA = new InMemoryStore();
|
|
3359
|
+
const seeded = await makeEngine(makeAdapter(), storeA).run(wf, void 0, {
|
|
3360
|
+
runId: "fault-resume-famine",
|
|
3361
|
+
budgetUsd: 10
|
|
3362
|
+
}).result;
|
|
3363
|
+
if (seeded.status !== "ok") throw new Error(`fault kit: the seeding run settled '${seeded.status}' instead of ok`);
|
|
3364
|
+
const entriesA = await storeA.load("fault-resume-famine");
|
|
3365
|
+
const firstWorkerOk = entriesA.findIndex((entry) => entry.kind === "agent" && entry.status === "ok");
|
|
3366
|
+
if (firstWorkerOk < 0) throw new Error("fault kit: the seeding journal carries no worker terminal to cut at");
|
|
3367
|
+
const cut = entriesA.slice(0, firstWorkerOk + 1);
|
|
3368
|
+
const storeB = new InMemoryStore();
|
|
3369
|
+
for (const entry of cut) await storeB.append("fault-resume-famine", entry);
|
|
3370
|
+
const resumeAdapter = makeAdapter();
|
|
3371
|
+
const resumed = await makeEngine(resumeAdapter, storeB).resume("fault-resume-famine", wf).result;
|
|
3372
|
+
const entriesB = await storeB.load("fault-resume-famine");
|
|
3373
|
+
const capDeclines = entriesB.filter((entry) => entry.kind === "decision" && JSON.stringify(entry.value ?? {}).includes("lifetime spawn cap"));
|
|
3374
|
+
const redemptionDeclines = entriesB.filter((entry) => entry.kind === "decision" && entry.value?.decisionType === "orchestrator_synthesis_redemption_declined");
|
|
3375
|
+
const liveWorkerCalls = resumeAdapter.calls.filter((req) => scriptedAgentType(req) !== "").length;
|
|
3376
|
+
const distinctAgentScopes = new Set(entriesB.filter((entry) => entry.kind === "agent" && entry.status === "running").map((entry) => `${entry.scope}#${String(entry.key)}`)).size;
|
|
3377
|
+
return {
|
|
3378
|
+
observation: {
|
|
3379
|
+
matched: resumed.status === "ok" && resumed.value === "the resumed dossier" && capDeclines.length === 0 && redemptionDeclines.length === 0 && liveWorkerCalls === 2 && distinctAgentScopes === LIFETIME_SPAWNS,
|
|
3380
|
+
detail: `resumed '${resumed.status}' result=${JSON.stringify(resumed.value)} at lifetimeSpawnCap ${String(LIFETIME_SPAWNS)} (${String(distinctAgentScopes)} distinct lifetime agent scopes); cap declines journaled=${String(capDeclines.length)}, redemption declines=${String(redemptionDeclines.length)}, live worker calls in the resumed segment=${String(liveWorkerCalls)} (the settled worker replayed free)`
|
|
3381
|
+
},
|
|
3382
|
+
artifacts: [
|
|
3383
|
+
jsonArtifact("journal-cut.json", cut),
|
|
3384
|
+
jsonArtifact("resume-outcome.json", {
|
|
3385
|
+
status: resumed.status,
|
|
3386
|
+
value: resumed.value ?? null,
|
|
3387
|
+
liveWorkerCalls
|
|
3388
|
+
}),
|
|
3389
|
+
jsonArtifact("journal-resumed.json", entriesB)
|
|
3390
|
+
]
|
|
3391
|
+
};
|
|
3392
|
+
}
|
|
3393
|
+
};
|
|
3394
|
+
/**
|
|
3395
|
+
* The c3 validator trap, converging (RV2202). The third subscription
|
|
3396
|
+
* run was pinned between two verdicts: evidence-grade demanded a run id
|
|
3397
|
+
* beside the live-observed claim, the model wove the id into a cited
|
|
3398
|
+
* sentence, cited-value lawfully rejected the id as a value absent from
|
|
3399
|
+
* the cited window, and both repairs burned without an exit. The
|
|
3400
|
+
* evidence-grade reason now NAMES the safe composition, so the same
|
|
3401
|
+
* trap converges in one repair round with cited-value silent. It also
|
|
3402
|
+
* names the id ITSELF (RV2501): the 1.226.0 comparison run obeyed the
|
|
3403
|
+
* same reason with an id no artifact pattern could match, so the
|
|
3404
|
+
* instruction was unexecutable and both repairs burned again. And the
|
|
3405
|
+
* composition it names is now the DIRECT one (RV2502): with the id in
|
|
3406
|
+
* hand cited-value reads it as identity rather than as a value asserted
|
|
3407
|
+
* about the cited line, so the corrected finish here writes this run's
|
|
3408
|
+
* own id in the graded sentence BESIDE the citation, the exact shape
|
|
3409
|
+
* the old bundle could not accept from either side.
|
|
3410
|
+
*/
|
|
3411
|
+
const validatorGuidanceConflict = {
|
|
3412
|
+
name: "validator-guidance-conflict",
|
|
3413
|
+
doctrine: "the evidence-grade reason names the SAFE composition against its cited-value sibling and names the run id it wants written (RV2202, RV2501, RV2502): the c3 trap finish repairs in ONE round by carrying THIS run's own id in the graded sentence, beside a source citation, with cited-value reading that id as identity and never rejecting; the third subscription run burned both repairs between the two verdicts, and the 1.226.0 comparison run burned both again on an id no artifact pattern could match",
|
|
3414
|
+
async run() {
|
|
3415
|
+
const TRAP_FINISH = "The reserve fold is live-observed under sustained load. The engine seals the journal at settle (`README.md:3`).";
|
|
3416
|
+
const FIXED_FINISH = "The reserve fold is live-observed under sustained load in run `fault-guidance-conflict`, where the engine seals the journal at settle (`README.md:3`).";
|
|
3417
|
+
const calls = [];
|
|
3418
|
+
let finishAttempts = 0;
|
|
3419
|
+
const adapter = {
|
|
3420
|
+
id: "fake",
|
|
3421
|
+
calls,
|
|
3422
|
+
caps: scriptedCaps,
|
|
3423
|
+
async *stream(req) {
|
|
3424
|
+
const call = calls.length;
|
|
3425
|
+
calls.push(req);
|
|
3426
|
+
await Promise.resolve();
|
|
3427
|
+
finishAttempts += 1;
|
|
3428
|
+
const result = finishAttempts === 1 ? TRAP_FINISH : FIXED_FINISH;
|
|
3429
|
+
for (const event of scriptedToolEvents("finish", { result }, `id-${String(call)}-0`)) yield event;
|
|
3430
|
+
yield {
|
|
3431
|
+
type: "finish",
|
|
3432
|
+
finish: { reason: "tool-calls" },
|
|
3433
|
+
usage: {
|
|
3434
|
+
inputTokens: 10,
|
|
3435
|
+
outputTokens: 40,
|
|
3436
|
+
cacheReadTokens: 0,
|
|
3437
|
+
cacheWriteTokens: 0
|
|
3438
|
+
}
|
|
3439
|
+
};
|
|
3440
|
+
}
|
|
3441
|
+
};
|
|
3442
|
+
const store = new InMemoryStore();
|
|
3443
|
+
const engine = createEngine({
|
|
3444
|
+
adapters: [adapter],
|
|
3445
|
+
stores: { journal: store },
|
|
3446
|
+
defaults: { routing: {
|
|
3447
|
+
loop: "fake:model",
|
|
3448
|
+
orchestrate: "fake:model"
|
|
3449
|
+
} }
|
|
3450
|
+
});
|
|
3451
|
+
const resolveSource = (target) => target.path === "README.md" ? "the rulvar engine\nholds one denominator\nthe engine seals the journal at settle\n" : void 0;
|
|
3452
|
+
const wf = makeOrchestratorWorkflow("the guidance trap", { finishValidation: {
|
|
3453
|
+
validators: [evidenceGradeValidator(), citedValueValidator({
|
|
3454
|
+
resolve: resolveSource,
|
|
3455
|
+
window: 2
|
|
3456
|
+
})],
|
|
3457
|
+
maxRepairs: 2,
|
|
3458
|
+
repairTurnReserve: 2
|
|
3459
|
+
} });
|
|
3460
|
+
const outcome = await engine.run(wf, void 0, {
|
|
3461
|
+
runId: "fault-guidance-conflict",
|
|
3462
|
+
budgetUsd: 10
|
|
3463
|
+
}).result;
|
|
3464
|
+
const entries = await store.load("fault-guidance-conflict");
|
|
3465
|
+
const repairRequest = calls[1];
|
|
3466
|
+
const repairBytes = JSON.stringify(repairRequest?.messages ?? []);
|
|
3467
|
+
const guidanceQuoted = repairBytes.includes("write this run's id fault-guidance-conflict") && repairBytes.includes("may share a sentence with a source citation");
|
|
3468
|
+
const citedValueNamed = repairBytes.includes("cited-value reads a run id as identity");
|
|
3469
|
+
const decisionsText = JSON.stringify(entries.filter((entry) => entry.kind === "decision").map((entry) => entry.value ?? null));
|
|
3470
|
+
const citedValueRejected = decisionsText.includes("\"cited-value\"") ? decisionsText.includes("not present inside the cited window") : false;
|
|
3471
|
+
return {
|
|
3472
|
+
observation: {
|
|
3473
|
+
matched: outcome.status === "ok" && outcome.value === FIXED_FINISH && finishAttempts === 2 && guidanceQuoted && citedValueNamed && !citedValueRejected,
|
|
3474
|
+
detail: `run '${outcome.status}' after ${String(finishAttempts)} finish attempt(s); the repair exchange named the run id and the shared-sentence composition (${String(guidanceQuoted)}) and named the identity reading (${String(citedValueNamed)}); cited-value rejected=${String(citedValueRejected)}; final result carries this run's own id beside the citation in the graded sentence: ${String(outcome.value === FIXED_FINISH)}`
|
|
3475
|
+
},
|
|
3476
|
+
artifacts: [
|
|
3477
|
+
jsonArtifact("outcome.json", {
|
|
3478
|
+
status: outcome.status,
|
|
3479
|
+
value: outcome.value ?? null
|
|
3480
|
+
}),
|
|
3481
|
+
{
|
|
3482
|
+
name: "repair-request.json",
|
|
3483
|
+
content: repairBytes
|
|
3484
|
+
},
|
|
3485
|
+
jsonArtifact("journal.json", entries)
|
|
3486
|
+
]
|
|
3487
|
+
};
|
|
3488
|
+
}
|
|
3489
|
+
};
|
|
3490
|
+
const TAIL_POOL_READING = "A failed audit write does not mask success (`src/exec.ts:256-296`).";
|
|
3491
|
+
const TAIL_DRAFT_INVERTED = "draft: an audit-write failure does not turn success into failure [src/exec.ts:256-296].";
|
|
3492
|
+
const TAIL_FINAL_INVERTED = "final: an audit-write failure does not turn success into failure [src/exec.ts:256-296].";
|
|
3493
|
+
const TAIL_FINAL_STILL_INVERTED = "final: the repaired text still flips the recorded outcome [src/exec.ts:256-296].";
|
|
3494
|
+
const TAIL_FINAL_CLEAN = "final: a failed audit write does not mask success [src/exec.ts:256-296].";
|
|
3495
|
+
const TAIL_FINDS = { contradictions: [{
|
|
3496
|
+
pair: 0,
|
|
3497
|
+
reason: "the draft inverts the recorded reading"
|
|
3498
|
+
}] };
|
|
3499
|
+
const TAIL_AGREES = { contradictions: [] };
|
|
3500
|
+
function tailHandles(req) {
|
|
3501
|
+
const handles = [];
|
|
3502
|
+
for (const msg of req.messages) for (const part of msg.parts) {
|
|
3503
|
+
if (part.type !== "tool-result") continue;
|
|
3504
|
+
const result = part.result;
|
|
3505
|
+
if (typeof result?.handle === "number") handles.push(result.handle);
|
|
3506
|
+
if (Array.isArray(result?.handles)) handles.push(...result.handles.filter((h) => typeof h === "number"));
|
|
3507
|
+
}
|
|
3508
|
+
return handles;
|
|
3509
|
+
}
|
|
3510
|
+
/**
|
|
3511
|
+
* One worker reads the span, the loop finishes with the inverted
|
|
3512
|
+
* draft, the composition finishes with `finals` in call order, and the
|
|
3513
|
+
* final stage judge answers through `judge` (a structured verdict or a
|
|
3514
|
+
* scripted wire death). Label keys ride first so the judge and the
|
|
3515
|
+
* composition route exactly, never through the prompt regex.
|
|
3516
|
+
*/
|
|
3517
|
+
function tailAdapter(options) {
|
|
3518
|
+
let judgeCalls = 0;
|
|
3519
|
+
let synthCalls = 0;
|
|
3520
|
+
let loopTurns = 0;
|
|
3521
|
+
return new FakeAdapter({ agents: {
|
|
3522
|
+
"claim-consistency-judge-final": () => options.judge(judgeCalls += 1),
|
|
3523
|
+
"final-composition": () => fakeToolCalls({
|
|
3524
|
+
name: "finish",
|
|
3525
|
+
args: { result: options.finals[Math.min(synthCalls++, options.finals.length - 1)] }
|
|
3526
|
+
}),
|
|
3527
|
+
worker: TAIL_POOL_READING,
|
|
3528
|
+
"*": (call) => {
|
|
3529
|
+
loopTurns += 1;
|
|
3530
|
+
if (loopTurns === 1) return fakeToolCalls({
|
|
3531
|
+
name: "spawn_agent",
|
|
3532
|
+
args: {
|
|
3533
|
+
agentType: "worker",
|
|
3534
|
+
prompt: "read the recorded span"
|
|
3535
|
+
}
|
|
3536
|
+
});
|
|
3537
|
+
if (loopTurns === 2) return fakeToolCalls({
|
|
3538
|
+
name: "await_all",
|
|
3539
|
+
args: { handles: tailHandles(call.req) }
|
|
3540
|
+
});
|
|
3541
|
+
return fakeToolCalls({
|
|
3542
|
+
name: "finish",
|
|
3543
|
+
args: { result: TAIL_DRAFT_INVERTED }
|
|
3439
3544
|
});
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3545
|
+
}
|
|
3546
|
+
} });
|
|
3547
|
+
}
|
|
3548
|
+
function tailEngine(adapter) {
|
|
3549
|
+
const store = new InMemoryStore();
|
|
3550
|
+
return {
|
|
3551
|
+
engine: createEngine({
|
|
3552
|
+
adapters: [adapter],
|
|
3553
|
+
stores: { journal: store },
|
|
3554
|
+
defaults: {
|
|
3555
|
+
routing: {
|
|
3556
|
+
loop: FAKE_MODEL_REF,
|
|
3557
|
+
orchestrate: FAKE_MODEL_REF,
|
|
3558
|
+
synthesize: FAKE_MODEL_REF,
|
|
3559
|
+
extract: FAKE_MODEL_REF
|
|
3560
|
+
},
|
|
3561
|
+
profiles: { worker: { description: "reads one span" } }
|
|
3562
|
+
}
|
|
3563
|
+
}),
|
|
3564
|
+
store
|
|
3565
|
+
};
|
|
3566
|
+
}
|
|
3567
|
+
const TAIL_OPTS = {
|
|
3568
|
+
acceptance: { childPolicy: "all-ok" },
|
|
3569
|
+
synthesis: { limits: { maxTurns: 3 } }
|
|
3570
|
+
};
|
|
3571
|
+
function tailSpans(entries) {
|
|
3572
|
+
const settled = entries.filter((entry) => entry.kind === "agent" && entry.status !== "running");
|
|
3573
|
+
return {
|
|
3574
|
+
compositions: settled.filter((entry) => entry.costAttribution?.label === "final-composition"),
|
|
3575
|
+
judges: settled.filter((entry) => entry.costAttribution?.label === "claim-consistency-judge-final")
|
|
3576
|
+
};
|
|
3577
|
+
}
|
|
3578
|
+
const SCENARIOS = [
|
|
3579
|
+
inFlightExposure,
|
|
3580
|
+
duplicateQuotaRule,
|
|
3581
|
+
tornJsonlTail,
|
|
3582
|
+
gluedJsonlTail,
|
|
3583
|
+
crashResumeSettleBoundary,
|
|
3584
|
+
pricingRotationUncoveredTail,
|
|
3585
|
+
unknownProviderId,
|
|
3586
|
+
nanStatementRefusal,
|
|
3587
|
+
tokenMismatchDivergence,
|
|
3588
|
+
auditMissingFieldFinding,
|
|
3589
|
+
anthropic1hPriced,
|
|
3590
|
+
pauseTurnUnits,
|
|
3591
|
+
preAdmissionCountRefusal,
|
|
3592
|
+
forcedFinishCompletion,
|
|
3593
|
+
settlementTerminalHonesty,
|
|
3594
|
+
ttlLiveBudgetParity,
|
|
3595
|
+
pauseTurnRealAdapter,
|
|
3596
|
+
statementSettleableGuard,
|
|
3597
|
+
supersededTerminalHonesty,
|
|
3598
|
+
tierCrossingLiveParity,
|
|
3599
|
+
benchmarkPrimaryPreflightParity,
|
|
3600
|
+
benchmarkRecoveryRootExposure,
|
|
3601
|
+
parityQuiescenceDeadlock,
|
|
3602
|
+
paritySequentialRosterFloor,
|
|
3603
|
+
parityReserveLineRedemption,
|
|
3604
|
+
resumeSpawnFamine,
|
|
3605
|
+
validatorGuidanceConflict,
|
|
3606
|
+
{
|
|
3607
|
+
name: "repair-round-honesty",
|
|
3608
|
+
doctrine: "the bounded post judge repair consumes the named finding (RV3307): one more composition carries the findings, the re-judge clears it, the run settles ok with the meta describing the repaired document (judgedStage 'final', findings 0, judgedHash equal to the shipped finalHash), two compositions and two final judge passes in the journal, and the invoice in the same denominator as the envelope",
|
|
3609
|
+
async run() {
|
|
3610
|
+
const { engine, store } = tailEngine(tailAdapter({
|
|
3611
|
+
judge: (call) => call === 1 ? TAIL_FINDS : TAIL_AGREES,
|
|
3612
|
+
finals: [TAIL_FINAL_INVERTED, TAIL_FINAL_CLEAN]
|
|
3613
|
+
}));
|
|
3614
|
+
const outcome = await engine.run(makeOrchestratorWorkflow("audit the executor", {
|
|
3615
|
+
...TAIL_OPTS,
|
|
3616
|
+
claimConsistency: {
|
|
3617
|
+
stage: "final",
|
|
3618
|
+
onFound: "repair"
|
|
3619
|
+
}
|
|
3620
|
+
}), void 0, {
|
|
3621
|
+
runId: "fault-repair-honesty",
|
|
3451
3622
|
budgetUsd: 10
|
|
3452
3623
|
}).result;
|
|
3453
|
-
const
|
|
3454
|
-
const
|
|
3455
|
-
const
|
|
3456
|
-
const
|
|
3457
|
-
const citedValueNamed = repairBytes.includes("cited-value reads a run id as identity");
|
|
3458
|
-
const decisionsText = JSON.stringify(entries.filter((entry) => entry.kind === "decision").map((entry) => entry.value ?? null));
|
|
3459
|
-
const citedValueRejected = decisionsText.includes("\"cited-value\"") ? decisionsText.includes("not present inside the cited window") : false;
|
|
3624
|
+
const value = outcome.value;
|
|
3625
|
+
const entries = await store.load("fault-repair-honesty");
|
|
3626
|
+
const { compositions, judges } = tailSpans(entries);
|
|
3627
|
+
const invoice = invoiceFromJournal(entries, () => 0);
|
|
3460
3628
|
return {
|
|
3461
3629
|
observation: {
|
|
3462
|
-
matched: outcome.status === "ok" &&
|
|
3463
|
-
detail: `run '${outcome.status}'
|
|
3630
|
+
matched: outcome.status === "ok" && value?.result === TAIL_FINAL_CLEAN && Array.isArray(value.claimContradictions) && value.claimContradictions.length === 0 && value.claimConsistencyMeta?.judgedStage === "final" && value.claimConsistencyMeta.findings === 0 && typeof value.claimConsistencyMeta.judgedHash === "string" && value.claimConsistencyMeta.judgedHash === value.draftToFinal?.finalHash && compositions.length === 2 && judges.length === 2 && [...compositions, ...judges].every((entry) => entry.status === "ok") && typeof outcome.envelope.wireRequests === "number" && outcome.envelope.wireRequests === invoice.cardinality.wireRequests,
|
|
3631
|
+
detail: `run '${outcome.status}' shipped ${value?.result === TAIL_FINAL_CLEAN ? "the repaired document" : "an unexpected document"}; meta judgedStage='${String(value?.claimConsistencyMeta?.judgedStage)}' findings=${String(value?.claimConsistencyMeta?.findings)} judgedHash==finalHash=${String(value?.claimConsistencyMeta?.judgedHash === value?.draftToFinal?.finalHash)}; ${String(compositions.length)} composition(s), ${String(judges.length)} final judge pass(es); wires ${String(outcome.envelope.wireRequests)} == invoice ` + String(invoice.cardinality.wireRequests)
|
|
3464
3632
|
},
|
|
3465
|
-
artifacts: [
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3633
|
+
artifacts: [jsonArtifact("outcome.json", {
|
|
3634
|
+
status: outcome.status,
|
|
3635
|
+
value: outcome.value ?? null,
|
|
3636
|
+
envelope: outcome.envelope
|
|
3637
|
+
}), jsonArtifact("journal.json", entries)]
|
|
3638
|
+
};
|
|
3639
|
+
}
|
|
3640
|
+
},
|
|
3641
|
+
{
|
|
3642
|
+
name: "repair-survivor-refusal",
|
|
3643
|
+
doctrine: "findings that survive the bounded repair round fail the run typed (RV3307): source 'orchestrator_claim_consistency', repairsUsed 1, preRepairHash distinct from repairedHash (the round demonstrably produced a different document and the judge still refused it), two compositions and two final judge passes paid, never a silent ok over the surviving contradiction",
|
|
3644
|
+
async run() {
|
|
3645
|
+
const { engine, store } = tailEngine(tailAdapter({
|
|
3646
|
+
judge: () => TAIL_FINDS,
|
|
3647
|
+
finals: [TAIL_FINAL_INVERTED, TAIL_FINAL_STILL_INVERTED]
|
|
3648
|
+
}));
|
|
3649
|
+
const outcome = await engine.run(makeOrchestratorWorkflow("audit the executor", {
|
|
3650
|
+
...TAIL_OPTS,
|
|
3651
|
+
claimConsistency: {
|
|
3652
|
+
stage: "final",
|
|
3653
|
+
onFound: "repair"
|
|
3654
|
+
}
|
|
3655
|
+
}), void 0, {
|
|
3656
|
+
runId: "fault-repair-survivor",
|
|
3657
|
+
budgetUsd: 10
|
|
3658
|
+
}).result;
|
|
3659
|
+
const data = outcome.error?.data ?? {};
|
|
3660
|
+
const entries = await store.load("fault-repair-survivor");
|
|
3661
|
+
const { compositions, judges } = tailSpans(entries);
|
|
3662
|
+
return {
|
|
3663
|
+
observation: {
|
|
3664
|
+
matched: outcome.status === "error" && (outcome.error?.message ?? "").includes("after the bounded repair round") && data.source === "orchestrator_claim_consistency" && data.repairsUsed === 1 && typeof data.preRepairHash === "string" && typeof data.repairedHash === "string" && data.preRepairHash !== data.repairedHash && compositions.length === 2 && judges.length === 2,
|
|
3665
|
+
detail: `run '${outcome.status}': ${outcome.error?.message ?? ""}; repairsUsed=${String(data.repairsUsed)}, hashes distinct=${String(data.preRepairHash !== data.repairedHash)}, ${String(compositions.length)} composition(s), ${String(judges.length)} final judge pass(es)`
|
|
3666
|
+
},
|
|
3667
|
+
artifacts: [jsonArtifact("outcome.json", {
|
|
3668
|
+
status: outcome.status,
|
|
3669
|
+
error: outcome.error ?? null
|
|
3670
|
+
}), jsonArtifact("journal.json", entries)]
|
|
3671
|
+
};
|
|
3672
|
+
}
|
|
3673
|
+
},
|
|
3674
|
+
{
|
|
3675
|
+
name: "claim-judge-dead-armed-refusal",
|
|
3676
|
+
doctrine: "a final stage judge that dies on the wire under an armed posture fails the run typed for both 'fail' and 'repair' (RV3307), each message naming its armed posture, with exactly one composition paid and no repair round dispatched, never a silent settle over findings nobody ruled on",
|
|
3677
|
+
async run() {
|
|
3678
|
+
const judgeDeath = () => fakeWireError({
|
|
3679
|
+
code: "agent",
|
|
3680
|
+
message: "the judge died mid stream",
|
|
3681
|
+
retryable: false,
|
|
3682
|
+
data: {}
|
|
3683
|
+
});
|
|
3684
|
+
const runs = [];
|
|
3685
|
+
const journals = {};
|
|
3686
|
+
for (const posture of ["fail", "repair"]) {
|
|
3687
|
+
const { engine, store } = tailEngine(tailAdapter({
|
|
3688
|
+
judge: judgeDeath,
|
|
3689
|
+
finals: [TAIL_FINAL_INVERTED]
|
|
3690
|
+
}));
|
|
3691
|
+
const runId = `fault-dead-judge-${posture}`;
|
|
3692
|
+
const outcome = await engine.run(makeOrchestratorWorkflow("audit the executor", {
|
|
3693
|
+
...TAIL_OPTS,
|
|
3694
|
+
claimConsistency: {
|
|
3695
|
+
stage: "final",
|
|
3696
|
+
onFound: posture
|
|
3697
|
+
}
|
|
3698
|
+
}), void 0, {
|
|
3699
|
+
runId,
|
|
3700
|
+
budgetUsd: 10
|
|
3701
|
+
}).result;
|
|
3702
|
+
const entries = await store.load(runId);
|
|
3703
|
+
const { compositions, judges } = tailSpans(entries);
|
|
3704
|
+
journals[posture] = entries;
|
|
3705
|
+
runs.push({
|
|
3706
|
+
posture,
|
|
3707
|
+
status: outcome.status,
|
|
3708
|
+
message: outcome.error?.message ?? "",
|
|
3709
|
+
compositions: compositions.length,
|
|
3710
|
+
judges: judges.length
|
|
3711
|
+
});
|
|
3712
|
+
}
|
|
3713
|
+
return {
|
|
3714
|
+
observation: {
|
|
3715
|
+
matched: runs.every((run) => run.status === "error" && run.message.includes(`armed ${run.posture} posture`) && run.compositions === 1 && run.judges === 1),
|
|
3716
|
+
detail: runs.map((run) => `${run.posture}: '${run.status}' (${run.compositions} composition(s), ${run.judges} judge span(s)) ${run.message.slice(0, 120)}`).join(" | ")
|
|
3717
|
+
},
|
|
3718
|
+
artifacts: [jsonArtifact("runs.json", runs), jsonArtifact("journals.json", journals)]
|
|
3476
3719
|
};
|
|
3477
3720
|
}
|
|
3478
3721
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/evals",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.239.0",
|
|
4
4
|
"description": "Rulvar evals: eval cases, golden outputs, rubric and judge graders, matrix sweeps, canary fingerprint.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
"access": "public"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@rulvar/anthropic": "1.
|
|
26
|
-
"@rulvar/
|
|
27
|
-
"@rulvar/
|
|
28
|
-
"@rulvar/
|
|
29
|
-
"@rulvar/
|
|
25
|
+
"@rulvar/anthropic": "1.239.0",
|
|
26
|
+
"@rulvar/core": "1.239.0",
|
|
27
|
+
"@rulvar/openai": "1.239.0",
|
|
28
|
+
"@rulvar/testing": "1.239.0",
|
|
29
|
+
"@rulvar/plan": "1.239.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/node": "^22.20.1",
|