blun-king-cli 9.1.360 → 9.1.362

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.
@@ -0,0 +1,73 @@
1
+ 'use strict';
2
+
3
+ const CANONICAL_LATEST_DOMAINS = new Set([
4
+ 'goal', 'open_thread', 'next_trigger', 'expected_evidence',
5
+ ]);
6
+ const CONFIDENCE_MARGIN = 0.2;
7
+
8
+ function compareVariants(left, right) {
9
+ return right.maxConfidence - left.maxConfidence
10
+ || right.confirmations - left.confirmations
11
+ || right.latestOccurredAt - left.latestOccurredAt
12
+ || left.value.localeCompare(right.value);
13
+ }
14
+
15
+ function resolveCognitiveEvidenceGroup(entries) {
16
+ if (!Array.isArray(entries) || entries.length === 0) return null;
17
+ const superseded = new Set(entries.map((item) => item.supersedes).filter(Boolean));
18
+ const active = entries.filter((item) => !superseded.has(item.observationId));
19
+ if (active.length === 0) return null;
20
+ const ordered = [...active].sort((left, right) => left.occurredAt - right.occurredAt
21
+ || left.index - right.index);
22
+ const latest = ordered.at(-1);
23
+ const corrected = ordered.some((item) => Boolean(item.supersedes));
24
+ const distinctValues = new Set(ordered.map((item) => item.value));
25
+ if (distinctValues.size === 1) return { ...latest, revised: false, corrected, contested: false, conflict: false };
26
+ if (CANONICAL_LATEST_DOMAINS.has(latest.domain)) {
27
+ return { ...latest, revised: true, corrected, contested: false, conflict: false };
28
+ }
29
+
30
+ const variants = new Map();
31
+ for (const item of ordered) {
32
+ const variant = variants.get(item.value) ?? {
33
+ value: item.value,
34
+ maxConfidence: item.confidence,
35
+ confirmations: 0,
36
+ latestOccurredAt: item.occurredAt,
37
+ representative: item,
38
+ };
39
+ variant.confirmations += 1;
40
+ variant.latestOccurredAt = Math.max(variant.latestOccurredAt, item.occurredAt);
41
+ if (item.confidence > variant.maxConfidence
42
+ || item.confidence === variant.maxConfidence && item.occurredAt >= variant.representative.occurredAt) {
43
+ variant.maxConfidence = item.confidence;
44
+ variant.representative = item;
45
+ }
46
+ variants.set(item.value, variant);
47
+ }
48
+ const ranked = [...variants.values()].sort(compareVariants);
49
+ const strongest = ranked[0];
50
+ const runnerUp = ranked[1];
51
+ if (strongest.maxConfidence - runnerUp.maxConfidence >= CONFIDENCE_MARGIN - Number.EPSILON) {
52
+ return {
53
+ ...strongest.representative,
54
+ confidence: strongest.maxConfidence,
55
+ occurredAt: strongest.latestOccurredAt,
56
+ revised: false,
57
+ corrected,
58
+ contested: true,
59
+ conflict: false,
60
+ };
61
+ }
62
+ return {
63
+ ...latest,
64
+ confidence: strongest.maxConfidence,
65
+ occurredAt: Math.max(...ranked.map((item) => item.latestOccurredAt)),
66
+ revised: false,
67
+ corrected,
68
+ contested: false,
69
+ conflict: true,
70
+ };
71
+ }
72
+
73
+ module.exports = { resolveCognitiveEvidenceGroup };
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ const { resolveCognitiveEvidenceGroup } = require('./cognitive-effective-view.cjs');
4
+
3
5
  const FOCUS_DOMAINS = new Set(['self', 'team', 'goal', 'open_thread', 'next_trigger', 'expected_evidence']);
