blun-king-cli 9.1.449 → 9.1.450
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.
|
@@ -12,6 +12,7 @@ const EPISTEMIC_STATES = new Set([
|
|
|
12
12
|
const TRIGGER_KINDS = new Set([
|
|
13
13
|
'immediate', 'external_event', 'time', 'dependency', 'user_decision',
|
|
14
14
|
]);
|
|
15
|
+
const VERIFICATION_SUBJECTS = new Set(['result', 'verifier']);
|
|
15
16
|
const MODEL_KEYS = new Set([
|
|
16
17
|
'revision', 'phase', 'evidenceBasis', 'epistemicState', 'lastVerified', 'nextAction', 'expectedEvidence', 'verificationProof', 'nextTrigger', 'problemFrame', 'updatedAt',
|
|
17
18
|
]);
|
|
@@ -210,39 +211,85 @@ function normalizeSuccessfulToolDigests(value) {
|
|
|
210
211
|
return Object.freeze([...value]);
|
|
211
212
|
}
|
|
212
213
|
|
|
214
|
+
function normalizeExactVerificationCall(input, receipt, label) {
|
|
215
|
+
if (!input || typeof input !== 'object' || Array.isArray(input)
|
|
216
|
+
|| Object.keys(input).length !== 3
|
|
217
|
+
|| !Object.hasOwn(input, 'toolCallId')
|
|
218
|
+
|| !Object.hasOwn(input, 'toolName')
|
|
219
|
+
|| !Object.hasOwn(input, 'claim')) {
|
|
220
|
+
throw new TypeError(`${label} fields are invalid`);
|
|
221
|
+
}
|
|
222
|
+
const toolCallId = bounded(input.toolCallId, `${label} toolCallId`, 256);
|
|
223
|
+
const toolName = bounded(input.toolName, `${label} toolName`, 128);
|
|
224
|
+
const claim = bounded(input.claim, `${label} claim`);
|
|
225
|
+
if (isActionOnlyTool(toolName)) {
|
|
226
|
+
const purpose = label === 'verificationProof' ? 'verification proof' : label;
|
|
227
|
+
throw new TypeError(`action-only tool cannot serve as ${purpose}`);
|
|
228
|
+
}
|
|
229
|
+
const callDigest = successfulToolCallDigest(receipt.turnId, toolCallId, toolName);
|
|
230
|
+
if (!receipt.successfulToolCallDigests.includes(callDigest)) {
|
|
231
|
+
throw new TypeError(`${label} must match a successful current-turn verification call`);
|
|
232
|
+
}
|
|
233
|
+
return Object.freeze({ toolCallId, toolName, claim });
|
|
234
|
+
}
|
|
235
|
+
|
|
213
236
|
function normalizeVerificationProof(input, evidenceReceipt, options = {}) {
|
|
214
237
|
const keys = input && typeof input === 'object' && !Array.isArray(input)
|
|
215
238
|
? Object.keys(input)
|
|
216
239
|
: [];
|
|
217
|
-
const
|
|
240
|
+
const legacyName = options.allowLegacy === true
|
|
218
241
|
&& keys.length === 2
|
|
219
242
|
&& Object.hasOwn(input, 'toolName')
|
|
220
243
|
&& Object.hasOwn(input, 'claim');
|
|
221
|
-
const
|
|
244
|
+
const legacyExact = options.allowLegacy === true
|
|
245
|
+
&& keys.length === 3
|
|
246
|
+
&& Object.hasOwn(input, 'toolCallId')
|
|
247
|
+
&& Object.hasOwn(input, 'toolName')
|
|
248
|
+
&& Object.hasOwn(input, 'claim');
|
|
249
|
+
const subject = String(input?.subject ?? '').trim();
|
|
250
|
+
const currentResult = subject === 'result'
|
|
251
|
+
&& keys.length === 4
|
|
222
252
|
&& Object.hasOwn(input, 'toolCallId')
|
|
223
253
|
&& Object.hasOwn(input, 'toolName')
|
|
224
254
|
&& Object.hasOwn(input, 'claim');
|
|
225
|
-
|
|
255
|
+
const currentVerifier = subject === 'verifier'
|
|
256
|
+
&& (keys.length === 4 || keys.length === 5)
|
|
257
|
+
&& Object.hasOwn(input, 'toolCallId')
|
|
258
|
+
&& Object.hasOwn(input, 'toolName')
|
|
259
|
+
&& Object.hasOwn(input, 'claim')
|
|
260
|
+
&& keys.every((key) => ['subject', 'toolCallId', 'toolName', 'claim', 'sharpnessProof'].includes(key));
|
|
261
|
+
if (!legacyName && !legacyExact && !currentResult && !currentVerifier) {
|
|
226
262
|
throw new TypeError('verificationProof fields are invalid');
|
|
227
263
|
}
|
|
228
|
-
const toolName = bounded(input.toolName, 'verificationProof toolName', 128);
|
|
229
|
-
const claim = bounded(input.claim, 'verificationProof claim');
|
|
230
|
-
if (isActionOnlyTool(toolName)) {
|
|
231
|
-
throw new TypeError('action-only tool cannot serve as verification proof');
|
|
232
|
-
}
|
|
233
264
|
const receipt = normalizeActionEvidenceReceipt(evidenceReceipt);
|
|
234
|
-
if (
|
|
265
|
+
if (legacyName) {
|
|
266
|
+
const toolName = bounded(input.toolName, 'verificationProof toolName', 128);
|
|
267
|
+
const claim = bounded(input.claim, 'verificationProof claim');
|
|
268
|
+
if (isActionOnlyTool(toolName)) {
|
|
269
|
+
throw new TypeError('action-only tool cannot serve as verification proof');
|
|
270
|
+
}
|
|
235
271
|
if (!receipt.successfulToolDigests.includes(successfulToolDigest(toolName))) {
|
|
236
272
|
throw new TypeError('verificationProof must name a successful current-turn tool');
|
|
237
273
|
}
|
|
238
274
|
return Object.freeze({ toolName, claim });
|
|
239
275
|
}
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
245
|
-
|
|
276
|
+
const primary = normalizeExactVerificationCall(legacyExact ? input : {
|
|
277
|
+
toolCallId: input.toolCallId,
|
|
278
|
+
toolName: input.toolName,
|
|
279
|
+
claim: input.claim,
|
|
280
|
+
}, receipt, 'verificationProof');
|
|
281
|
+
if (legacyExact) return primary;
|
|
282
|
+
if (!VERIFICATION_SUBJECTS.has(subject)) throw new TypeError('verificationProof subject is invalid');
|
|
283
|
+
if (subject === 'result') return Object.freeze({ subject, ...primary });
|
|
284
|
+
if (input.sharpnessProof === undefined) {
|
|
285
|
+
throw new TypeError('verifier proof requires a sharpnessProof');
|
|
286
|
+
}
|
|
287
|
+
const sharpnessProof = normalizeExactVerificationCall(input.sharpnessProof, receipt, 'sharpnessProof');
|
|
288
|
+
if (sharpnessProof.toolCallId === primary.toolCallId
|
|
289
|
+
&& sharpnessProof.toolName === primary.toolName) {
|
|
290
|
+
throw new TypeError('sharpnessProof must name a distinct verification call');
|
|
291
|
+
}
|
|
292
|
+
return Object.freeze({ subject, ...primary, sharpnessProof });
|
|
246
293
|
}
|
|
247
294
|
|
|
248
295
|
function emptyActionEvidenceReceipt(turnId) {
|
|
@@ -440,7 +487,14 @@ function projectActionCheckpoint(checkpoint) {
|
|
|
440
487
|
const call = value.verificationProof.toolCallId === undefined
|
|
441
488
|
? value.verificationProof.toolName
|
|
442
489
|
: `${value.verificationProof.toolName} call ${value.verificationProof.toolCallId}`;
|
|
443
|
-
|
|
490
|
+
const subject = value.verificationProof.subject === undefined
|
|
491
|
+
? ''
|
|
492
|
+
: ` [${value.verificationProof.subject}]`;
|
|
493
|
+
lines.push(`Verification proof${subject}: ${call} - ${value.verificationProof.claim}`);
|
|
494
|
+
if (value.verificationProof.sharpnessProof !== undefined) {
|
|
495
|
+
const sharpness = value.verificationProof.sharpnessProof;
|
|
496
|
+
lines.push(`Sharpness proof: ${sharpness.toolName} call ${sharpness.toolCallId} - ${sharpness.claim}`);
|
|
497
|
+
}
|
|
444
498
|
}
|
|
445
499
|
if (value.nextTrigger !== undefined) {
|
|
446
500
|
lines.push(`Next trigger: ${value.nextTrigger.kind.replaceAll('_', ' ')} - ${value.nextTrigger.condition}`);
|
|
@@ -22,6 +22,14 @@ function verificationProofGaps(checkpoint) {
|
|
|
22
22
|
normalizeVerificationProof(checkpoint.verificationProof, checkpoint.evidenceReceipt, { allowLegacy: true });
|
|
23
23
|
return [];
|
|
24
24
|
} catch (error) {
|
|
25
|
+
if (/verifier proof requires a sharpnessProof|sharpnessProof must name a distinct verification call/u
|
|
26
|
+
.test(String(error?.message ?? ''))) {
|
|
27
|
+
return ['A verifier completion needs a distinct current-turn counterexample or mutation call.'];
|
|
28
|
+
}
|
|
29
|
+
if (/sharpnessProof must match a successful current-turn verification call/u
|
|
30
|
+
.test(String(error?.message ?? ''))) {
|
|
31
|
+
return ['The verifier sharpness proof does not match a successful current-turn verification call.'];
|
|
32
|
+
}
|
|
25
33
|
if (/action-only tool/u.test(String(error?.message ?? ''))) {
|
|
26
34
|
return ['The completion proof names an action-only tool, not a verification tool.'];
|
|
27
35
|
}
|
package/blun.mjs
CHANGED
|
@@ -260349,10 +260349,34 @@ function createActionCheckpointInputSchema(problemFrameSchema, requireProblemFra
|
|
|
260349
260349
|
nextAction: string().min(1).max(512),
|
|
260350
260350
|
expectedEvidence: string().min(1).max(512),
|
|
260351
260351
|
verificationProof: object({
|
|
260352
|
+
subject: _enum(["result", "verifier"]),
|
|
260352
260353
|
toolCallId: string().min(1).max(256),
|
|
260353
260354
|
toolName: string().min(1).max(128),
|
|
260354
|
-
claim: string().min(1).max(512)
|
|
260355
|
-
|
|
260355
|
+
claim: string().min(1).max(512),
|
|
260356
|
+
sharpnessProof: object({
|
|
260357
|
+
toolCallId: string().min(1).max(256),
|
|
260358
|
+
toolName: string().min(1).max(128),
|
|
260359
|
+
claim: string().min(1).max(512)
|
|
260360
|
+
}).strict().optional()
|
|
260361
|
+
}).strict().superRefine((value, ctx) => {
|
|
260362
|
+
if (value.subject === "verifier" && value.sharpnessProof === void 0) ctx.addIssue({
|
|
260363
|
+
code: "custom",
|
|
260364
|
+
path: ["sharpnessProof"],
|
|
260365
|
+
message: "verifier subject requires sharpnessProof"
|
|
260366
|
+
});
|
|
260367
|
+
if (value.subject === "result" && value.sharpnessProof !== void 0) ctx.addIssue({
|
|
260368
|
+
code: "custom",
|
|
260369
|
+
path: ["sharpnessProof"],
|
|
260370
|
+
message: "result subject cannot carry sharpnessProof"
|
|
260371
|
+
});
|
|
260372
|
+
if (value.sharpnessProof !== void 0
|
|
260373
|
+
&& value.sharpnessProof.toolCallId === value.toolCallId
|
|
260374
|
+
&& value.sharpnessProof.toolName === value.toolName) ctx.addIssue({
|
|
260375
|
+
code: "custom",
|
|
260376
|
+
path: ["sharpnessProof"],
|
|
260377
|
+
message: "sharpnessProof must name a distinct verification call"
|
|
260378
|
+
});
|
|
260379
|
+
}).optional(),
|
|
260356
260380
|
nextTrigger: object({
|
|
260357
260381
|
kind: _enum(["immediate", "external_event", "time", "dependency", "user_decision"]),
|
|
260358
260382
|
condition: string().min(1).max(512),
|
|
@@ -262875,7 +262899,7 @@ var init_outcome_prompts = __esmMin((() => {}));
|
|
|
262875
262899
|
var update_goal_default;
|
|
262876
262900
|
var init_update_goal$1 = __esmMin((() => {
|
|
262877
262901
|
update_goal_default = "Update the current autonomous goal. Set `status` only for a lifecycle change. After a coherent work slice, save `actionCheckpoint` with a monotone revision, the last verified result, exact next action, expected evidence, exact `nextTrigger`, and an explicit evidence basis. Persist the exact `nextTrigger` that releases `nextAction`: use `immediate` outside the `wait` phase; while waiting, name the external event, time, dependency, or user decision instead of pretending work can continue. A `time` trigger must include the exact ISO timestamp in `dueAt`; no other trigger kind may include `dueAt`. Use `runtime_tool` only when a successful tool in this turn measured the result; use `user_statement` for a direct user assertion, `external_report` for a report not independently measured here, and `carried_forward` only when the last verified text is unchanged. Classify knowledge as `verified`, `credible_unverified`, `hypothesis`, `uncertain_memory`, `stale`, or `unknown`; never present a weaker state as verified, and preserve the state on carry-forward. Start at revision 1 and increment the currently projected revision by exactly one; stale writers fail closed. This is durable progress state, not permission, and should change only when the facts change. A checkpoint-only call keeps the goal active.\n\n- `active` — resume a paused or blocked goal when the user explicitly asks you to work on that goal.\n- `complete` — the objective is fully satisfied, all files are written, all tests pass, and any stated validation has passed. When the goal has a completion criterion, first save a `verify` checkpoint with `runtime_tool`, `verified`, and a successful runtime evidence receipt.\n- `blocked` — a genuine external condition or required user decision prevents progress.\n- `paused` — set the goal aside for now.\n\nDo not mark complete after a plan or partial result. If useful work remains, checkpoint it and continue. Do not ask for permission merely to execute an already authorized checkpoint; ask only at a real rights boundary or missing user decision.\n";
|
|
262878
|
-
update_goal_default += "\nBefore completing a goal with a criterion, bind the verified claim to the exact successful current-turn verification call in `verificationProof`, including its `toolCallId`. A write, edit, copy, deploy, or other action is not proof that the changed behavior works, even when it shares a mixed-use tool such as `Bash` with tests.
|
|
262902
|
+
update_goal_default += "\nBefore completing a goal with a criterion, bind the verified claim to the exact successful current-turn verification call in `verificationProof`, including its `toolCallId`. A write, edit, copy, deploy, or other action is not proof that the changed behavior works, even when it shares a mixed-use tool such as `Bash` with tests. Use `subject: result` for a result, report, measurement, or download. Use `subject: verifier` only when the new or changed test, gate, harness, or detector itself is the completion subject; then bind `sharpnessProof` to a separate successful current-turn counterexample or mutation call. Do not require a red probe for a normal report or measurement.\n";
|
|
262879
262903
|
update_goal_default += "\nFor a non-trivial or unfamiliar problem, preserve `problemFrame` with the success criterion, missing knowledge, bounded candidate actions, selected action and reason, support choice, risk, and reversibility. The selected action must match one candidate. Bind each selected action to the projected durable facts or assumptions it relies on by copying their explicit refs into `decisionBasis`. A stale or unknown decision basis requires replanning before execution. Problem framing is descriptive state and never grants permission.\n";
|
|
262880
262904
|
}));
|
|
262881
262905
|
//#endregion
|