@pentatonic-ai/ai-agent-sdk 0.10.12 → 0.10.13

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/dist/index.cjs CHANGED
@@ -878,7 +878,7 @@ function fireAndForgetEmit(clientConfig, sessionOpts, messages, result, model) {
878
878
  }
879
879
 
880
880
  // src/telemetry.js
881
- var VERSION = "0.10.12";
881
+ var VERSION = "0.10.13";
882
882
  var TELEMETRY_URL = "https://sdk-telemetry.philip-134.workers.dev";
883
883
  function machineId() {
884
884
  const raw = typeof process !== "undefined" ? `${process.env?.USER || process.env?.USERNAME || "u"}:${process.platform || "x"}:${process.arch || "x"}` : "browser";
package/dist/index.js CHANGED
@@ -847,7 +847,7 @@ function fireAndForgetEmit(clientConfig, sessionOpts, messages, result, model) {
847
847
  }
848
848
 
849
849
  // src/telemetry.js
850
- var VERSION = "0.10.12";
850
+ var VERSION = "0.10.13";
851
851
  var TELEMETRY_URL = "https://sdk-telemetry.philip-134.workers.dev";
852
852
  function machineId() {
853
853
  const raw = typeof process !== "undefined" ? `${process.env?.USER || process.env?.USERNAME || "u"}:${process.platform || "x"}:${process.arch || "x"}` : "browser";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pentatonic-ai/ai-agent-sdk",
3
- "version": "0.10.12",
3
+ "version": "0.10.13",
4
4
  "description": "TES SDK — LLM observability and lifecycle tracking via Pentatonic Thing Event System. Track token usage, tool calls, and conversations. Manage things through event-sourced lifecycle stages with AI enrichment and vector search.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -0,0 +1,22 @@
1
+ -- Fusion Drive audit integrity: the merge-audit tables must never lose rows
2
+ -- when the row they reference changes.
3
+ --
4
+ -- 002 (entity_merges) and 006 (fact_merges) declared canonical_id as
5
+ -- REFERENCES entities/facts(id) ON DELETE CASCADE
6
+ -- That destroys audit + rollback history on CHAINED merges. When fact/entity A
7
+ -- is merged into canonical K, a receipt is written with canonical_id = K. If K
8
+ -- is itself later merged away (deleted), the ON DELETE CASCADE deletes A's
9
+ -- receipt too — A stays deleted with no record of why, and no rollback payload.
10
+ -- Observed 2026-06-15: a single arena --apply left 4 facts deleted with no
11
+ -- fact_merges row (their canonical was absorbed into a longer "standing by"
12
+ -- statement, cascading the receipts away).
13
+ --
14
+ -- An append-only audit log must outlive its referents. deprecated_id was always
15
+ -- a plain TEXT column (no FK — the row it names is deleted by definition);
16
+ -- canonical_id should be treated the same. Drop the cascading FK and keep
17
+ -- canonical_id as a plain TEXT column. (We deliberately do NOT re-add a
18
+ -- SET NULL FK: canonical_id must stay populated for forensics even after the
19
+ -- canonical row is gone.)
20
+
21
+ ALTER TABLE entity_merges DROP CONSTRAINT IF EXISTS entity_merges_canonical_id_fkey;
22
+ ALTER TABLE fact_merges DROP CONSTRAINT IF EXISTS fact_merges_canonical_id_fkey;
@@ -386,6 +386,15 @@ def main() -> int:
386
386
  merged += len(loser_ids)
387
387
  return len(loser_ids)
388
388
 
389
+ # Audit invariant baseline: every entity/fact deletion MUST leave a
390
+ # rollback receipt. Capture pre-counts; cross-check after the run.
391
+ def _counts():
392
+ return {t: cur.execute(
393
+ f"SELECT count(*) AS n FROM {t} WHERE arena=%s",
394
+ (args.arena,)).fetchone()["n"]
395
+ for t in ("entities", "facts", "entity_merges", "fact_merges")}
396
+ pre_counts = _counts()
397
+
389
398
  # Tier 1 — deterministic: exact normalized-name dupes only
390
399
  # (case/whitespace variants). Co-occurrence is NOT auto-merged.
391
400
  for group in _entity_dup_sets(cur, args.arena):
@@ -434,10 +443,26 @@ def main() -> int:
434
443
  conn.commit()
435
444
  llm_fact_merges += len(same) - 1
436
445
 
446
+ # Audit invariant: deletions must equal receipts written this run.
447
+ # A mismatch means some rows were deleted with no rollback receipt —
448
+ # e.g. a chained-merge cascade eating audit rows (fixed in migration
449
+ # 007, guarded here so it can never recur silently). Detective, not
450
+ # preventive (merges commit per-group), but it turns a silent leak
451
+ # into a loud, recorded failure. Holds trivially for dry-run (0==0).
452
+ post_counts = _counts()
453
+ ent_deleted = pre_counts["entities"] - post_counts["entities"]
454
+ fact_deleted = pre_counts["facts"] - post_counts["facts"]
455
+ ent_audited = post_counts["entity_merges"] - pre_counts["entity_merges"]
456
+ fact_audited = post_counts["fact_merges"] - pre_counts["fact_merges"]
457
+ audit_ok = (ent_deleted == ent_audited) and (fact_deleted == fact_audited)
458
+
437
459
  run_id = "fdr_" + uuid.uuid4().hex[:20]
438
460
  detail = {"proposals": proposals, "merged": merged,
439
461
  "llm_entity_merges": llm_entity_merges, "llm_fact_merges": llm_fact_merges,
440
- "llm_tier": bool(post_fn)}
462
+ "llm_tier": bool(post_fn),
463
+ "audit": {"ok": audit_ok,
464
+ "entities_deleted": ent_deleted, "entities_audited": ent_audited,
465
+ "facts_deleted": fact_deleted, "facts_audited": fact_audited}}
441
466
  cur.execute(
442
467
  """INSERT INTO fusion_drive_runs (id, arena, pass_kind, mode, scanned, changed, detail, finished_at)
443
468
  VALUES (%s,%s,'fusion',%s,%s,%s,%s::jsonb,NOW())""",
@@ -450,6 +475,14 @@ def main() -> int:
450
475
  f"{merged} entities merged ({llm_entity_merges} via llm), {llm_fact_merges} facts merged via llm. "
451
476
  f"LLM tier: {'on (distiller)' if post_fn else 'off'}")
452
477
  print(f" ledger: {run_id}")
478
+ if not audit_ok:
479
+ print(f"[fusion-drive:fuse] AUDIT INVARIANT VIOLATED arena={args.arena}: "
480
+ f"entities deleted={ent_deleted} audited={ent_audited}; "
481
+ f"facts deleted={fact_deleted} audited={fact_audited}. "
482
+ f"Deletions without a rollback receipt — do NOT trust audit-based "
483
+ f"rollback for this run; restore from backup if needed.",
484
+ file=sys.stderr)
485
+ return 3
453
486
  return 0
454
487
 
455
488