blun-king-cli 9.1.413 → 9.1.415

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/LIESMICH.txt CHANGED
@@ -475,6 +475,23 @@ Bereits über das Reply-Werkzeug zugestellte Antworten werden dabei nicht
475
475
  wiederholt. Die Fortsetzung ist auf drei Versuche begrenzt; danach wird niemals
476
476
  ein abgeschnittener Text als Ergebnis ausgegeben.
477
477
 
478
+ Ab BLUN King 9.1.414 trägt jeder neue dauerhafte Aktions-Checkpoint zusätzlich
479
+ den genauen Auslöser für seinen nächsten Schritt. Außerhalb einer Wartephase
480
+ muss dieser Auslöser „sofort“ sein. Eine Wartephase benennt stattdessen ein
481
+ äußeres Ereignis, einen Zeitpunkt, eine Abhängigkeit oder eine ausstehende
482
+ Nutzerentscheidung. Auslöser und Bedingung bleiben bei Fortsetzung und Neustart
483
+ erhalten, ohne Berechtigungen zu erteilen. Bereits gespeicherte ältere
484
+ Checkpoints bleiben lesbar.
485
+
486
+ Ab BLUN King 9.1.415 übernimmt der sitzungsübergreifende Arbeitsfokus den
487
+ gespeicherten Auslöser vollständig. Die nächste Aktion und die Bedingung, unter
488
+ der sie ausgeführt werden darf, bleiben getrennt sichtbar. Dadurch erscheint
489
+ eine Wartephase nach einem Neustart oder Kontextwechsel nicht mehr als sofortiger
490
+ Arbeitsauftrag. Art und Bedingung des Auslösers verändern außerdem die Identität
491
+ des dauerhaften Fokuszustands; fehlerhafte oder zur Phase widersprüchliche
492
+ Auslöser werden verworfen. Ältere Checkpoints ohne ausdrücklichen Auslöser
493
+ behalten ihr bisheriges Verhalten.
494
+
478
495
  Der eigentliche Anhang und die vollständige Nutzernachricht bleiben für den Zug
479
496
  unverändert verfügbar. Die Begrenzung betrifft ausschließlich die kleine
480
497
  lexikalische Vorauswahl von höchstens zwei Werkzeugschemas; ToolSearch und alle
package/README.md CHANGED
@@ -481,6 +481,23 @@ diese. Bereits über das Reply-Werkzeug zugestellte Antworten werden dabei nicht
481
481
  wiederholt. Die Fortsetzung ist auf drei Versuche begrenzt; danach wird niemals
482
482
  ein abgeschnittener Text als Ergebnis ausgegeben.
483
483
 
484
+ Ab BLUN King 9.1.414 trägt jeder neue dauerhafte Aktions-Checkpoint zusätzlich
485
+ den genauen Auslöser für seinen nächsten Schritt. Außerhalb einer Wartephase
486
+ muss dieser Auslöser „sofort“ sein. Eine Wartephase benennt stattdessen ein
487
+ äußeres Ereignis, einen Zeitpunkt, eine Abhängigkeit oder eine ausstehende
488
+ Nutzerentscheidung. Auslöser und Bedingung bleiben bei Fortsetzung und Neustart
489
+ erhalten, ohne Berechtigungen zu erteilen. Bereits gespeicherte ältere
490
+ Checkpoints bleiben lesbar.
491
+
492
+ Ab BLUN King 9.1.415 übernimmt der sitzungsübergreifende Arbeitsfokus den
493
+ gespeicherten Auslöser vollständig. Die nächste Aktion und die Bedingung, unter
494
+ der sie ausgeführt werden darf, bleiben getrennt sichtbar. Dadurch erscheint
495
+ eine Wartephase nach einem Neustart oder Kontextwechsel nicht mehr als sofortiger
496
+ Arbeitsauftrag. Art und Bedingung des Auslösers verändern außerdem die Identität
497
+ des dauerhaften Fokuszustands; fehlerhafte oder zur Phase widersprüchliche
498
+ Auslöser werden verworfen. Ältere Checkpoints ohne ausdrücklichen Auslöser
499
+ behalten ihr bisheriges Verhalten.
500
+
484
501
  Der eigentliche Anhang und die vollständige Nutzernachricht bleiben für den Zug
