blun-king-cli 9.1.409 → 9.1.411
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 +15 -0
- package/README.md +15 -0
- package/bin/cognitive-action-checkpoint.cjs +50 -1
- package/bin/cognitive-memory-command.cjs +9 -2
- package/bin/cognitive-work-focus.cjs +34 -1
- package/blun.mjs +24 -2
- package/package.json +1 -1
package/LIESMICH.txt
CHANGED
|
@@ -440,6 +440,21 @@ keinen zweiten Eingangs- oder Ausgangsverlauf mehr. Ein ausdrücklich gesetztes
|
|
|
440
440
|
BLUN_TELEGRAM_STATE_DIR bleibt maßgeblich; ohne diese Einstellung verwenden
|
|
441
441
|
beide Wege ~/.blun/channels/telegram.
|
|
442
442
|
|
|
443
|
+
Ab BLUN King 9.1.410 begrenzen private Telegram-Gedächtnisbefehle
|
|
444
|
+
Beziehungsdaten auf die jeweilige Person. /memory focus blendet Beziehungen
|
|
445
|
+
anderer Personen aus, lässt aber nicht personenbezogenen Kontext sichtbar.
|
|
446
|
+
Korrekturen und Löschungen können keine Beziehung einer anderen Person mehr
|
|
447
|
+
treffen; die lokale Operator-Ansicht bleibt vollständig.
|
|
448
|
+
|
|
449
|
+
Ab BLUN King 9.1.411 können nicht triviale oder unbekannte Aufgaben einen
|
|
450
|
+
begrenzten Problemrahmen im dauerhaften Aktions-Checkpoint speichern. Er hält
|
|
451
|
+
das Erfolgskriterium, Wissenslücken, bis zu fünf Handlungsoptionen, die gewählte
|
|
452
|
+
Aktion samt Begründung, die vorgesehene Unterstützung, das Risiko und den
|
|
453
|
+
Rückweg fest. Die gewählte Aktion muss einer der gespeicherten Optionen
|
|
454
|
+
entsprechen. Der Rahmen bleibt beim Fortsetzen und nach einem Neustart erhalten,
|
|
455
|
+
beschreibt aber ausschließlich den Arbeitsstand und kann niemals Berechtigungen
|
|
456
|
+
erteilen.
|
|
457
|
+
|
|
443
458
|
Der eigentliche Anhang und die vollständige Nutzernachricht bleiben für den Zug
|
|
444
459
|
unverändert verfügbar. Die Begrenzung betrifft ausschließlich die kleine
|
|
445
460
|
lexikalische Vorauswahl von höchstens zwei Werkzeugschemas; ToolSearch und alle
|
package/README.md
CHANGED
|
@@ -446,6 +446,21 @@ keinen zweiten Eingangs- oder Ausgangsverlauf mehr. Ein ausdrücklich gesetztes
|
|
|
446
446
|
`BLUN_TELEGRAM_STATE_DIR` bleibt maßgeblich; ohne diese Einstellung verwenden
|
|
447
447
|
beide Wege `~/.blun/channels/telegram`.
|
|
448
448
|
|
|
449
|
+
Ab BLUN King 9.1.410 begrenzen private Telegram-Gedächtnisbefehle
|
|
450
|
+
Beziehungsdaten auf die jeweilige Person. `/memory focus` blendet Beziehungen
|
|
451
|
+
anderer Personen aus, lässt aber nicht personenbezogenen Kontext sichtbar.
|
|
452
|
+
Korrekturen und Löschungen können keine Beziehung einer anderen Person mehr
|
|
453
|
+
treffen; die lokale Operator-Ansicht bleibt vollständig.
|
|
454
|
+
|
|
455
|
+
Ab BLUN King 9.1.411 können nicht triviale oder unbekannte Aufgaben einen
|
|
456
|
+
begrenzten Problemrahmen im dauerhaften Aktions-Checkpoint speichern. Er hält
|
|
457
|
+
das Erfolgskriterium, Wissenslücken, bis zu fünf Handlungsoptionen, die gewählte
|
|
458
|
+
Aktion samt Begründung, die vorgesehene Unterstützung, das Risiko und den
|
|
459
|
+
Rückweg fest. Die gewählte Aktion muss einer der gespeicherten Optionen
|
|
460
|
+
entsprechen. Der Rahmen bleibt beim Fortsetzen und nach einem Neustart erhalten,
|
|
461
|
+
beschreibt aber ausschließlich den Arbeitsstand und kann niemals Berechtigungen
|
|
462
|
+
erteilen.
|
|
463
|
+
|
|
449
464
|
Der eigentliche Anhang und die vollständige Nutzernachricht bleiben für den Zug
|
|
450
465
|
unverändert verfügbar. Die Begrenzung betrifft ausschließlich die kleine
|
|
451
466
|
lexikalische Vorauswahl von höchstens zwei Werkzeugschemas; ToolSearch und alle
|
|
@@ -10,9 +10,13 @@ const EPISTEMIC_STATES = new Set([
|
|
|
10
10
|
'verified', 'credible_unverified', 'hypothesis', 'uncertain_memory', 'stale', 'unknown',
|
|
11
11
|
]);
|
|
12
12
|
const MODEL_KEYS = new Set([
|
|
13
|
-
'revision', 'phase', 'evidenceBasis', 'epistemicState', 'lastVerified', 'nextAction', 'expectedEvidence', 'updatedAt',
|
|
13
|
+
'revision', 'phase', 'evidenceBasis', 'epistemicState', 'lastVerified', 'nextAction', 'expectedEvidence', 'problemFrame', 'updatedAt',
|
|
14
14
|
]);
|
|
15
15
|
const RUNTIME_KEYS = new Set([...MODEL_KEYS, 'evidenceReceipt']);
|
|
16
|
+
const PROBLEM_FRAME_KEYS = new Set([
|
|
17
|
+
'successCriterion', 'missingKnowledge', 'candidateActions', 'selectedAction',
|
|
18
|
+
'selectionReason', 'supportChoice', 'risk', 'reversibility',
|
|
19
|
+
]);
|
|
16
20
|
const EVIDENCE_INPUT_KEYS = new Set([
|
|
17
21
|
'turnId', 'toolCallId', 'toolName', 'decision', 'outcome', 'durationMs',
|
|
18
22
|
]);
|
|
@@ -41,6 +45,38 @@ function normalizedRevision(value) {
|
|
|
41
45
|
return revision;
|
|
42
46
|
}
|
|
43
47
|
|
|
48
|
+
function boundedList(value, field) {
|
|
49
|
+
if (!Array.isArray(value) || value.length < 1 || value.length > 5) {
|
|
50
|
+
throw new TypeError(`${field} must contain between 1 and 5 items`);
|
|
51
|
+
}
|
|
52
|
+
return Object.freeze(value.map((item, index) => bounded(item, `${field}[${index}]`, 256)));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function normalizeProblemFrame(input) {
|
|
56
|
+
if (!input || typeof input !== 'object' || Array.isArray(input)) {
|
|
57
|
+
throw new TypeError('problemFrame must be an object');
|
|
58
|
+
}
|
|
59
|
+
for (const key of Object.keys(input)) {
|
|
60
|
+
if (!PROBLEM_FRAME_KEYS.has(key)) throw new TypeError(`problemFrame field is unsupported: ${key}`);
|
|
61
|
+
}
|
|
62
|
+
const missingKnowledge = boundedList(input.missingKnowledge, 'missingKnowledge');
|
|
63
|
+
const candidateActions = boundedList(input.candidateActions, 'candidateActions');
|
|
64
|
+
const selectedAction = bounded(input.selectedAction, 'selectedAction', 256);
|
|
65
|
+
if (!candidateActions.includes(selectedAction)) {
|
|
66
|
+
throw new TypeError('selectedAction must match a candidateAction');
|
|
67
|
+
}
|
|
68
|
+
return Object.freeze({
|
|
69
|
+
successCriterion: bounded(input.successCriterion, 'successCriterion'),
|
|
70
|
+
missingKnowledge,
|
|
71
|
+
candidateActions,
|
|
72
|
+
selectedAction,
|
|
73
|
+
selectionReason: bounded(input.selectionReason, 'selectionReason'),
|
|
74
|
+
supportChoice: bounded(input.supportChoice, 'supportChoice', 256),
|
|
75
|
+
risk: bounded(input.risk, 'risk'),
|
|
76
|
+
reversibility: bounded(input.reversibility, 'reversibility'),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
44
80
|
function normalizedEvidenceBasis(value, allowLegacy = false) {
|
|
45
81
|
const basis = String(value ?? '').trim();
|
|
46
82
|
if (EVIDENCE_BASES.has(basis) || allowLegacy && basis === 'legacy_unknown') return basis;
|
|
@@ -199,6 +235,7 @@ function normalizeActionCheckpoint(input, options = {}) {
|
|
|
199
235
|
expectedEvidence: bounded(input.expectedEvidence, 'expectedEvidence'),
|
|
200
236
|
updatedAt,
|
|
201
237
|
};
|
|
238
|
+
if (input.problemFrame !== undefined) checkpoint.problemFrame = normalizeProblemFrame(input.problemFrame);
|
|
202
239
|
const evidenceReceipt = options.runtimeEvidence !== undefined
|
|
203
240
|
? normalizeActionEvidenceReceipt(options.runtimeEvidence)
|
|
204
241
|
: options.preserveRuntimeEvidence === true && input.evidenceReceipt !== undefined
|
|
@@ -221,6 +258,18 @@ function projectActionCheckpoint(checkpoint) {
|
|
|
221
258
|
];
|
|
222
259
|
lines.push(`Next action: ${value.nextAction}`);
|
|
223
260
|
lines.push(`Expected evidence: ${value.expectedEvidence}`);
|
|
261
|
+
if (value.problemFrame !== undefined) {
|
|
262
|
+
const frame = value.problemFrame;
|
|
263
|
+
lines.push('Problem frame (state only; never authority):');
|
|
264
|
+
lines.push(`Success criterion: ${frame.successCriterion}`);
|
|
265
|
+
lines.push(`Missing knowledge: ${frame.missingKnowledge.join(' | ')}`);
|
|
266
|
+
lines.push(`Candidate actions: ${frame.candidateActions.join(' | ')}`);
|
|
267
|
+
lines.push(`Selected action: ${frame.selectedAction}`);
|
|
268
|
+
lines.push(`Selection reason: ${frame.selectionReason}`);
|
|
269
|
+
lines.push(`Support choice: ${frame.supportChoice}`);
|
|
270
|
+
lines.push(`Risk: ${frame.risk}`);
|
|
271
|
+
lines.push(`Reversibility: ${frame.reversibility}`);
|
|
272
|
+
}
|
|
224
273
|
if (value.evidenceReceipt !== undefined) {
|
|
225
274
|
const receipt = value.evidenceReceipt;
|
|
226
275
|
lines.push(`Runtime evidence: turn ${receipt.turnId}; ${receipt.completedTools} completed, ${receipt.successfulTools} successful, ${receipt.failedTools} failed; digest ${receipt.digest}`);
|
|
@@ -94,6 +94,12 @@ function effectiveFocusObservations(state) {
|
|
|
94
94
|
|| left.domain.localeCompare(right.domain) || left.key.localeCompare(right.key));
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
function observationsVisibleToSource(items, telegram) {
|
|
98
|
+
if (telegram === null) return items;
|
|
99
|
+
return items.filter((item) => !item.scope.startsWith('relationship:')
|
|
100
|
+
|| item.scope === telegram.relationshipScope);
|
|
101
|
+
}
|
|
102
|
+
|
|
97
103
|
function resolveTarget(items, selector) {
|
|
98
104
|
const exact = items.find((item) => item.observationId === selector);
|
|
99
105
|
if (exact) return exact;
|
|
@@ -132,6 +138,7 @@ function normalizeTelegramSource(source) {
|
|
|
132
138
|
return {
|
|
133
139
|
requestId: digestId('tgrequest', [userId, chatId, messageId]),
|
|
134
140
|
occurredAt: timestamp,
|
|
141
|
+
relationshipScope: `relationship:telegram-${userId}:private`,
|
|
135
142
|
source: {
|
|
136
143
|
provider: 'telegram',
|
|
137
144
|
channelId: 'direct',
|
|
@@ -197,8 +204,8 @@ function runCognitiveMemoryCommand({
|
|
|
197
204
|
const lifecycle = openLifecycle(env, lifecycleFactory);
|
|
198
205
|
try {
|
|
199
206
|
const state = lifecycle.read();
|
|
200
|
-
const all = normalizedFocusObservations(state);
|
|
201
|
-
const active = effectiveFocusObservations(state);
|
|
207
|
+
const all = observationsVisibleToSource(normalizedFocusObservations(state), telegram);
|
|
208
|
+
const active = observationsVisibleToSource(effectiveFocusObservations(state), telegram);
|
|
202
209
|
if (command.action === 'focus') return formatFocus(active);
|
|
203
210
|
const occurredAt = String(now());
|
|
204
211
|
if (Number.isNaN(Date.parse(occurredAt))) fail('COGNITIVE_COMMAND_RUNTIME_INVALID');
|
|
@@ -40,6 +40,24 @@ function buildCognitiveWorkFocus(goal) {
|
|
|
40
40
|
const nextAction = bounded(checkpoint?.nextAction);
|
|
41
41
|
const checkpointEvidence = bounded(checkpoint?.expectedEvidence);
|
|
42
42
|
const checkpointEpistemicState = bounded(checkpoint?.epistemicState, 32);
|
|
43
|
+
const problemFrame = checkpoint?.problemFrame && typeof checkpoint.problemFrame === 'object'
|
|
44
|
+
&& !Array.isArray(checkpoint.problemFrame) ? checkpoint.problemFrame : null;
|
|
45
|
+
const frameMissingKnowledge = Array.isArray(problemFrame?.missingKnowledge)
|
|
46
|
+
? problemFrame.missingKnowledge.slice(0, 5).map((item) => bounded(item, 256)).filter(Boolean)
|
|
47
|
+
: [];
|
|
48
|
+
const frameCandidates = Array.isArray(problemFrame?.candidateActions)
|
|
49
|
+
? problemFrame.candidateActions.slice(0, 5).map((item) => bounded(item, 256)).filter(Boolean)
|
|
50
|
+
: [];
|
|
51
|
+
const frameSuccessCriterion = bounded(problemFrame?.successCriterion);
|
|
52
|
+
const frameSelectedAction = bounded(problemFrame?.selectedAction, 256);
|
|
53
|
+
const frameSelectionReason = bounded(problemFrame?.selectionReason);
|
|
54
|
+
const frameSupportChoice = bounded(problemFrame?.supportChoice, 256);
|
|
55
|
+
const frameRisk = bounded(problemFrame?.risk);
|
|
56
|
+
const frameReversibility = bounded(problemFrame?.reversibility);
|
|
57
|
+
const hasProblemFrame = problemFrame !== null && frameSuccessCriterion
|
|
58
|
+
&& frameMissingKnowledge.length > 0 && frameCandidates.length > 0
|
|
59
|
+
&& frameSelectedAction && frameSelectionReason && frameSupportChoice
|
|
60
|
+
&& frameRisk && frameReversibility;
|
|
43
61
|
const hasCheckpoint = checkpoint !== null && checkpointPhase && lastVerified
|
|
44
62
|
&& nextAction && checkpointEvidence;
|
|
45
63
|
const epistemicState = hasCheckpoint && EPISTEMIC_STATES.has(checkpointEpistemicState)
|
|
@@ -52,6 +70,14 @@ function buildCognitiveWorkFocus(goal) {
|
|
|
52
70
|
hasCheckpoint ? nextAction : '',
|
|
53
71
|
hasCheckpoint ? checkpointEvidence : '',
|
|
54
72
|
epistemicState,
|
|
73
|
+
hasProblemFrame ? frameSuccessCriterion : '',
|
|
74
|
+
hasProblemFrame ? frameMissingKnowledge.join('\0') : '',
|
|
75
|
+
hasProblemFrame ? frameCandidates.join('\0') : '',
|
|
76
|
+
hasProblemFrame ? frameSelectedAction : '',
|
|
77
|
+
hasProblemFrame ? frameSelectionReason : '',
|
|
78
|
+
hasProblemFrame ? frameSupportChoice : '',
|
|
79
|
+
hasProblemFrame ? frameRisk : '',
|
|
80
|
+
hasProblemFrame ? frameReversibility : '',
|
|
55
81
|
].join('\0'))
|
|
56
82
|
.digest('hex').slice(0, 40);
|
|
57
83
|
const keyRoot = `goal:${goalId}`;
|
|
@@ -62,7 +88,14 @@ function buildCognitiveWorkFocus(goal) {
|
|
|
62
88
|
{ domain: 'goal', key: `${keyRoot}:objective`, value: objective, confidence: 1, epistemicState, scope: focusScope },
|
|
63
89
|
{
|
|
64
90
|
domain: 'open_thread', key: `${keyRoot}:status`,
|
|
65
|
-
value: hasCheckpoint
|
|
91
|
+
value: bounded(hasCheckpoint
|
|
92
|
+
? [
|
|
93
|
+
`Goal is ${status}. Phase ${checkpointPhase}. Last verified: ${lastVerified}`,
|
|
94
|
+
hasProblemFrame ? `Missing knowledge: ${frameMissingKnowledge.join(' | ')}` : '',
|
|
95
|
+
hasProblemFrame ? `Risk: ${frameRisk}` : '',
|
|
96
|
+
hasProblemFrame ? `Selected action: ${frameSelectedAction}` : '',
|
|
97
|
+
].filter(Boolean).join(' ')
|
|
98
|
+
: `Goal is ${status}.`),
|
|
66
99
|
confidence: 1, epistemicState, scope: focusScope,
|
|
67
100
|
},
|
|
68
101
|
{
|
package/blun.mjs
CHANGED
|
@@ -245751,6 +245751,16 @@ var init_events$1 = __esmMin((() => {
|
|
|
245751
245751
|
lastVerified: string(),
|
|
245752
245752
|
nextAction: string(),
|
|
245753
245753
|
expectedEvidence: string(),
|
|
245754
|
+
problemFrame: object({
|
|
245755
|
+
successCriterion: string(),
|
|
245756
|
+
missingKnowledge: array(string()),
|
|
245757
|
+
candidateActions: array(string()),
|
|
245758
|
+
selectedAction: string(),
|
|
245759
|
+
selectionReason: string(),
|
|
245760
|
+
supportChoice: string(),
|
|
245761
|
+
risk: string(),
|
|
245762
|
+
reversibility: string()
|
|
245763
|
+
}).strict().optional(),
|
|
245754
245764
|
updatedAt: string(),
|
|
245755
245765
|
evidenceReceipt: object({
|
|
245756
245766
|
turnId: number$1().int().min(0),
|
|
@@ -262725,16 +262735,27 @@ var init_outcome_prompts = __esmMin((() => {}));
|
|
|
262725
262735
|
var update_goal_default;
|
|
262726
262736
|
var init_update_goal$1 = __esmMin((() => {
|
|
262727
262737
|
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";
|
|
262738
|
+
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";
|
|
262728
262739
|
}));
|
|
262729
262740
|
//#endregion
|
|
262730
262741
|
//#region ../../packages/agent-core/src/tools/builtin/goal/update-goal.ts
|
|
262731
|
-
var ActionCheckpointInputSchema, UpdateGoalToolInputSchema, UpdateGoalTool;
|
|
262742
|
+
var ProblemFrameInputSchema, ActionCheckpointInputSchema, UpdateGoalToolInputSchema, UpdateGoalTool;
|
|
262732
262743
|
var init_update_goal = __esmMin((() => {
|
|
262733
262744
|
init_zod$1();
|
|
262734
262745
|
init_turn();
|
|
262735
262746
|
init_outcome_prompts();
|
|
262736
262747
|
init_input_schema();
|
|
262737
262748
|
init_update_goal$1();
|
|
262749
|
+
ProblemFrameInputSchema = object({
|
|
262750
|
+
successCriterion: string().min(1).max(512),
|
|
262751
|
+
missingKnowledge: array(string().min(1).max(256)).min(1).max(5),
|
|
262752
|
+
candidateActions: array(string().min(1).max(256)).min(1).max(5),
|
|
262753
|
+
selectedAction: string().min(1).max(256),
|
|
262754
|
+
selectionReason: string().min(1).max(512),
|
|
262755
|
+
supportChoice: string().min(1).max(256),
|
|
262756
|
+
risk: string().min(1).max(512),
|
|
262757
|
+
reversibility: string().min(1).max(512)
|
|
262758
|
+
}).strict();
|
|
262738
262759
|
ActionCheckpointInputSchema = object({
|
|
262739
262760
|
revision: number$1().int().min(1),
|
|
262740
262761
|
phase: _enum(["orient", "plan", "act", "verify", "learn", "wait"]),
|
|
@@ -262742,7 +262763,8 @@ var init_update_goal = __esmMin((() => {
|
|
|
262742
262763
|
epistemicState: _enum(["verified", "credible_unverified", "hypothesis", "uncertain_memory", "stale", "unknown"]),
|
|
262743
262764
|
lastVerified: string().min(1).max(512),
|
|
262744
262765
|
nextAction: string().min(1).max(512),
|
|
262745
|
-
expectedEvidence: string().min(1).max(512)
|
|
262766
|
+
expectedEvidence: string().min(1).max(512),
|
|
262767
|
+
problemFrame: ProblemFrameInputSchema.optional()
|
|
262746
262768
|
}).strict();
|
|
262747
262769
|
UpdateGoalToolInputSchema = object({ status: _enum([
|
|
262748
262770
|
"active",
|