blun-king-cli 9.1.447 → 9.1.449
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,7 +13,7 @@ const TRIGGER_KINDS = new Set([
|
|
|
13
13
|
'immediate', 'external_event', 'time', 'dependency', 'user_decision',
|
|
14
14
|
]);
|
|
15
15
|
const MODEL_KEYS = new Set([
|
|
16
|
-
'revision', 'phase', 'evidenceBasis', 'epistemicState', 'lastVerified', 'nextAction', 'expectedEvidence', 'nextTrigger', 'problemFrame', 'updatedAt',
|
|
16
|
+
'revision', 'phase', 'evidenceBasis', 'epistemicState', 'lastVerified', 'nextAction', 'expectedEvidence', 'verificationProof', 'nextTrigger', 'problemFrame', 'updatedAt',
|
|
17
17
|
]);
|
|
18
18
|
const RUNTIME_KEYS = new Set([...MODEL_KEYS, 'evidenceReceipt']);
|
|
19
19
|
const PROBLEM_FRAME_KEYS = new Set([
|
|
@@ -22,11 +22,28 @@ const PROBLEM_FRAME_KEYS = new Set([
|
|
|
22
22
|
]);
|
|
23
23
|
const NEXT_TRIGGER_KEYS = new Set(['kind', 'condition', 'dueAt']);
|
|
24
24
|
const EVIDENCE_INPUT_KEYS = new Set([
|
|
25
|
+
'turnId', 'toolCallId', 'toolName', 'decision', 'outcome', 'durationMs', 'toolArgs',
|
|
26
|
+
]);
|
|
27
|
+
const REQUIRED_EVIDENCE_INPUT_KEYS = new Set([
|
|
25
28
|
'turnId', 'toolCallId', 'toolName', 'decision', 'outcome', 'durationMs',
|
|
26
29
|
]);
|
|
27
30
|
const EVIDENCE_DIGEST_RE = /^[a-f0-9]{16}$/u;
|
|
28
31
|
const DECISION_BASIS_RE = /^[a-f0-9]{16}$/u;
|
|
29
32
|
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;
|
|
33
|
+
const ACTION_ONLY_TOOL_NAMES = new Set([
|
|
34
|
+
'CreateGoal', 'CronCreate', 'CronDelete', 'DubVideo', 'Edit', 'EnterPlanMode',
|
|
35
|
+
'ExitPlanMode', 'GenerateImage', 'GenerateSpeech', 'GenerateVideo', 'LipSyncMedia',
|
|
36
|
+
'MistakeRecord', 'SetGoalBudget', 'TaskStop', 'TaskUpdate', 'UpdateGoal', 'Write',
|
|
37
|
+
]);
|
|
38
|
+
const VERIFICATION_TOOL_NAMES = new Set([
|
|
39
|
+
'codebasesearch', 'cronlist', 'fetchurl', 'getgoal', 'getmedia', 'glob', 'grep',
|
|
40
|
+
'read', 'readmediafile', 'taskoutput', 'test', 'understandimage', 'understandvideo',
|
|
41
|
+
'websearch',
|
|
42
|
+
]);
|
|
43
|
+
const COMMAND_TOOL_NAMES = new Set(['bash', 'command', 'exec_command', 'shell']);
|
|
44
|
+
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;
|
|
45
|
+
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;
|
|
46
|
+
const MAX_SUCCESSFUL_TOOL_DIGESTS = 32;
|
|
30
47
|
|
|
31
48
|
function bounded(value, field, max = 512) {
|
|
32
49
|
const text = String(value ?? '')
|
|
@@ -148,6 +165,86 @@ function normalizedTurnId(value) {
|
|
|
148
165
|
return turnId;
|
|
149
166
|
}
|
|
150
167
|
|
|
168
|
+
function successfulToolDigest(toolName) {
|
|
169
|
+
const name = bounded(toolName, 'verificationProof toolName', 128);
|
|
170
|
+
return crypto.createHash('sha256').update(`tool:${name}`).digest('hex').slice(0, 16);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function successfulToolCallDigest(turnId, toolCallId, toolName) {
|
|
174
|
+
const turn = normalizedTurnId(turnId);
|
|
175
|
+
const callId = bounded(toolCallId, 'verificationProof toolCallId', 256);
|
|
176
|
+
const name = bounded(toolName, 'verificationProof toolName', 128);
|
|
177
|
+
return crypto.createHash('sha256')
|
|
178
|
+
.update(`turn:${turn}\0call:${callId}\0tool:${name}`)
|
|
179
|
+
.digest('hex')
|
|
180
|
+
.slice(0, 16);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function isActionOnlyTool(toolName) {
|
|
184
|
+
return ACTION_ONLY_TOOL_NAMES.has(String(toolName ?? '').trim());
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function verificationCommand(toolArgs) {
|
|
188
|
+
if (!toolArgs || typeof toolArgs !== 'object' || Array.isArray(toolArgs)) return '';
|
|
189
|
+
const command = toolArgs.command ?? toolArgs.cmd;
|
|
190
|
+
return typeof command === 'string' ? command.trim().replace(/\s+/gu, ' ') : '';
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function isVerificationToolCall(toolName, toolArgs) {
|
|
194
|
+
const normalizedName = String(toolName ?? '').trim().toLowerCase();
|
|
195
|
+
if (VERIFICATION_TOOL_NAMES.has(normalizedName)) return true;
|
|
196
|
+
if (!COMMAND_TOOL_NAMES.has(normalizedName)) return false;
|
|
197
|
+
const command = verificationCommand(toolArgs);
|
|
198
|
+
return command.length > 0
|
|
199
|
+
&& !MUTATING_COMMAND.test(command)
|
|
200
|
+
&& VERIFICATION_COMMAND.test(command);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function normalizeSuccessfulToolDigests(value) {
|
|
204
|
+
if (value === undefined) return Object.freeze([]);
|
|
205
|
+
if (!Array.isArray(value) || value.length > MAX_SUCCESSFUL_TOOL_DIGESTS
|
|
206
|
+
|| value.some((item) => typeof item !== 'string' || !EVIDENCE_DIGEST_RE.test(item))
|
|
207
|
+
|| new Set(value).size !== value.length) {
|
|
208
|
+
throw new TypeError('successful tool digests are invalid');
|
|
209
|
+
}
|
|
210
|
+
return Object.freeze([...value]);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function normalizeVerificationProof(input, evidenceReceipt, options = {}) {
|
|
214
|
+
const keys = input && typeof input === 'object' && !Array.isArray(input)
|
|
215
|
+
? Object.keys(input)
|
|
216
|
+
: [];
|
|
217
|
+
const legacy = options.allowLegacy === true
|
|
218
|
+
&& keys.length === 2
|
|
219
|
+
&& Object.hasOwn(input, 'toolName')
|
|
220
|
+
&& Object.hasOwn(input, 'claim');
|
|
221
|
+
const current = keys.length === 3
|
|
222
|
+
&& Object.hasOwn(input, 'toolCallId')
|
|
223
|
+
&& Object.hasOwn(input, 'toolName')
|
|
224
|
+
&& Object.hasOwn(input, 'claim');
|
|
225
|
+
if (!legacy && !current) {
|
|
226
|
+
throw new TypeError('verificationProof fields are invalid');
|
|
227
|
+
}
|
|
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
|
+
const receipt = normalizeActionEvidenceReceipt(evidenceReceipt);
|
|
234
|
+
if (legacy) {
|
|
235
|
+
if (!receipt.successfulToolDigests.includes(successfulToolDigest(toolName))) {
|
|
236
|
+
throw new TypeError('verificationProof must name a successful current-turn tool');
|
|
237
|
+
}
|
|
238
|
+
return Object.freeze({ toolName, claim });
|
|
239
|
+
}
|
|
240
|
+
const toolCallId = bounded(input.toolCallId, 'verificationProof toolCallId', 256);
|
|
241
|
+
const callDigest = successfulToolCallDigest(receipt.turnId, toolCallId, toolName);
|
|
242
|
+
if (!receipt.successfulToolCallDigests.includes(callDigest)) {
|
|
243
|
+
throw new TypeError('verificationProof must match a successful current-turn verification call');
|
|
244
|
+
}
|
|
245
|
+
return Object.freeze({ toolCallId, toolName, claim });
|
|
246
|
+
}
|
|
247
|
+
|
|
151
248
|
function emptyActionEvidenceReceipt(turnId) {
|
|
152
249
|
const normalized = normalizedTurnId(turnId);
|
|
153
250
|
return Object.freeze({
|
|
@@ -155,14 +252,18 @@ function emptyActionEvidenceReceipt(turnId) {
|
|
|
155
252
|
completedTools: 0,
|
|
156
253
|
successfulTools: 0,
|
|
157
254
|
failedTools: 0,
|
|
255
|
+
successfulToolDigests: Object.freeze([]),
|
|
256
|
+
successfulToolCallDigests: Object.freeze([]),
|
|
158
257
|
digest: crypto.createHash('sha256').update(`turn:${normalized}:empty`).digest('hex').slice(0, 16),
|
|
159
258
|
});
|
|
160
259
|
}
|
|
161
260
|
|
|
162
261
|
function normalizeActionEvidenceReceipt(input) {
|
|
163
262
|
if (!input || typeof input !== 'object' || Array.isArray(input)) throw new TypeError('evidence receipt must be an object');
|
|
164
|
-
const
|
|
165
|
-
|
|
263
|
+
const requiredKeys = new Set(['turnId', 'completedTools', 'successfulTools', 'failedTools', 'digest']);
|
|
264
|
+
const allowedKeys = new Set([...requiredKeys, 'successfulToolDigests', 'successfulToolCallDigests']);
|
|
265
|
+
if (!Object.keys(input).every((key) => allowedKeys.has(key))
|
|
266
|
+
|| ![...requiredKeys].every((key) => Object.hasOwn(input, key))) {
|
|
166
267
|
throw new TypeError('evidence receipt fields are invalid');
|
|
167
268
|
}
|
|
168
269
|
const receipt = {
|
|
@@ -170,6 +271,8 @@ function normalizeActionEvidenceReceipt(input) {
|
|
|
170
271
|
completedTools: Number(input.completedTools),
|
|
171
272
|
successfulTools: Number(input.successfulTools),
|
|
172
273
|
failedTools: Number(input.failedTools),
|
|
274
|
+
successfulToolDigests: normalizeSuccessfulToolDigests(input.successfulToolDigests),
|
|
275
|
+
successfulToolCallDigests: normalizeSuccessfulToolDigests(input.successfulToolCallDigests),
|
|
173
276
|
digest: String(input.digest ?? ''),
|
|
174
277
|
};
|
|
175
278
|
if (![receipt.completedTools, receipt.successfulTools, receipt.failedTools]
|
|
@@ -184,8 +287,8 @@ function normalizeActionEvidenceReceipt(input) {
|
|
|
184
287
|
function advanceActionEvidenceReceipt(current, input) {
|
|
185
288
|
const prior = normalizeActionEvidenceReceipt(current);
|
|
186
289
|
if (!input || typeof input !== 'object' || Array.isArray(input)
|
|
187
|
-
|| Object.keys(input).
|
|
188
|
-
|| !
|
|
290
|
+
|| !Object.keys(input).every((key) => EVIDENCE_INPUT_KEYS.has(key))
|
|
291
|
+
|| ![...REQUIRED_EVIDENCE_INPUT_KEYS].every((key) => Object.hasOwn(input, key))) {
|
|
189
292
|
throw new TypeError('evidence input fields are invalid');
|
|
190
293
|
}
|
|
191
294
|
const turnId = normalizedTurnId(input.turnId);
|
|
@@ -200,14 +303,30 @@ function advanceActionEvidenceReceipt(current, input) {
|
|
|
200
303
|
throw new TypeError('evidence input values are invalid');
|
|
201
304
|
}
|
|
202
305
|
const successful = decision === 'passed' && outcome === 'success';
|
|
306
|
+
const successfulToolDigests = [...prior.successfulToolDigests];
|
|
307
|
+
const successfulToolCallDigests = [...prior.successfulToolCallDigests];
|
|
308
|
+
const toolDigest = successfulToolDigest(toolName);
|
|
309
|
+
if (successful && !successfulToolDigests.includes(toolDigest)) {
|
|
310
|
+
successfulToolDigests.push(toolDigest);
|
|
311
|
+
if (successfulToolDigests.length > MAX_SUCCESSFUL_TOOL_DIGESTS) successfulToolDigests.shift();
|
|
312
|
+
}
|
|
313
|
+
const verificationCall = successful && isVerificationToolCall(toolName, input.toolArgs);
|
|
314
|
+
if (verificationCall) {
|
|
315
|
+
const callDigest = successfulToolCallDigest(turnId, toolCallId, toolName);
|
|
316
|
+
if (!successfulToolCallDigests.includes(callDigest)) successfulToolCallDigests.push(callDigest);
|
|
317
|
+
if (successfulToolCallDigests.length > MAX_SUCCESSFUL_TOOL_DIGESTS) successfulToolCallDigests.shift();
|
|
318
|
+
}
|
|
203
319
|
const digest = crypto.createHash('sha256').update([
|
|
204
320
|
prior.digest, String(turnId), toolCallId, toolName, decision, outcome, String(durationMs),
|
|
321
|
+
String(verificationCall),
|
|
205
322
|
].join('\0')).digest('hex').slice(0, 16);
|
|
206
323
|
return Object.freeze({
|
|
207
324
|
turnId,
|
|
208
325
|
completedTools: prior.completedTools + 1,
|
|
209
326
|
successfulTools: prior.successfulTools + (successful ? 1 : 0),
|
|
210
327
|
failedTools: prior.failedTools + (successful ? 0 : 1),
|
|
328
|
+
successfulToolDigests: Object.freeze(successfulToolDigests),
|
|
329
|
+
successfulToolCallDigests: Object.freeze(successfulToolCallDigests),
|
|
211
330
|
digest,
|
|
212
331
|
});
|
|
213
332
|
}
|
|
@@ -293,6 +412,14 @@ function normalizeActionCheckpoint(input, options = {}) {
|
|
|
293
412
|
? normalizeActionEvidenceReceipt(input.evidenceReceipt)
|
|
294
413
|
: undefined;
|
|
295
414
|
if (evidenceReceipt !== undefined) checkpoint.evidenceReceipt = evidenceReceipt;
|
|
415
|
+
if (input.verificationProof !== undefined) {
|
|
416
|
+
if (phase !== 'verify' || evidenceBasis !== 'runtime_tool') {
|
|
417
|
+
throw new TypeError('verificationProof requires a runtime_tool verify checkpoint');
|
|
418
|
+
}
|
|
419
|
+
checkpoint.verificationProof = normalizeVerificationProof(input.verificationProof, evidenceReceipt, {
|
|
420
|
+
allowLegacy: replay,
|
|
421
|
+
});
|
|
422
|
+
}
|
|
296
423
|
return Object.freeze(checkpoint);
|
|
297
424
|
}
|
|
298
425
|
|
|
@@ -309,6 +436,12 @@ function projectActionCheckpoint(checkpoint) {
|
|
|
309
436
|
];
|
|
310
437
|
lines.push(`Next action: ${value.nextAction}`);
|
|
311
438
|
lines.push(`Expected evidence: ${value.expectedEvidence}`);
|
|
439
|
+
if (value.verificationProof !== undefined) {
|
|
440
|
+
const call = value.verificationProof.toolCallId === undefined
|
|
441
|
+
? value.verificationProof.toolName
|
|
442
|
+
: `${value.verificationProof.toolName} call ${value.verificationProof.toolCallId}`;
|
|
443
|
+
lines.push(`Verification proof: ${call} - ${value.verificationProof.claim}`);
|
|
444
|
+
}
|
|
312
445
|
if (value.nextTrigger !== undefined) {
|
|
313
446
|
lines.push(`Next trigger: ${value.nextTrigger.kind.replaceAll('_', ' ')} - ${value.nextTrigger.condition}`);
|
|
314
447
|
if (value.nextTrigger.dueAt !== undefined) lines.push(`Due at: ${value.nextTrigger.dueAt}`);
|
|
@@ -344,5 +477,8 @@ module.exports = {
|
|
|
344
477
|
assertActionCheckpointRevision,
|
|
345
478
|
emptyActionEvidenceReceipt,
|
|
346
479
|
normalizeActionCheckpoint,
|
|
480
|
+
normalizeVerificationProof,
|
|
347
481
|
projectActionCheckpoint,
|
|
482
|
+
successfulToolCallDigest,
|
|
483
|
+
successfulToolDigest,
|
|
348
484
|
};
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const {
|
|
4
|
+
normalizeVerificationProof,
|
|
5
|
+
} = require('./cognitive-action-checkpoint.cjs');
|
|
6
|
+
|
|
3
7
|
function hasCompletionCriterion(goal) {
|
|
4
8
|
return typeof goal?.completionCriterion === 'string'
|
|
5
9
|
&& goal.completionCriterion.trim().length > 0;
|
|
@@ -10,6 +14,24 @@ function successfulRuntimeEvidence(checkpoint) {
|
|
|
10
14
|
return Number.isSafeInteger(successfulTools) && successfulTools > 0;
|
|
11
15
|
}
|
|
12
16
|
|
|
17
|
+
function verificationProofGaps(checkpoint) {
|
|
18
|
+
if (!checkpoint?.verificationProof) {
|
|
19
|
+
return ['Bind the completion claim to a successful verification tool from the checkpoint turn.'];
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
normalizeVerificationProof(checkpoint.verificationProof, checkpoint.evidenceReceipt, { allowLegacy: true });
|
|
23
|
+
return [];
|
|
24
|
+
} catch (error) {
|
|
25
|
+
if (/action-only tool/u.test(String(error?.message ?? ''))) {
|
|
26
|
+
return ['The completion proof names an action-only tool, not a verification tool.'];
|
|
27
|
+
}
|
|
28
|
+
if (/successful current-turn (?:tool|verification call)/u.test(String(error?.message ?? ''))) {
|
|
29
|
+
return ['The completion proof does not match a successful verification call from the checkpoint turn.'];
|
|
30
|
+
}
|
|
31
|
+
return ['The completion verification proof is malformed.'];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
13
35
|
function evaluateGoalCompletionEvidence(goal) {
|
|
14
36
|
if (!hasCompletionCriterion(goal)) {
|
|
15
37
|
return {
|
|
@@ -40,9 +62,16 @@ function evaluateGoalCompletionEvidence(goal) {
|
|
|
40
62
|
if (checkpoint.epistemicState !== 'verified') {
|
|
41
63
|
gaps.push('The completion proof must be classified as verified.');
|
|
42
64
|
}
|
|
43
|
-
|
|
65
|
+
const hasRuntimeEvidence = successfulRuntimeEvidence(checkpoint);
|
|
66
|
+
if (!hasRuntimeEvidence) {
|
|
44
67
|
gaps.push('The runtime evidence receipt must contain at least one successful tool result.');
|
|
45
68
|
}
|
|
69
|
+
if (checkpoint.phase === 'verify'
|
|
70
|
+
&& checkpoint.evidenceBasis === 'runtime_tool'
|
|
71
|
+
&& checkpoint.epistemicState === 'verified'
|
|
72
|
+
&& hasRuntimeEvidence) {
|
|
73
|
+
gaps.push(...verificationProofGaps(checkpoint));
|
|
74
|
+
}
|
|
46
75
|
|
|
47
76
|
return {
|
|
48
77
|
required: true,
|
package/blun.mjs
CHANGED
|
@@ -260348,6 +260348,11 @@ function createActionCheckpointInputSchema(problemFrameSchema, requireProblemFra
|
|
|
260348
260348
|
lastVerified: string().min(1).max(512),
|
|
260349
260349
|
nextAction: string().min(1).max(512),
|
|
260350
260350
|
expectedEvidence: string().min(1).max(512),
|
|
260351
|
+
verificationProof: object({
|
|
260352
|
+
toolCallId: string().min(1).max(256),
|
|
260353
|
+
toolName: string().min(1).max(128),
|
|
260354
|
+
claim: string().min(1).max(512)
|
|
260355
|
+
}).strict().optional(),
|
|
260351
260356
|
nextTrigger: object({
|
|
260352
260357
|
kind: _enum(["immediate", "external_event", "time", "dependency", "user_decision"]),
|
|
260353
260358
|
condition: string().min(1).max(512),
|
|
@@ -262733,6 +262738,7 @@ var init_turn = __esmMin((() => {
|
|
|
262733
262738
|
this.toolCallDupType.set(event.toolCallId, dupType === "cross_step" ? "cross_step" : "normal");
|
|
262734
262739
|
this.toolCallStartedAt.set(event.toolCallId, {
|
|
262735
262740
|
name: event.name,
|
|
262741
|
+
args: event.args,
|
|
262736
262742
|
startedAt: Date.now()
|
|
262737
262743
|
});
|
|
262738
262744
|
this.agent.feedRootMissionContract("start", {
|
|
@@ -262763,7 +262769,8 @@ var init_turn = __esmMin((() => {
|
|
|
262763
262769
|
toolCallId: event.toolCallId,
|
|
262764
262770
|
toolName: started.name,
|
|
262765
262771
|
outcome,
|
|
262766
|
-
durationMs: Date.now() - started.startedAt
|
|
262772
|
+
durationMs: Date.now() - started.startedAt,
|
|
262773
|
+
toolArgs: started.args
|
|
262767
262774
|
});
|
|
262768
262775
|
this.agent.telemetry.track("tool_call", properties);
|
|
262769
262776
|
this.agent.feedRootMissionContract("result", {
|
|
@@ -262868,6 +262875,7 @@ var init_outcome_prompts = __esmMin((() => {}));
|
|
|
262868
262875
|
var update_goal_default;
|
|
262869
262876
|
var init_update_goal$1 = __esmMin((() => {
|
|
262870
262877
|
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. Run a separate observation, test, or counterexample probe and cite that exact successful call plus the claim it supports.\n";
|
|
262871
262879
|
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";
|
|
262872
262880
|
}));
|
|
262873
262881
|
//#endregion
|