485
502
  unverändert verfügbar. Die Begrenzung betrifft ausschließlich die kleine
486
503
  lexikalische Vorauswahl von höchstens zwei Werkzeugschemas; ToolSearch und alle
@@ -9,14 +9,18 @@ const EVIDENCE_BASES = new Set([
9
9
  const EPISTEMIC_STATES = new Set([
10
10
  'verified', 'credible_unverified', 'hypothesis', 'uncertain_memory', 'stale', 'unknown',
11
11
  ]);
12
+ const TRIGGER_KINDS = new Set([
13
+ 'immediate', 'external_event', 'time', 'dependency', 'user_decision',
14
+ ]);
12
15
  const MODEL_KEYS = new Set([
13
- 'revision', 'phase', 'evidenceBasis', 'epistemicState', 'lastVerified', 'nextAction', 'expectedEvidence', 'problemFrame', 'updatedAt',
16
+ 'revision', 'phase', 'evidenceBasis', 'epistemicState', 'lastVerified', 'nextAction', 'expectedEvidence', 'nextTrigger', 'problemFrame', 'updatedAt',
14
17
  ]);
15
18
  const RUNTIME_KEYS = new Set([...MODEL_KEYS, 'evidenceReceipt']);
16
19
  const PROBLEM_FRAME_KEYS = new Set([
17
20
  'successCriterion', 'missingKnowledge', 'candidateActions', 'selectedAction',
18
21
  'selectionReason', 'supportChoice', 'risk', 'reversibility',
19
22
  ]);
23
+ const NEXT_TRIGGER_KEYS = new Set(['kind', 'condition']);
20
24
  const EVIDENCE_INPUT_KEYS = new Set([
21
25
  'turnId', 'toolCallId', 'toolName', 'decision', 'outcome', 'durationMs',
22
26
  ]);
@@ -77,6 +81,27 @@ function normalizeProblemFrame(input) {
77
81
  });
78
82
  }
79
83
 
