blun-king-cli 9.1.361 → 9.1.363

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.
@@ -14,13 +14,21 @@ function compareVariants(left, right) {
14
14
 
15
15
  function resolveCognitiveEvidenceGroup(entries) {
16
16
  if (!Array.isArray(entries) || entries.length === 0) return null;
17
- const ordered = [...entries].sort((left, right) => left.occurredAt - right.occurredAt
17
+ const withdrawals = entries.filter((item) => Boolean(item.withdraws));
18
+ const deletionCutoff = withdrawals.length > 0
19
+ ? Math.max(...withdrawals.map((item) => item.occurredAt)) : Number.NEGATIVE_INFINITY;
20
+ const evidence = entries.filter((item) => !item.withdraws && item.occurredAt > deletionCutoff);
21
+ const superseded = new Set(evidence.map((item) => item.supersedes).filter(Boolean));
22
+ const active = evidence.filter((item) => !superseded.has(item.observationId));
23
+ if (active.length === 0) return null;
24
+ const ordered = [...active].sort((left, right) => left.occurredAt - right.occurredAt
18
25
  || left.index - right.index);
19
26
  const latest = ordered.at(-1);
27
+ const corrected = ordered.some((item) => Boolean(item.supersedes));
20
28
  const distinctValues = new Set(ordered.map((item) => item.value));
21
- if (distinctValues.size === 1) return { ...latest, revised: false, contested: false, conflict: false };
29
+ if (distinctValues.size === 1) return { ...latest, revised: false, corrected, contested: false, conflict: false };
22
30
  if (CANONICAL_LATEST_DOMAINS.has(latest.domain)) {
23
- return { ...latest, revised: true, contested: false, conflict: false };
31
+ return { ...latest, revised: true, corrected, contested: false, conflict: false };
24
32
  }
25
33
 
26
34
  const variants = new Map();
@@ -50,6 +58,7 @@ function resolveCognitiveEvidenceGroup(entries) {
50
58
  confidence: strongest.maxConfidence,
51
59
  occurredAt: strongest.latestOccurredAt,
52
60
  revised: false,
61
+ corrected,
53
62
  contested: true,
54
63
  conflict: false,
55
64
  };
@@ -59,6 +68,7 @@ function resolveCognitiveEvidenceGroup(entries) {
59
68
  confidence: strongest.maxConfidence,
60
69
  occurredAt: Math.max(...ranked.map((item) => item.latestOccurredAt)),
61
70
  revised: false,
71
+ corrected,
62
72
  contested: false,
63
73
  conflict: true,
64
74
  };
@@ -46,6 +46,11 @@ function buildCognitiveFocusProjection(state, { focusScopes, maxItems = 6, maxCh
46
46
  const key = clean(item?.key, 128);
47
47
  const value = clean(item?.value, 512);
48
48
  const scope = clean(item?.scope, 128);
49
+ const observationId = clean(item?.observation_id, 128);
50
+ const supersedes = item?.supersedes === null || item?.supersedes === undefined
51
+ ? null : clean(item.supersedes, 128);
52
+ const withdraws = item?.withdraws === null || item?.withdraws === undefined
53
+ ? null : clean(item.withdraws, 128);
49
54
  const confidence = Number(item?.confidence);
50
55
  const occurredAt = Date.parse(String(item?.occurred_at ?? ''));
51
56
  if (!FOCUS_DOMAINS.has(domain) || !key || !value || !scope || scope === 'runtime'
@@ -53,7 +58,7 @@ function buildCognitiveFocusProjection(state, { focusScopes, maxItems = 6, maxCh
53
58
  || !Number.isFinite(occurredAt)) return;
54
59
  const groupKey = `${scope}\0${domain}\0${key}`;
55
60
  const existing = groups.get(groupKey) ?? [];
56
- existing.push({ domain, key, value, scope, confidence, occurredAt, index });
61
+ existing.push({ domain, key, value, scope, observationId, supersedes, withdraws, confidence, occurredAt, index });
57
62
  groups.set(groupKey, existing);
58
63
  });
59
64
 
@@ -76,7 +81,8 @@ function buildCognitiveFocusProjection(state, { focusScopes, maxItems = 6, maxCh
76
81
  const selected = ranked.slice(0, maxItems);
77
82
  const lines = selected.map((item) => {
78
83
  if (item.conflict) return `- Conflict: ${item.key} has incompatible evidence; verify before relying on it.`;
79
- const marker = item.contested ? ' [contested; stronger evidence]' : item.revised ? ' [revised]' : '';
84
+ const marker = item.corrected ? ' [corrected]'
85
+ : item.contested ? ' [contested; stronger evidence]' : item.revised ? ' [revised]' : '';
80
86
  return `- ${LABELS.get(item.domain)}: ${item.value}${marker}`;
81
87
  });
82
88
  while ([`Current durable focus (${lines.length} items):`, ...lines, SAFETY_LINE].join('\n').length > maxChars
@@ -52,7 +52,7 @@ function normalizeSource(source) {
52
52
  }
53
53
 
54
54
  function normalizeObservation(value) {
55
- const allowed = new Set(['observation_id', 'domain', 'key', 'value', 'confidence', 'scope']);
55
+ const allowed = new Set(['observation_id', 'domain', 'key', 'value', 'confidence', 'scope', 'supersedes', 'withdraws']);
56
56
  if (!exactKeys(value, allowed) || hasForbiddenKey(value)) fail('COGNITIVE_FORBIDDEN_FIELD');
57
57
  const observation = {
58
58
  observation_id: safeId(value.observation_id),
@@ -68,6 +68,17 @@ function normalizeObservation(value) {
68
68
  fail('COGNITIVE_INVALID_EVENT');
69
69
  }
70
70
  if (FORBIDDEN_KEY_RE.test(observation.key)) fail('COGNITIVE_FORBIDDEN_FIELD');
71
+ if (value.supersedes !== undefined && value.supersedes !== null) {
72
+ observation.supersedes = safeId(value.supersedes);
73
+ if (!observation.supersedes || observation.confidence !== 1) fail('COGNITIVE_INVALID_CORRECTION');
74
+ }
75
+ if (value.withdraws !== undefined && value.withdraws !== null) {
76
+ observation.withdraws = safeId(value.withdraws);
77
+ if (!observation.withdraws || observation.confidence !== 1 || observation.value !== 'withdrawn') {
78
+ fail('COGNITIVE_INVALID_WITHDRAWAL');
79
+ }
80
+ }
81
+ if (observation.supersedes && observation.withdraws) fail('COGNITIVE_INVALID_EVENT');
71
82
  return observation;
72
83
  }
73
84
 
@@ -143,7 +154,9 @@ function initialize(db) {
143
154
  confidence REAL NOT NULL,
144
155
  scope TEXT NOT NULL,
145
156
  source_json TEXT NOT NULL,
146
- occurred_at TEXT NOT NULL
157
+ occurred_at TEXT NOT NULL,
158
+ supersedes_observation_id TEXT,
159
+ withdraws_observation_id TEXT
147
160
  );
148
161
  CREATE INDEX IF NOT EXISTS cognitive_observations_stream
149
162
  ON cognitive_observations (tenant_id, agent_id, occurred_at, observation_id);
@@ -167,6 +180,13 @@ function initialize(db) {
167
180
  PRIMARY KEY (tenant_id, receipt_id)
168
181
  );
169
182
  `);
183
+ const observationColumns = db.prepare('PRAGMA table_info(cognitive_observations)').all();
184
+ if (!observationColumns.some((column) => column.name === 'supersedes_observation_id')) {
185
+ db.exec('ALTER TABLE cognitive_observations ADD COLUMN supersedes_observation_id TEXT');
186
+ }
187
+ if (!observationColumns.some((column) => column.name === 'withdraws_observation_id')) {
188
+ db.exec('ALTER TABLE cognitive_observations ADD COLUMN withdraws_observation_id TEXT');
189
+ }
170
190
  }
171
191
 
172
192
  function openCognitiveStateStore({ home } = {}) {
@@ -198,12 +218,27 @@ function openCognitiveStateStore({ home } = {}) {
198
218
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
199
219
  .run(normalized.event_id, normalized.tenant_id, normalized.agent_id, actualVersion, newVersion, normalized.occurred_at, payload, previousHash, eventHash);
200
220
  const insertObservation = db.prepare(`INSERT INTO cognitive_observations
201
- (observation_id, event_id, tenant_id, agent_id, domain, fact_key, value_text, confidence, scope, source_json, occurred_at)
202
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
221
+ (observation_id, event_id, tenant_id, agent_id, domain, fact_key, value_text, confidence, scope, source_json, occurred_at, supersedes_observation_id, withdraws_observation_id)
222
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
203
223
  const sourceJson = JSON.stringify(normalized.source);
204
224
  for (const observation of normalized.observations) {
225
+ if (observation.supersedes) {
226
+ const target = db.prepare(`SELECT tenant_id, agent_id, domain, fact_key, scope
227
+ FROM cognitive_observations WHERE observation_id = ?`).get(observation.supersedes);
228
+ if (!target || target.tenant_id !== normalized.tenant_id || target.agent_id !== normalized.agent_id
229
+ || target.domain !== observation.domain || target.fact_key !== observation.key
230
+ || target.scope !== observation.scope) fail('COGNITIVE_INVALID_CORRECTION');
231
+ }
232
+ if (observation.withdraws) {
233
+ const target = db.prepare(`SELECT tenant_id, agent_id, domain, fact_key, scope
234
+ FROM cognitive_observations WHERE observation_id = ?`).get(observation.withdraws);
235
+ if (!target || target.tenant_id !== normalized.tenant_id || target.agent_id !== normalized.agent_id
236
+ || target.domain !== observation.domain || target.fact_key !== observation.key
237
+ || target.scope !== observation.scope) fail('COGNITIVE_INVALID_WITHDRAWAL');
238
+ }
205
239
  insertObservation.run(observation.observation_id, normalized.event_id, normalized.tenant_id, normalized.agent_id,
206
- observation.domain, observation.key, observation.value, observation.confidence, observation.scope, sourceJson, normalized.occurred_at);
240
+ observation.domain, observation.key, observation.value, observation.confidence, observation.scope, sourceJson,
241
+ normalized.occurred_at, observation.supersedes ?? null, observation.withdraws ?? null);
207
242
  }
208
243
  db.prepare(`INSERT INTO cognitive_streams (tenant_id, agent_id, version, updated_at) VALUES (?, ?, ?, ?)
209
244
  ON CONFLICT(tenant_id, agent_id) DO UPDATE SET version = excluded.version, updated_at = excluded.updated_at`)
@@ -221,7 +256,8 @@ function openCognitiveStateStore({ home } = {}) {
221
256
  const agent = safeId(agentId);
222
257
  if (!tenant || !agent) fail('COGNITIVE_INVALID_EVENT');
223
258
  const stream = db.prepare('SELECT version, updated_at FROM cognitive_streams WHERE tenant_id = ? AND agent_id = ?').get(tenant, agent);
224
- const rows = db.prepare(`SELECT domain, fact_key, value_text, confidence, scope, source_json, occurred_at, observation_id
259
+ const rows = db.prepare(`SELECT domain, fact_key, value_text, confidence, scope, source_json, occurred_at, observation_id,
260
+ supersedes_observation_id, withdraws_observation_id
225
261
  FROM cognitive_observations WHERE tenant_id = ? AND agent_id = ? ORDER BY occurred_at, rowid`).all(tenant, agent);
226
262
  return {
227
263
  version: Number(stream?.version ?? 0),
@@ -235,6 +271,8 @@ function openCognitiveStateStore({ home } = {}) {
235
271
  scope: row.scope,
236
272
  source: JSON.parse(row.source_json),
237
273
  occurred_at: row.occurred_at,
274
+ supersedes: row.supersedes_observation_id ?? null,
275
+ withdraws: row.withdraws_observation_id ?? null,
238
276
  })),
239
277
  };
240
278
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.361",
3
+ "version": "9.1.363",
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": {