blun-king-cli 9.1.450 → 9.1.451

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.
@@ -13,6 +13,7 @@ const TRIGGER_KINDS = new Set([
13
13
  'immediate', 'external_event', 'time', 'dependency', 'user_decision',
14
14
  ]);
15
15
  const VERIFICATION_SUBJECTS = new Set(['result', 'verifier']);
16
+ const VERIFICATION_KINDS = new Set(['inspection', 'integrity', 'syntax', 'test', 'reachability']);
16
17
  const MODEL_KEYS = new Set([
17
18
  'revision', 'phase', 'evidenceBasis', 'epistemicState', 'lastVerified', 'nextAction', 'expectedEvidence', 'verificationProof', 'nextTrigger', 'problemFrame', 'updatedAt',
18
19
  ]);
@@ -24,6 +25,7 @@ const PROBLEM_FRAME_KEYS = new Set([
24
25
  const NEXT_TRIGGER_KEYS = new Set(['kind', 'condition', 'dueAt']);
25
26
  const EVIDENCE_INPUT_KEYS = new Set([
26
27
  'turnId', 'toolCallId', 'toolName', 'decision', 'outcome', 'durationMs', 'toolArgs',
28
+ 'resultEvidenceKinds',
27
29
  ]);
28
30
  const REQUIRED_EVIDENCE_INPUT_KEYS = new Set([
29
31
  'turnId', 'toolCallId', 'toolName', 'decision', 'outcome', 'durationMs',
@@ -36,14 +38,19 @@ const ACTION_ONLY_TOOL_NAMES = new Set([
36
38
  'ExitPlanMode', 'GenerateImage', 'GenerateSpeech', 'GenerateVideo', 'LipSyncMedia',
37
39
  'MistakeRecord', 'SetGoalBudget', 'TaskStop', 'TaskUpdate', 'UpdateGoal', 'Write',
38
40
  ]);
39
- const VERIFICATION_TOOL_NAMES = new Set([
41
+ const INSPECTION_TOOL_NAMES = new Set([
40
42
  'codebasesearch', 'cronlist', 'fetchurl', 'getgoal', 'getmedia', 'glob', 'grep',
41
- 'read', 'readmediafile', 'taskoutput', 'test', 'understandimage', 'understandvideo',
43
+ 'read', 'readmediafile', 'taskoutput', 'understandimage', 'understandvideo',
42
44
  'websearch',
43
45
  ]);
46
+ const TEST_TOOL_NAMES = new Set(['test']);
44
47
  const COMMAND_TOOL_NAMES = new Set(['bash', 'command', 'exec_command', 'shell']);
45
48
  const MUTATING_COMMAND = /(?:^|(?:&&|\|\||;|\s))(?:(?:cp|mv|rm|mkdir|touch|tee|install|scp|sftp|ssh)\b|(?:sed\s+-i\b)|(?:git\s+(?:add|commit|push|checkout|switch|reset|clean|merge|rebase)\b)|(?:Set-Content|Add-Content|Copy-Item|Move-Item|Remove-Item|New-Item|Start-Process)\b)/iu;
46
- const VERIFICATION_COMMAND = /(?:^|(?:&&|\|\||;|\s))(?:(?:node\s+--(?:test|check))|(?:node\s+[^\s;&|]*(?:check|test|verify|validate|lint|gate|probe)[^\s;&|]*\b)|(?:(?:npm|pnpm|yarn)\s+(?:test|(?:run\s+)?(?:test|lint|check|typecheck|build)))|(?:python(?:3)?\s+-m\s+pytest)|(?:pytest)|(?:go\s+test)|(?:cargo\s+test)|(?:dotnet\s+test)|(?:npx\s+)?(?:tsc|eslint|biome\s+check)|(?:git\s+(?:diff(?:\s+--check)?|fsck|status|rev-parse|show))|(?:sha(?:1|256|512)sum|shasum|cmp|diff|wc|rg|grep|cat|ls|stat)\b|(?:certutil\s+-hashfile)|(?:Get-FileHash|Get-Content|Get-Item|Test-Path|Compare-Object|Measure-Object)\b)/iu;
49
+ const INSPECTION_COMMAND = /(?:^|(?:&&|\|\||;|\s))(?:(?:git\s+(?:status|rev-parse|show))|(?:wc|rg|grep|cat|ls|stat)\b|(?:Get-Content|Get-Item|Test-Path|Measure-Object)\b)/iu;
50
+ const INTEGRITY_COMMAND = /(?:^|(?:&&|\|\||;|\s))(?:(?:git\s+(?:diff(?:\s+--check)?|fsck))|(?:sha(?:1|256|512)sum|shasum|cmp|diff)\b|(?:certutil\s+-hashfile)|(?:Get-FileHash|Compare-Object)\b)/iu;
51
+ const SYNTAX_COMMAND = /(?:^|(?:&&|\|\||;|\s))(?:(?:node\s+--check\b)|(?:(?:npx\s+)?tsc\b)|(?:(?:npm|pnpm|yarn)\s+(?:(?:run\s+)?typecheck)\b))/iu;
52
+ const TEST_COMMAND = /(?:^|(?:&&|\|\||;|\s))(?:(?:node\s+--test\b)|(?:node\s+(?!--)[^\s;&|]*(?:check|test|verify|validate|lint|gate|probe)[^\s;&|]*\b)|(?:(?:npm|pnpm|yarn)\s+(?:test|(?:run\s+)?(?:test|lint|check|build))\b)|(?:python(?:3)?\s+-m\s+pytest\b)|(?:pytest\b)|(?:go\s+test\b)|(?:cargo\s+test\b)|(?:dotnet\s+test\b)|(?:(?:npx\s+)?(?:eslint|biome\s+check)\b))/iu;
53
+ const RUNTIME_EVIDENCE_COMMAND = /(?:^|(?:&&|\|\||;|\s))(?:node\s+(?!--check\b)(?:-e\b|[^\s;&|]+)|(?:python(?:3)?\s+(?!-m\s+pytest\b)[^\s;&|]+)|(?:npm|pnpm|yarn)\s+(?:test|run\b)|pytest\b|go\s+test\b|cargo\s+test\b|dotnet\s+test\b)/iu;
47
54
  const MAX_SUCCESSFUL_TOOL_DIGESTS = 32;
48
55
 
49
56
  function bounded(value, field, max = 512) {
@@ -181,6 +188,17 @@ function successfulToolCallDigest(turnId, toolCallId, toolName) {
181
188
  .slice(0, 16);
182
189
  }
183
190
 
191
+ function successfulVerificationCallDigest(turnId, toolCallId, toolName, kind) {
192
+ const turn = normalizedTurnId(turnId);
193
+ const callId = bounded(toolCallId, 'verificationProof toolCallId', 256);
194
+ const name = bounded(toolName, 'verificationProof toolName', 128);
195
+ const normalizedKind = normalizedVerificationKind(kind);
196
+ return crypto.createHash('sha256')
197
+ .update(`turn:${turn}\0call:${callId}\0tool:${name}\0kind:${normalizedKind}`)
198
+ .digest('hex')
199
+ .slice(0, 16);
200
+ }
201
+
184
202
  function isActionOnlyTool(toolName) {
185
203
  return ACTION_ONLY_TOOL_NAMES.has(String(toolName ?? '').trim());
186
204
  }
@@ -191,14 +209,45 @@ function verificationCommand(toolArgs) {
191
209
  return typeof command === 'string' ? command.trim().replace(/\s+/gu, ' ') : '';
192
210
  }
193
211
 
194
- function isVerificationToolCall(toolName, toolArgs) {
212
+ function verificationKindsForToolCall(toolName, toolArgs) {
213
+ const normalizedName = String(toolName ?? '').trim().toLowerCase();
214
+ if (INSPECTION_TOOL_NAMES.has(normalizedName)) return Object.freeze(['inspection']);
215
+ if (TEST_TOOL_NAMES.has(normalizedName)) return Object.freeze(['test']);
216
+ if (!COMMAND_TOOL_NAMES.has(normalizedName)) return Object.freeze([]);
217
+ const command = verificationCommand(toolArgs);
218
+ if (command.length < 1 || MUTATING_COMMAND.test(command)) return Object.freeze([]);
219
+ const kinds = [];
220
+ if (INSPECTION_COMMAND.test(command)) kinds.push('inspection');
221
+ if (INTEGRITY_COMMAND.test(command)) kinds.push('integrity');
222
+ if (SYNTAX_COMMAND.test(command)) kinds.push('syntax');
223
+ if (TEST_COMMAND.test(command)) kinds.push('test');
224
+ return Object.freeze(kinds);
225
+ }
226
+
227
+ function canCarryExplicitResultEvidence(toolName, toolArgs) {
195
228
  const normalizedName = String(toolName ?? '').trim().toLowerCase();
196
- if (VERIFICATION_TOOL_NAMES.has(normalizedName)) return true;
197
229
  if (!COMMAND_TOOL_NAMES.has(normalizedName)) return false;
198
230
  const command = verificationCommand(toolArgs);
199
231
  return command.length > 0
200
232
  && !MUTATING_COMMAND.test(command)
201
- && VERIFICATION_COMMAND.test(command);
233
+ && RUNTIME_EVIDENCE_COMMAND.test(command);
234
+ }
235
+
236
+ function normalizedVerificationKind(value, field = 'verificationProof kind') {
237
+ const kind = String(value ?? '').trim();
238
+ if (!VERIFICATION_KINDS.has(kind)) throw new TypeError(`${field} is invalid`);
239
+ return kind;
240
+ }
241
+
242
+ function normalizedResultEvidenceKinds(value) {
243
+ if (value === undefined) return Object.freeze([]);
244
+ const kinds = Array.isArray(value) ? value.map((item) => String(item ?? '').trim()) : [];
245
+ if (!Array.isArray(value) || value.length > VERIFICATION_KINDS.size
246
+ || kinds.some((item) => !VERIFICATION_KINDS.has(item))
247
+ || new Set(kinds).size !== kinds.length) {
248
+ throw new TypeError('result evidence kinds are invalid');
249
+ }
250
+ return Object.freeze(kinds);
202
251
  }
203
252
 
204
253
  function normalizeSuccessfulToolDigests(value) {
@@ -211,12 +260,15 @@ function normalizeSuccessfulToolDigests(value) {
211
260
  return Object.freeze([...value]);
212
261
  }
213
262
 
214
- function normalizeExactVerificationCall(input, receipt, label) {
263
+ function normalizeExactVerificationCall(input, receipt, label, options = {}) {
264
+ const requireKind = options.requireKind === true;
265
+ const expectedKeys = requireKind ? 4 : 3;
215
266
  if (!input || typeof input !== 'object' || Array.isArray(input)
216
- || Object.keys(input).length !== 3
267
+ || Object.keys(input).length !== expectedKeys
217
268
  || !Object.hasOwn(input, 'toolCallId')
218
269
  || !Object.hasOwn(input, 'toolName')
219
- || !Object.hasOwn(input, 'claim')) {
270
+ || !Object.hasOwn(input, 'claim')
271
+ || requireKind !== Object.hasOwn(input, 'kind')) {
220
272
  throw new TypeError(`${label} fields are invalid`);
221
273
  }
222
274
  const toolCallId = bounded(input.toolCallId, `${label} toolCallId`, 256);
@@ -230,6 +282,14 @@ function normalizeExactVerificationCall(input, receipt, label) {
230
282
  if (!receipt.successfulToolCallDigests.includes(callDigest)) {
231
283
  throw new TypeError(`${label} must match a successful current-turn verification call`);
232
284
  }
285
+ if (requireKind) {
286
+ const kind = normalizedVerificationKind(input.kind, `${label} kind`);
287
+ const typedDigest = successfulVerificationCallDigest(receipt.turnId, toolCallId, toolName, kind);
288
+ if (!receipt.successfulVerificationCallDigests.includes(typedDigest)) {
289
+ throw new TypeError(`${label} kind must match the successful current-turn verification call`);
290
+ }
291
+ return Object.freeze({ toolCallId, toolName, kind, claim });
292
+ }
233
293
  return Object.freeze({ toolCallId, toolName, claim });
234
294
  }
235
295
 
@@ -247,18 +307,34 @@ function normalizeVerificationProof(input, evidenceReceipt, options = {}) {
247
307
  && Object.hasOwn(input, 'toolName')
248
308
  && Object.hasOwn(input, 'claim');
249
309
  const subject = String(input?.subject ?? '').trim();
250
- const currentResult = subject === 'result'
310
+ const legacySubjectResult = options.allowLegacy === true
311
+ && subject === 'result'
251
312
  && keys.length === 4
252
313
  && Object.hasOwn(input, 'toolCallId')
253
314
  && Object.hasOwn(input, 'toolName')
254
315
  && Object.hasOwn(input, 'claim');
255
- const currentVerifier = subject === 'verifier'
316
+ const legacySubjectVerifier = options.allowLegacy === true
317
+ && subject === 'verifier'
256
318
  && (keys.length === 4 || keys.length === 5)
257
319
  && Object.hasOwn(input, 'toolCallId')
258
320
  && Object.hasOwn(input, 'toolName')
259
321
  && Object.hasOwn(input, 'claim')
260
322
  && keys.every((key) => ['subject', 'toolCallId', 'toolName', 'claim', 'sharpnessProof'].includes(key));
261
- if (!legacyName && !legacyExact && !currentResult && !currentVerifier) {
323
+ const currentResult = subject === 'result'
324
+ && keys.length === 5
325
+ && Object.hasOwn(input, 'toolCallId')
326
+ && Object.hasOwn(input, 'toolName')
327
+ && Object.hasOwn(input, 'kind')
328
+ && Object.hasOwn(input, 'claim');
329
+ const currentVerifier = subject === 'verifier'
330
+ && (keys.length === 5 || keys.length === 6)
331
+ && Object.hasOwn(input, 'toolCallId')
332
+ && Object.hasOwn(input, 'toolName')
333
+ && Object.hasOwn(input, 'kind')
334
+ && Object.hasOwn(input, 'claim')
335
+ && keys.every((key) => ['subject', 'toolCallId', 'toolName', 'kind', 'claim', 'sharpnessProof'].includes(key));
336
+ if (!legacyName && !legacyExact && !legacySubjectResult && !legacySubjectVerifier
337
+ && !currentResult && !currentVerifier) {
262
338
  throw new TypeError('verificationProof fields are invalid');
263
339
  }
264
340
  const receipt = normalizeActionEvidenceReceipt(evidenceReceipt);
@@ -273,18 +349,22 @@ function normalizeVerificationProof(input, evidenceReceipt, options = {}) {
273
349
  }
274
350
  return Object.freeze({ toolName, claim });
275
351
  }
352
+ const legacySubject = legacySubjectResult || legacySubjectVerifier;
276
353
  const primary = normalizeExactVerificationCall(legacyExact ? input : {
277
354
  toolCallId: input.toolCallId,
278
355
  toolName: input.toolName,
356
+ ...(legacySubject ? {} : { kind: input.kind }),
279
357
  claim: input.claim,
280
- }, receipt, 'verificationProof');
358
+ }, receipt, 'verificationProof', { requireKind: !legacyExact && !legacySubject });
281
359
  if (legacyExact) return primary;
282
360
  if (!VERIFICATION_SUBJECTS.has(subject)) throw new TypeError('verificationProof subject is invalid');
283
361
  if (subject === 'result') return Object.freeze({ subject, ...primary });
284
362
  if (input.sharpnessProof === undefined) {
285
363
  throw new TypeError('verifier proof requires a sharpnessProof');
286
364
  }
287
- const sharpnessProof = normalizeExactVerificationCall(input.sharpnessProof, receipt, 'sharpnessProof');
365
+ const sharpnessProof = normalizeExactVerificationCall(input.sharpnessProof, receipt, 'sharpnessProof', {
366
+ requireKind: !legacySubject,
367
+ });
288
368
  if (sharpnessProof.toolCallId === primary.toolCallId
289
369
  && sharpnessProof.toolName === primary.toolName) {
290
370
  throw new TypeError('sharpnessProof must name a distinct verification call');
@@ -301,6 +381,7 @@ function emptyActionEvidenceReceipt(turnId) {
301
381
  failedTools: 0,
302
382
  successfulToolDigests: Object.freeze([]),
303
383
  successfulToolCallDigests: Object.freeze([]),
384
+ successfulVerificationCallDigests: Object.freeze([]),
304
385
  digest: crypto.createHash('sha256').update(`turn:${normalized}:empty`).digest('hex').slice(0, 16),
305
386
  });
306
387
  }
@@ -308,7 +389,10 @@ function emptyActionEvidenceReceipt(turnId) {
308
389
  function normalizeActionEvidenceReceipt(input) {
309
390
  if (!input || typeof input !== 'object' || Array.isArray(input)) throw new TypeError('evidence receipt must be an object');
310
391
  const requiredKeys = new Set(['turnId', 'completedTools', 'successfulTools', 'failedTools', 'digest']);
311
- const allowedKeys = new Set([...requiredKeys, 'successfulToolDigests', 'successfulToolCallDigests']);
392
+ const allowedKeys = new Set([
393
+ ...requiredKeys, 'successfulToolDigests', 'successfulToolCallDigests',
394
+ 'successfulVerificationCallDigests',
395
+ ]);
312
396
  if (!Object.keys(input).every((key) => allowedKeys.has(key))
313
397
  || ![...requiredKeys].every((key) => Object.hasOwn(input, key))) {
314
398
  throw new TypeError('evidence receipt fields are invalid');
@@ -320,6 +404,9 @@ function normalizeActionEvidenceReceipt(input) {
320
404
  failedTools: Number(input.failedTools),
321
405
  successfulToolDigests: normalizeSuccessfulToolDigests(input.successfulToolDigests),
322
406
  successfulToolCallDigests: normalizeSuccessfulToolDigests(input.successfulToolCallDigests),
407
+ successfulVerificationCallDigests: normalizeSuccessfulToolDigests(
408
+ input.successfulVerificationCallDigests,
409
+ ),
323
410
  digest: String(input.digest ?? ''),
324
411
  };
325
412
  if (![receipt.completedTools, receipt.successfulTools, receipt.failedTools]
@@ -352,20 +439,37 @@ function advanceActionEvidenceReceipt(current, input) {
352
439
  const successful = decision === 'passed' && outcome === 'success';
353
440
  const successfulToolDigests = [...prior.successfulToolDigests];
354
441
  const successfulToolCallDigests = [...prior.successfulToolCallDigests];
442
+ const successfulVerificationCallDigests = [...prior.successfulVerificationCallDigests];
355
443
  const toolDigest = successfulToolDigest(toolName);
356
444
  if (successful && !successfulToolDigests.includes(toolDigest)) {
357
445
  successfulToolDigests.push(toolDigest);
358
446
  if (successfulToolDigests.length > MAX_SUCCESSFUL_TOOL_DIGESTS) successfulToolDigests.shift();
359
447
  }
360
- const verificationCall = successful && isVerificationToolCall(toolName, input.toolArgs);
448
+ const providedResultKinds = normalizedResultEvidenceKinds(input.resultEvidenceKinds);
449
+ const explicitResultKinds = successful && canCarryExplicitResultEvidence(toolName, input.toolArgs)
450
+ ? providedResultKinds
451
+ : [];
452
+ const verificationKinds = successful
453
+ ? [...new Set([...verificationKindsForToolCall(toolName, input.toolArgs), ...explicitResultKinds])]
454
+ : [];
455
+ const verificationCall = verificationKinds.length > 0;
361
456
  if (verificationCall) {
362
457
  const callDigest = successfulToolCallDigest(turnId, toolCallId, toolName);
363
458
  if (!successfulToolCallDigests.includes(callDigest)) successfulToolCallDigests.push(callDigest);
364
459
  if (successfulToolCallDigests.length > MAX_SUCCESSFUL_TOOL_DIGESTS) successfulToolCallDigests.shift();
460
+ for (const kind of verificationKinds) {
461
+ const typedDigest = successfulVerificationCallDigest(turnId, toolCallId, toolName, kind);
462
+ if (!successfulVerificationCallDigests.includes(typedDigest)) {
463
+ successfulVerificationCallDigests.push(typedDigest);
464
+ }
465
+ if (successfulVerificationCallDigests.length > MAX_SUCCESSFUL_TOOL_DIGESTS) {
466
+ successfulVerificationCallDigests.shift();
467
+ }
468
+ }
365
469
  }
366
470
  const digest = crypto.createHash('sha256').update([
367
471
  prior.digest, String(turnId), toolCallId, toolName, decision, outcome, String(durationMs),
368
- String(verificationCall),
472
+ verificationKinds.join(','),
369
473
  ].join('\0')).digest('hex').slice(0, 16);
370
474
  return Object.freeze({
371
475
  turnId,
@@ -374,6 +478,7 @@ function advanceActionEvidenceReceipt(current, input) {
374
478
  failedTools: prior.failedTools + (successful ? 0 : 1),
375
479
  successfulToolDigests: Object.freeze(successfulToolDigests),
376
480
  successfulToolCallDigests: Object.freeze(successfulToolCallDigests),
481
+ successfulVerificationCallDigests: Object.freeze(successfulVerificationCallDigests),
377
482
  digest,
378
483
  });
379
484
  }
@@ -490,10 +595,14 @@ function projectActionCheckpoint(checkpoint) {
490
595
  const subject = value.verificationProof.subject === undefined
491
596
  ? ''
492
597
  : ` [${value.verificationProof.subject}]`;
493
- lines.push(`Verification proof${subject}: ${call} - ${value.verificationProof.claim}`);
598
+ const kind = value.verificationProof.kind === undefined
599
+ ? ''
600
+ : ` [${value.verificationProof.kind}]`;
601
+ lines.push(`Verification proof${subject}${kind}: ${call} - ${value.verificationProof.claim}`);
494
602
  if (value.verificationProof.sharpnessProof !== undefined) {
495
603
  const sharpness = value.verificationProof.sharpnessProof;
496
- lines.push(`Sharpness proof: ${sharpness.toolName} call ${sharpness.toolCallId} - ${sharpness.claim}`);
604
+ const sharpnessKind = sharpness.kind === undefined ? '' : ` [${sharpness.kind}]`;
605
+ lines.push(`Sharpness proof${sharpnessKind}: ${sharpness.toolName} call ${sharpness.toolCallId} - ${sharpness.claim}`);
497
606
  }
498
607
  }
499
608
  if (value.nextTrigger !== undefined) {
@@ -534,5 +643,7 @@ module.exports = {
534
643
  normalizeVerificationProof,
535
644
  projectActionCheckpoint,
536
645
  successfulToolCallDigest,
646
+ successfulVerificationCallDigest,
537
647
  successfulToolDigest,
648
+ verificationKindsForToolCall,
538
649
  };
@@ -30,6 +30,10 @@ function verificationProofGaps(checkpoint) {
30
30
  .test(String(error?.message ?? ''))) {
31
31
  return ['The verifier sharpness proof does not match a successful current-turn verification call.'];
32
32
  }
33
+ if (/(?:verificationProof|sharpnessProof) kind must match the successful current-turn verification call/u
34
+ .test(String(error?.message ?? ''))) {
35
+ return ['The completion proof kind exceeds what its exact verification call measured.'];
36
+ }
33
37
  if (/action-only tool/u.test(String(error?.message ?? ''))) {
34
38
  return ['The completion proof names an action-only tool, not a verification tool.'];
35
39
  }
package/blun.mjs CHANGED
@@ -260352,10 +260352,12 @@ function createActionCheckpointInputSchema(problemFrameSchema, requireProblemFra
260352
260352
  subject: _enum(["result", "verifier"]),
260353
260353
  toolCallId: string().min(1).max(256),
260354
260354
  toolName: string().min(1).max(128),
260355
+ kind: _enum(["inspection", "integrity", "syntax", "test", "reachability"]),
260355
260356
  claim: string().min(1).max(512),
260356
260357
  sharpnessProof: object({
260357
260358
  toolCallId: string().min(1).max(256),
260358
260359
  toolName: string().min(1).max(128),
260360
+ kind: _enum(["inspection", "integrity", "syntax", "test", "reachability"]),
260359
260361
  claim: string().min(1).max(512)
260360
260362
  }).strict().optional()
260361
260363
  }).strict().superRefine((value, ctx) => {
@@ -261692,6 +261694,10 @@ function telemetryToolErrorType(result) {
261692
261694
  function toolResultText(result) {
261693
261695
  return toolOutputText(result.output);
261694
261696
  }
261697
+ function explicitToolResultEvidenceKinds(result) {
261698
+ const text = toolResultText(result);
261699
+ return /(?:^|\s)BLUN_EVIDENCE_KIND=reachability(?:\s|$)/u.test(text) ? ["reachability"] : [];
261700
+ }
261695
261701
  function abandonedToolResultOutput(ended) {
261696
261702
  return `Tool call did not complete: ${ended.reason === "cancelled" ? "the turn was cancelled" : ended.reason === "failed" ? `the turn failed${ended.error !== void 0 ? ` (${ended.error.message})` : ""}` : "the turn ended"} before its result was recorded. Do not assume the tool completed successfully.`;
261697
261703
  }
@@ -262794,7 +262800,8 @@ var init_turn = __esmMin((() => {
262794
262800
  toolName: started.name,
262795
262801
  outcome,
262796
262802
  durationMs: Date.now() - started.startedAt,
262797
- toolArgs: started.args
262803
+ toolArgs: started.args,
262804
+ resultEvidenceKinds: explicitToolResultEvidenceKinds(event.result)
262798
262805
  });
262799
262806
  this.agent.telemetry.track("tool_call", properties);
262800
262807
  this.agent.feedRootMissionContract("result", {
@@ -262900,6 +262907,7 @@ var update_goal_default;
262900
262907
  var init_update_goal$1 = __esmMin((() => {
262901
262908
  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";
262902
262909
  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";
262910
+ 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";
262903
262911
  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";
262904
262912
  }));
262905
262913
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.450",
3
+ "version": "9.1.451",
4
4
  "description": "BLUN CLI - your own AI agent with a Telegram channel. Get it done. With BLUN.",
5
5
  "license": "MIT",
6
6
  "bin": {