84
+ function normalizeNextTrigger(input, phase) {
85
+ if (!input || typeof input !== 'object' || Array.isArray(input)) {
86
+ throw new TypeError('nextTrigger must be an object');
87
+ }
88
+ for (const key of Object.keys(input)) {
89
+ if (!NEXT_TRIGGER_KEYS.has(key)) throw new TypeError(`nextTrigger field is unsupported: ${key}`);
90
+ }
91
+ const kind = String(input.kind ?? '').trim();
92
+ if (!TRIGGER_KINDS.has(kind)) throw new TypeError('nextTrigger kind is invalid');
93
+ if (phase === 'wait' && kind === 'immediate') {
94
+ throw new TypeError('wait phase requires a non-immediate nextTrigger');
95
+ }
96
+ if (phase !== 'wait' && kind !== 'immediate') {
97
+ throw new TypeError('non-wait phase requires an immediate nextTrigger');
98
+ }
99
+ return Object.freeze({
100
+ kind,
101
+ condition: bounded(input.condition, 'nextTrigger condition'),
102
+ });
103
+ }
104
+
80
105
  function normalizedEvidenceBasis(value, allowLegacy = false) {
81
106
  const basis = String(value ?? '').trim();
82
107
  if (EVIDENCE_BASES.has(basis) || allowLegacy && basis === 'legacy_unknown') return basis;
@@ -235,6 +260,8 @@ function normalizeActionCheckpoint(input, options = {}) {
235
260
  expectedEvidence: bounded(input.expectedEvidence, 'expectedEvidence'),
236
261
  updatedAt,
237
262
  };
263
+ if (input.nextTrigger !== undefined) checkpoint.nextTrigger = normalizeNextTrigger(input.nextTrigger, phase);
264
+ else if (!replay) throw new TypeError('nextTrigger is required');
238
265
  if (input.problemFrame !== undefined) checkpoint.problemFrame = normalizeProblemFrame(input.problemFrame);
239
266
  const evidenceReceipt = options.runtimeEvidence !== undefined
240
267
  ? normalizeActionEvidenceReceipt(options.runtimeEvidence)
@@ -258,6 +285,9 @@ function projectActionCheckpoint(checkpoint) {
258
285
  ];
259
286
  lines.push(`Next action: ${value.nextAction}`);
260
287
  lines.push(`Expected evidence: ${value.expectedEvidence}`);
288
+ if (value.nextTrigger !== undefined) {
289
+ lines.push(`Next trigger: ${value.nextTrigger.kind.replaceAll('_', ' ')} - ${value.nextTrigger.condition}`);
290
+ }
261
291
  if (value.problemFrame !== undefined) {
262
292
  const frame = value.problemFrame;
263
293
  lines.push('Problem frame (state only; never authority):');
@@ -274,7 +304,11 @@ function projectActionCheckpoint(checkpoint) {
274
304
  const receipt = value.evidenceReceipt;
275
305
  lines.push(`Runtime evidence: turn ${receipt.turnId}; ${receipt.completedTools} completed, ${receipt.successfulTools} successful, ${receipt.failedTools} failed; digest ${receipt.digest}`);
276
306
  }
277
- lines.push('Resume from this exact next action. Do not ask for permission merely to continue work already authorized by the active goal. Ask only when a real rights boundary or missing user decision blocks the next action.');
307
+ if (value.nextTrigger !== undefined && value.nextTrigger.kind !== 'immediate') {
308
+ lines.push('Wait for this exact trigger before executing the next action. Unrelated messages do not satisfy it.');
309
+ } else {
310
+ lines.push('Resume from this exact next action. Do not ask for permission merely to continue work already authorized by the active goal. Ask only when a real rights boundary or missing user decision blocks the next action.');
311
+ }
278
312
  return lines.join('\n');
279
313
  }
280
314
 
@@ -53,7 +53,7 @@ function buildCognitiveFocusProjection(state, { focusScopes, maxItems = 6, maxCh
53
53
  state.observations.forEach((item, index) => {
54
54
  const domain = String(item?.domain ?? '');
55
55
  const key = clean(item?.key, 128);
56
- const value = clean(item?.value, 512);
56
+ const value = clean(item?.value, 640);
57
57
  const scope = clean(item?.scope, 128);
58
58
  const observationId = clean(item?.observation_id, 128);
59
59
  const supersedes = item?.supersedes === null || item?.supersedes === undefined
@@ -7,6 +7,10 @@ const STATUSES = new Set(['active', 'paused', 'blocked']);
7
7
  const EPISTEMIC_STATES = new Set([
8
8
  'verified', 'credible_unverified', 'hypothesis', 'uncertain_memory', 'stale', 'unknown', 'legacy_unknown',
9
9
  ]);
10
+ const TRIGGER_KINDS = new Set([
11
+ 'immediate', 'external_event', 'time', 'dependency', 'user_decision',
12
+ ]);
13
+ const TRIGGER_KEYS = new Set(['kind', 'condition']);
10
14
  const NEXT_TRIGGER = new Map([
11
15
  ['active', 'Continue the active goal from its last verified state.'],
12
16
  ['paused', 'Wait until the goal is explicitly resumed.'],
@@ -40,6 +44,23 @@ function buildCognitiveWorkFocus(goal) {
40
44
  const nextAction = bounded(checkpoint?.nextAction);
41
45
  const checkpointEvidence = bounded(checkpoint?.expectedEvidence);
42
46
  const checkpointEpistemicState = bounded(checkpoint?.epistemicState, 32);
47
+ const rawNextTrigger = checkpoint?.nextTrigger;
48
+ let triggerKind = '';
49
+ let triggerCondition = '';
50
+ if (rawNextTrigger !== undefined) {
51
+ if (!rawNextTrigger || typeof rawNextTrigger !== 'object' || Array.isArray(rawNextTrigger)
52
+ || Object.keys(rawNextTrigger).length !== TRIGGER_KEYS.size
53
+ || Object.keys(rawNextTrigger).some((key) => !TRIGGER_KEYS.has(key))) return null;
54
+ triggerKind = String(rawNextTrigger.kind ?? '').trim();
55
+ triggerCondition = bounded(rawNextTrigger.condition);
56
+ if (!TRIGGER_KINDS.has(triggerKind) || !triggerCondition
57
+ || checkpointPhase === 'wait' && triggerKind === 'immediate'
58
+ || checkpointPhase !== 'wait' && triggerKind !== 'immediate') return null;
59
+ }
60
+ const hasExplicitTrigger = Boolean(triggerKind && triggerCondition);
61
+ const triggerValue = hasExplicitTrigger
62
+ ? `${triggerKind.replaceAll('_', ' ')} - ${triggerCondition}`
63
+ : nextAction;
43
64
  const problemFrame = checkpoint?.problemFrame && typeof checkpoint.problemFrame === 'object'
44
65
  && !Array.isArray(checkpoint.problemFrame) ? checkpoint.problemFrame : null;
45
66
  const frameMissingKnowledge = Array.isArray(problemFrame?.missingKnowledge)
@@ -69,6 +90,8 @@ function buildCognitiveWorkFocus(goal) {
69
90
  hasCheckpoint ? lastVerified : '',
70
91
  hasCheckpoint ? nextAction : '',
71
92
  hasCheckpoint ? checkpointEvidence : '',
93
+ hasExplicitTrigger ? triggerKind : '',
94
+ hasExplicitTrigger ? triggerCondition : '',
72
95
  epistemicState,
73
96
  hasProblemFrame ? frameSuccessCriterion : '',
74
97
  hasProblemFrame ? frameMissingKnowledge.join('\0') : '',
@@ -91,6 +114,7 @@ function buildCognitiveWorkFocus(goal) {
91
114
  value: bounded(hasCheckpoint
92
115
  ? [
93
116
  `Goal is ${status}. Phase ${checkpointPhase}. Last verified: ${lastVerified}`,
117
+ `Next action: ${nextAction}`,
94
118
  hasProblemFrame ? `Missing knowledge: ${frameMissingKnowledge.join(' | ')}` : '',
95
119
  hasProblemFrame ? `Risk: ${frameRisk}` : '',
96
120
  hasProblemFrame ? `Selected action: ${frameSelectedAction}` : '',
@@ -100,7 +124,7 @@ function buildCognitiveWorkFocus(goal) {
100
124
  },
101
125
  {
102
126
  domain: 'next_trigger', key: `${keyRoot}:next`,
103
- value: status === 'active' && hasCheckpoint ? nextAction : NEXT_TRIGGER.get(status),
127
+ value: status === 'active' && hasCheckpoint ? triggerValue : NEXT_TRIGGER.get(status),
104
128
  confidence: 1, epistemicState, scope: focusScope,
105
129
  },
106
130
  {
package/blun.mjs CHANGED
@@ -231135,7 +231135,8 @@ function buildGoalReminder(goal) {
231135
231135
  if (checkpointProjection !== null) {
231136
231136
  lines.push("");
231137
231137
  lines.push(checkpointProjection);
231138
- lines.push("Execute the exact checkpointed next action before exploring alternatives. Update the checkpoint only after new evidence changes the verified state.");
231138
+ if (goal.actionCheckpoint?.nextTrigger?.kind === "immediate" || goal.actionCheckpoint?.nextTrigger === void 0) lines.push("Execute the exact checkpointed next action before exploring alternatives. Update the checkpoint only after new evidence changes the verified state.");
231139
+ else lines.push("Keep the goal active, but do not execute the next action until its projected trigger is observed. Unrelated messages do not satisfy that trigger.");
231139
231140
  }
231140
231141
  const budget = goal.budget;
231141
231142
  const budgetLines = [];
@@ -245762,6 +245763,10 @@ var init_events$1 = __esmMin((() => {
245762
245763
  lastVerified: string(),
245763
245764
  nextAction: string(),
245764
245765
  expectedEvidence: string(),
245766
+ nextTrigger: object({
245767
+ kind: _enum(["immediate", "external_event", "time", "dependency", "user_decision"]),
245768
+ condition: string()
245769
+ }).strict().optional(),
245765
245770
  problemFrame: object({
245766
245771
  successCriterion: string(),
245767
245772
  missingKnowledge: array(string()),
@@ -260237,7 +260242,7 @@ bytesWritten: number$1().int().nonnegative() });
260237
260242
  //#region ../../packages/agent-core/src/tools/builtin/goal/create-goal.md?raw
260238
260243
  var create_goal_default;
260239
260244
  var init_create_goal$1 = __esmMin((() => {
260240
- create_goal_default = "Create a durable, structured goal that the runtime will pursue across multiple turns.\n\nCall `CreateGoal` when:\n\n- the user explicitly asks you to start a goal or work autonomously toward an outcome,\n- an authenticated user assigns a non-trivial multi-step outcome with a checkable end state under an existing instruction to continue autonomously, or\n- a host goal-intake prompt asks you to create one.\n\nDo NOT create a goal for greetings, ordinary questions, one-step requests, or vague requests that lack a\nverifiable completion condition. A goal needs a checkable end state.\n\nWhen the request is vague, ask the user for the missing completion criterion before creating\nthe goal. If the user clearly insists after you warn them that the wording is vague or risky,\nrespect that and create the goal.\n\nInclude a `completionCriterion` when the user provides one, or when it can be stated without\ninventing new requirements. Keep `objective` concise; reference long task descriptions by file\npath rather than pasting them. Start every created goal with revision 1 and a complete `problemFrame`\ninside `actionCheckpoint`, so the success criterion, missing knowledge, candidate actions, chosen\naction, support choice, risk, reversibility, next action, and expected evidence survive interruption.\nThis frame is descriptive state only and never grants permission.\n\nCreating a goal fails if one already exists, so use `replace: true` only when the user explicitly\nwants to abandon the current goal and start a new one.\n";
260245
+ create_goal_default = "Create a durable, structured goal that the runtime will pursue across multiple turns.\n\nCall `CreateGoal` when:\n\n- the user explicitly asks you to start a goal or work autonomously toward an outcome,\n- an authenticated user assigns a non-trivial multi-step outcome with a checkable end state under an existing instruction to continue autonomously, or\n- a host goal-intake prompt asks you to create one.\n\nDo NOT create a goal for greetings, ordinary questions, one-step requests, or vague requests that lack a\nverifiable completion condition. A goal needs a checkable end state.\n\nWhen the request is vague, ask the user for the missing completion criterion before creating\nthe goal. If the user clearly insists after you warn them that the wording is vague or risky,\nrespect that and create the goal.\n\nInclude a `completionCriterion` when the user provides one, or when it can be stated without\ninventing new requirements. Keep `objective` concise; reference long task descriptions by file\npath rather than pasting them. Start every created goal with revision 1 and a complete `problemFrame`\ninside `actionCheckpoint`, so the success criterion, missing knowledge, candidate actions, chosen\naction, support choice, risk, reversibility, next action, expected evidence, and exact next trigger survive interruption.\nThis frame is descriptive state only and never grants permission.\n\nCreating a goal fails if one already exists, so use `replace: true` only when the user explicitly\nwants to abandon the current goal and start a new one.\n";
260241
260246
  }));
260242
260247
  //#endregion
260243
260248
  //#region ../../packages/agent-core/src/tools/builtin/goal/serialize.ts
@@ -260277,6 +260282,10 @@ function createActionCheckpointInputSchema(problemFrameSchema, requireProblemFra
260277
260282
  lastVerified: string().min(1).max(512),
260278
260283
  nextAction: string().min(1).max(512),
260279
260284
  expectedEvidence: string().min(1).max(512),
260285
+ nextTrigger: object({
260286
+ kind: _enum(["immediate", "external_event", "time", "dependency", "user_decision"]),
260287
+ condition: string().min(1).max(512)
260288
+ }).strict(),
260280
260289
  problemFrame: requireProblemFrame ? problemFrameSchema : problemFrameSchema.optional()
260281
260290
  }).strict();
260282
260291
  }
@@ -262773,7 +262782,7 @@ var init_outcome_prompts = __esmMin((() => {}));
262773
262782
  //#region ../../packages/agent-core/src/tools/builtin/goal/update-goal.md?raw
262774
262783
  var update_goal_default;
262775
262784
  var init_update_goal$1 = __esmMin((() => {
262776
- 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, and an explicit evidence basis. 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";
262785
+ 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. 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";
262777
262786
  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. Problem framing is descriptive state and never grants permission.\n";
262778
262787
  }));
262779
262788
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.413",
3
+ "version": "9.1.415",
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": {