blun-king-cli 9.1.452 → 9.1.453
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.
|
@@ -32,6 +32,7 @@ const REQUIRED_EVIDENCE_INPUT_KEYS = new Set([
|
|
|
32
32
|
]);
|
|
33
33
|
const EVIDENCE_DIGEST_RE = /^[a-f0-9]{16}$/u;
|
|
34
34
|
const DECISION_BASIS_RE = /^[a-f0-9]{16}$/u;
|
|
35
|
+
const COMPLETION_CRITERION_REF_RE = /^[a-f0-9]{16}$/u;
|
|
35
36
|
const ISO_TIMESTAMP_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}(?::?\d{2})?)$/u;
|
|
36
37
|
const ACTION_ONLY_TOOL_NAMES = new Set([
|
|
37
38
|
'CreateGoal', 'CronCreate', 'CronDelete', 'DubVideo', 'Edit', 'EnterPlanMode',
|
|
@@ -216,6 +217,15 @@ function successfulVerificationScopeDigest(turnId, toolCallId, toolName, kind, s
|
|
|
216
217
|
.slice(0, 16);
|
|
217
218
|
}
|
|
218
219
|
|
|
220
|
+
function completionCriterionRef(value) {
|
|
221
|
+
const criterion = String(value ?? '').trim();
|
|
222
|
+
if (!criterion) throw new TypeError('completion criterion is required');
|
|
223
|
+
return crypto.createHash('sha256')
|
|
224
|
+
.update(`completion-criterion:${criterion}`)
|
|
225
|
+
.digest('hex')
|
|
226
|
+
.slice(0, 16);
|
|
227
|
+
}
|
|
228
|
+
|
|
219
229
|
function isActionOnlyTool(toolName) {
|
|
220
230
|
return ACTION_ONLY_TOOL_NAMES.has(String(toolName ?? '').trim());
|
|
221
231
|
}
|
|
@@ -412,14 +422,16 @@ function normalizeVerificationProof(input, evidenceReceipt, options = {}) {
|
|
|
412
422
|
&& Object.hasOwn(input, 'kind')
|
|
413
423
|
&& Object.hasOwn(input, 'claim')
|
|
414
424
|
&& keys.every((key) => ['subject', 'toolCallId', 'toolName', 'kind', 'claim', 'sharpnessProof'].includes(key));
|
|
415
|
-
const
|
|
425
|
+
const legacyScopedResult = options.allowLegacy === true
|
|
426
|
+
&& subject === 'result'
|
|
416
427
|
&& keys.length === 6
|
|
417
428
|
&& Object.hasOwn(input, 'toolCallId')
|
|
418
429
|
&& Object.hasOwn(input, 'toolName')
|
|
419
430
|
&& Object.hasOwn(input, 'kind')
|
|
420
431
|
&& Object.hasOwn(input, 'scope')
|
|
421
432
|
&& Object.hasOwn(input, 'claim');
|
|
422
|
-
const
|
|
433
|
+
const legacyScopedVerifier = options.allowLegacy === true
|
|
434
|
+
&& subject === 'verifier'
|
|
423
435
|
&& (keys.length === 6 || keys.length === 7)
|
|
424
436
|
&& Object.hasOwn(input, 'toolCallId')
|
|
425
437
|
&& Object.hasOwn(input, 'toolName')
|
|
@@ -427,9 +439,46 @@ function normalizeVerificationProof(input, evidenceReceipt, options = {}) {
|
|
|
427
439
|
&& Object.hasOwn(input, 'scope')
|
|
428
440
|
&& Object.hasOwn(input, 'claim')
|
|
429
441
|
&& keys.every((key) => ['subject', 'toolCallId', 'toolName', 'kind', 'scope', 'claim', 'sharpnessProof'].includes(key));
|
|
442
|
+
const freshResult = subject === 'result'
|
|
443
|
+
&& keys.length === 7
|
|
444
|
+
&& Object.hasOwn(input, 'toolCallId')
|
|
445
|
+
&& Object.hasOwn(input, 'toolName')
|
|
446
|
+
&& Object.hasOwn(input, 'kind')
|
|
447
|
+
&& Object.hasOwn(input, 'scope')
|
|
448
|
+
&& Object.hasOwn(input, 'criterion')
|
|
449
|
+
&& Object.hasOwn(input, 'claim');
|
|
450
|
+
const freshVerifier = subject === 'verifier'
|
|
451
|
+
&& (keys.length === 7 || keys.length === 8)
|
|
452
|
+
&& Object.hasOwn(input, 'toolCallId')
|
|
453
|
+
&& Object.hasOwn(input, 'toolName')
|
|
454
|
+
&& Object.hasOwn(input, 'kind')
|
|
455
|
+
&& Object.hasOwn(input, 'scope')
|
|
456
|
+
&& Object.hasOwn(input, 'criterion')
|
|
457
|
+
&& Object.hasOwn(input, 'claim')
|
|
458
|
+
&& keys.every((key) => ['subject', 'toolCallId', 'toolName', 'kind', 'scope', 'criterion', 'claim', 'sharpnessProof'].includes(key));
|
|
459
|
+
const replayResult = options.allowLegacy === true
|
|
460
|
+
&& subject === 'result'
|
|
461
|
+
&& keys.length === 7
|
|
462
|
+
&& Object.hasOwn(input, 'toolCallId')
|
|
463
|
+
&& Object.hasOwn(input, 'toolName')
|
|
464
|
+
&& Object.hasOwn(input, 'kind')
|
|
465
|
+
&& Object.hasOwn(input, 'scope')
|
|
466
|
+
&& Object.hasOwn(input, 'criterionRef')
|
|
467
|
+
&& Object.hasOwn(input, 'claim');
|
|
468
|
+
const replayVerifier = options.allowLegacy === true
|
|
469
|
+
&& subject === 'verifier'
|
|
470
|
+
&& (keys.length === 7 || keys.length === 8)
|
|
471
|
+
&& Object.hasOwn(input, 'toolCallId')
|
|
472
|
+
&& Object.hasOwn(input, 'toolName')
|
|
473
|
+
&& Object.hasOwn(input, 'kind')
|
|
474
|
+
&& Object.hasOwn(input, 'scope')
|
|
475
|
+
&& Object.hasOwn(input, 'criterionRef')
|
|
476
|
+
&& Object.hasOwn(input, 'claim')
|
|
477
|
+
&& keys.every((key) => ['subject', 'toolCallId', 'toolName', 'kind', 'scope', 'criterionRef', 'claim', 'sharpnessProof'].includes(key));
|
|
430
478
|
if (!legacyName && !legacyExact && !legacySubjectResult && !legacySubjectVerifier
|
|
431
479
|
&& !legacyTypedSubjectResult && !legacyTypedSubjectVerifier
|
|
432
|
-
&& !
|
|
480
|
+
&& !legacyScopedResult && !legacyScopedVerifier
|
|
481
|
+
&& !freshResult && !freshVerifier && !replayResult && !replayVerifier) {
|
|
433
482
|
throw new TypeError('verificationProof fields are invalid');
|
|
434
483
|
}
|
|
435
484
|
const receipt = normalizeActionEvidenceReceipt(evidenceReceipt);
|
|
@@ -450,15 +499,27 @@ function normalizeVerificationProof(input, evidenceReceipt, options = {}) {
|
|
|
450
499
|
toolCallId: input.toolCallId,
|
|
451
500
|
toolName: input.toolName,
|
|
452
501
|
...(legacySubject ? {} : { kind: input.kind }),
|
|
453
|
-
...(
|
|
502
|
+
...(legacyScopedResult || legacyScopedVerifier || freshResult || freshVerifier
|
|
503
|
+
|| replayResult || replayVerifier ? { scope: input.scope } : {}),
|
|
454
504
|
claim: input.claim,
|
|
455
505
|
}, receipt, 'verificationProof', {
|
|
456
506
|
requireKind: !legacyExact && !legacySubject,
|
|
457
|
-
requireScope:
|
|
507
|
+
requireScope: legacyScopedResult || legacyScopedVerifier || freshResult || freshVerifier
|
|
508
|
+
|| replayResult || replayVerifier,
|
|
458
509
|
});
|
|
459
510
|
if (legacyExact) return primary;
|
|
460
511
|
if (!VERIFICATION_SUBJECTS.has(subject)) throw new TypeError('verificationProof subject is invalid');
|
|
461
|
-
|
|
512
|
+
const criterionRef = freshResult || freshVerifier
|
|
513
|
+
? completionCriterionRef(input.criterion)
|
|
514
|
+
: replayResult || replayVerifier
|
|
515
|
+
? String(input.criterionRef ?? '')
|
|
516
|
+
: undefined;
|
|
517
|
+
if (criterionRef !== undefined && !COMPLETION_CRITERION_REF_RE.test(criterionRef)) {
|
|
518
|
+
throw new TypeError('verificationProof criterionRef is invalid');
|
|
519
|
+
}
|
|
520
|
+
if (subject === 'result') {
|
|
521
|
+
return Object.freeze({ subject, ...primary, ...(criterionRef === undefined ? {} : { criterionRef }) });
|
|
522
|
+
}
|
|
462
523
|
if (input.sharpnessProof === undefined) {
|
|
463
524
|
throw new TypeError('verifier proof requires a sharpnessProof');
|
|
464
525
|
}
|
|
@@ -470,7 +531,12 @@ function normalizeVerificationProof(input, evidenceReceipt, options = {}) {
|
|
|
470
531
|
&& sharpnessProof.toolName === primary.toolName) {
|
|
471
532
|
throw new TypeError('sharpnessProof must name a distinct verification call');
|
|
472
533
|
}
|
|
473
|
-
return Object.freeze({
|
|
534
|
+
return Object.freeze({
|
|
535
|
+
subject,
|
|
536
|
+
...primary,
|
|
537
|
+
...(criterionRef === undefined ? {} : { criterionRef }),
|
|
538
|
+
sharpnessProof,
|
|
539
|
+
});
|
|
474
540
|
}
|
|
475
541
|
|
|
476
542
|
function emptyActionEvidenceReceipt(turnId) {
|
|
@@ -728,7 +794,10 @@ function projectActionCheckpoint(checkpoint) {
|
|
|
728
794
|
const scope = value.verificationProof.scope === undefined
|
|
729
795
|
? ''
|
|
730
796
|
: ` [scope: ${value.verificationProof.scope}]`;
|
|
731
|
-
|
|
797
|
+
const criterion = value.verificationProof.criterionRef === undefined
|
|
798
|
+
? ''
|
|
799
|
+
: ` [criterion: ${value.verificationProof.criterionRef}]`;
|
|
800
|
+
lines.push(`Verification proof${subject}${kind}${scope}${criterion}: ${call} - ${value.verificationProof.claim}`);
|
|
732
801
|
if (value.verificationProof.sharpnessProof !== undefined) {
|
|
733
802
|
const sharpness = value.verificationProof.sharpnessProof;
|
|
734
803
|
const sharpnessKind = sharpness.kind === undefined ? '' : ` [${sharpness.kind}]`;
|
|
@@ -769,6 +838,7 @@ module.exports = {
|
|
|
769
838
|
advanceActionEvidenceReceipt,
|
|
770
839
|
assertActionCheckpointEvidenceBasis,
|
|
771
840
|
assertActionCheckpointRevision,
|
|
841
|
+
completionCriterionRef,
|
|
772
842
|
emptyActionEvidenceReceipt,
|
|
773
843
|
normalizeActionCheckpoint,
|
|
774
844
|
normalizeVerificationProof,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const {
|
|
4
|
+
completionCriterionRef,
|
|
4
5
|
normalizeVerificationProof,
|
|
5
6
|
} = require('./cognitive-action-checkpoint.cjs');
|
|
6
7
|
|
|
@@ -14,12 +15,19 @@ function successfulRuntimeEvidence(checkpoint) {
|
|
|
14
15
|
return Number.isSafeInteger(successfulTools) && successfulTools > 0;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
function verificationProofGaps(checkpoint) {
|
|
18
|
+
function verificationProofGaps(checkpoint, criterion) {
|
|
18
19
|
if (!checkpoint?.verificationProof) {
|
|
19
20
|
return ['Bind the completion claim to a successful verification tool from the checkpoint turn.'];
|
|
20
21
|
}
|
|
21
22
|
try {
|
|
22
|
-
|
|
23
|
+
const proof = normalizeVerificationProof(
|
|
24
|
+
checkpoint.verificationProof,
|
|
25
|
+
checkpoint.evidenceReceipt,
|
|
26
|
+
{ allowLegacy: true },
|
|
27
|
+
);
|
|
28
|
+
if (proof.criterionRef !== completionCriterionRef(criterion)) {
|
|
29
|
+
return ['Bind the completion proof to the active completion criterion.'];
|
|
30
|
+
}
|
|
23
31
|
return [];
|
|
24
32
|
} catch (error) {
|
|
25
33
|
if (/verifier proof requires a sharpnessProof|sharpnessProof must name a distinct verification call/u
|
|
@@ -86,7 +94,7 @@ function evaluateGoalCompletionEvidence(goal) {
|
|
|
86
94
|
&& checkpoint.evidenceBasis === 'runtime_tool'
|
|
87
95
|
&& checkpoint.epistemicState === 'verified'
|
|
88
96
|
&& hasRuntimeEvidence) {
|
|
89
|
-
gaps.push(...verificationProofGaps(checkpoint));
|
|
97
|
+
gaps.push(...verificationProofGaps(checkpoint, goal.completionCriterion));
|
|
90
98
|
}
|
|
91
99
|
|
|
92
100
|
return {
|
package/blun.mjs
CHANGED
|
@@ -260354,6 +260354,7 @@ function createActionCheckpointInputSchema(problemFrameSchema, requireProblemFra
|
|
|
260354
260354
|
toolName: string().min(1).max(128),
|
|
260355
260355
|
kind: _enum(["inspection", "integrity", "syntax", "test", "reachability"]),
|
|
260356
260356
|
scope: string().min(1).max(256),
|
|
260357
|
+
criterion: string().min(1),
|
|
260357
260358
|
claim: string().min(1).max(512),
|
|
260358
260359
|
sharpnessProof: object({
|
|
260359
260360
|
toolCallId: string().min(1).max(256),
|
|
@@ -262917,6 +262918,7 @@ var update_goal_default;
|
|
|
262917
262918
|
var init_update_goal$1 = __esmMin((() => {
|
|
262918
262919
|
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";
|
|
262919
262920
|
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";
|
|
262921
|
+
update_goal_default += "\nCopy the active goal's exact `completionCriterion` into `verificationProof.criterion`. The runtime stores only its bounded reference and refuses completion if the proof belongs to a different or superseded completion criterion.\n";
|
|
262920
262922
|
update_goal_default += "\nSet the proof `kind` to the exact capability of that call: `inspection` reads or searches, `integrity` compares bytes or hashes, `syntax` parses or type-checks, and `test` runs assertions. None of these alone proves a stronger kind. Use `reachability` only for a successful runtime probe that actually invokes the changed path and emits the exact marker `BLUN_EVIDENCE_KIND=reachability` after its assertions; loading a module without reaching the changed path is not reachability.\n";
|
|
262921
262923
|
update_goal_default += "\nBind each proof `scope` to the exact target measured by that successful call, never to a free-text claim or intended file. Read and search tools derive scope from their target arguments. For shell or command tools, include the same safe token `BLUN_EVIDENCE_SCOPE=<scope>` in the launched non-mutating verification command and emit it only after that exact target succeeds; the runtime requires both sides.\n";
|
|
262922
262924
|
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";
|