4
6
  const DOMAIN_WEIGHTS = new Map([
5
7
  ['goal', 60],
@@ -44,6 +46,9 @@ function buildCognitiveFocusProjection(state, { focusScopes, maxItems = 6, maxCh
44
46
  const key = clean(item?.key, 128);
45
47
  const value = clean(item?.value, 512);
46
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);
47
52
  const confidence = Number(item?.confidence);
48
53
  const occurredAt = Date.parse(String(item?.occurred_at ?? ''));
49
54
  if (!FOCUS_DOMAINS.has(domain) || !key || !value || !scope || scope === 'runtime'
@@ -51,7 +56,7 @@ function buildCognitiveFocusProjection(state, { focusScopes, maxItems = 6, maxCh
51
56
  || !Number.isFinite(occurredAt)) return;
52
57
  const groupKey = `${scope}\0${domain}\0${key}`;
53
58
  const existing = groups.get(groupKey) ?? [];
54
- existing.push({ domain, key, value, scope, confidence, occurredAt, index });
59
+ existing.push({ domain, key, value, scope, observationId, supersedes, confidence, occurredAt, index });
55
60
  groups.set(groupKey, existing);
56
61
  });
57
62
 
@@ -60,11 +65,11 @@ function buildCognitiveFocusProjection(state, { focusScopes, maxItems = 6, maxCh
60
65
  entries.sort((left, right) => left.occurredAt - right.occurredAt || left.index - right.index);
61
66
  const latest = entries.at(-1);
62
67
  if (!scopes.includes(latest.scope)) continue;
63
- const revised = entries.some((item) => item.value !== latest.value);
68
+ const effective = resolveCognitiveEvidenceGroup(entries);
69
+ if (!effective) continue;
64
70
  ranked.push({
65
- ...latest,
66
- revised,
67
- score: DOMAIN_WEIGHTS.get(latest.domain) + latest.confidence * 10,
71
+ ...effective,
72
+ score: DOMAIN_WEIGHTS.get(effective.domain) + effective.confidence * 10,
68
73
  });
69
74
  }
70
75
  ranked.sort((left, right) => right.score - left.score
@@ -72,7 +77,12 @@ function buildCognitiveFocusProjection(state, { focusScopes, maxItems = 6, maxCh
72
77
  if (ranked.length === 0) return null;
73
78
 
74
79
  const selected = ranked.slice(0, maxItems);
75
- const lines = selected.map((item) => `- ${LABELS.get(item.domain)}: ${item.value}${item.revised ? ' [revised]' : ''}`);
80
+ const lines = selected.map((item) => {
81
+ if (item.conflict) return `- Conflict: ${item.key} has incompatible evidence; verify before relying on it.`;
82
+ const marker = item.corrected ? ' [corrected]'
83
+ : item.contested ? ' [contested; stronger evidence]' : item.revised ? ' [revised]' : '';
84
+ return `- ${LABELS.get(item.domain)}: ${item.value}${marker}`;
85
+ });
76
86
  while ([`Current durable focus (${lines.length} items):`, ...lines, SAFETY_LINE].join('\n').length > maxChars
77
87
  && lines.length > 0) lines.pop();
78
88
  if (lines.length === 0) return null;
@@ -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']);
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,10 @@ 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
+ }
71
75
  return observation;
72
76
  }
73
77
 
@@ -143,7 +147,8 @@ function initialize(db) {
143
147
  confidence REAL NOT NULL,
144
148
  scope TEXT NOT NULL,
145
149
  source_json TEXT NOT NULL,
146
- occurred_at TEXT NOT NULL
150
+ occurred_at TEXT NOT NULL,
151
+ supersedes_observation_id TEXT
147
152
  );
148
153
  CREATE INDEX IF NOT EXISTS cognitive_observations_stream
149
154
  ON cognitive_observations (tenant_id, agent_id, occurred_at, observation_id);
@@ -167,6 +172,10 @@ function initialize(db) {
167
172
  PRIMARY KEY (tenant_id, receipt_id)
168
173
  );
169
174
  `);
175
+ const observationColumns = db.prepare('PRAGMA table_info(cognitive_observations)').all();
176
+ if (!observationColumns.some((column) => column.name === 'supersedes_observation_id')) {
177
+ db.exec('ALTER TABLE cognitive_observations ADD COLUMN supersedes_observation_id TEXT');
178
+ }
170
179
  }
171
180
 
172
181
  function openCognitiveStateStore({ home } = {}) {
@@ -198,12 +207,20 @@ function openCognitiveStateStore({ home } = {}) {
198
207
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
199
208
  .run(normalized.event_id, normalized.tenant_id, normalized.agent_id, actualVersion, newVersion, normalized.occurred_at, payload, previousHash, eventHash);
200
209
  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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
210
+ (observation_id, event_id, tenant_id, agent_id, domain, fact_key, value_text, confidence, scope, source_json, occurred_at, supersedes_observation_id)
211
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
203
212
  const sourceJson = JSON.stringify(normalized.source);
204
213
  for (const observation of normalized.observations) {
214
+ if (observation.supersedes) {
215
+ const target = db.prepare(`SELECT tenant_id, agent_id, domain, fact_key, scope
216
+ FROM cognitive_observations WHERE observation_id = ?`).get(observation.supersedes);
217
+ if (!target || target.tenant_id !== normalized.tenant_id || target.agent_id !== normalized.agent_id
218
+ || target.domain !== observation.domain || target.fact_key !== observation.key
219
+ || target.scope !== observation.scope) fail('COGNITIVE_INVALID_CORRECTION');
220
+ }
205
221
  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);
222
+ observation.domain, observation.key, observation.value, observation.confidence, observation.scope, sourceJson,
223
+ normalized.occurred_at, observation.supersedes ?? null);
207
224
  }
208
225
  db.prepare(`INSERT INTO cognitive_streams (tenant_id, agent_id, version, updated_at) VALUES (?, ?, ?, ?)
209
226
  ON CONFLICT(tenant_id, agent_id) DO UPDATE SET version = excluded.version, updated_at = excluded.updated_at`)
@@ -221,7 +238,8 @@ function openCognitiveStateStore({ home } = {}) {
221
238
  const agent = safeId(agentId);
222
239
  if (!tenant || !agent) fail('COGNITIVE_INVALID_EVENT');
223
240
  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
241
+ const rows = db.prepare(`SELECT domain, fact_key, value_text, confidence, scope, source_json, occurred_at, observation_id,
242
+ supersedes_observation_id
225
243
  FROM cognitive_observations WHERE tenant_id = ? AND agent_id = ? ORDER BY occurred_at, rowid`).all(tenant, agent);
226
244
  return {
227
245
  version: Number(stream?.version ?? 0),
@@ -235,6 +253,7 @@ function openCognitiveStateStore({ home } = {}) {
235
253
  scope: row.scope,
236
254
  source: JSON.parse(row.source_json),
237
255
  occurred_at: row.occurred_at,
256
+ supersedes: row.supersedes_observation_id ?? null,
238
257
  })),
239
258
  };
240
259
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.360",
3
+ "version": "9.1.362",
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": {