@wrongstack/core 0.309.0 → 0.310.0

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.
Files changed (129) hide show
  1. package/dist/chronicle/index.js +113 -41
  2. package/dist/chronicle/metrics-ingest.d.ts +7 -0
  3. package/dist/chronicle/metrics-schema.d.ts +4 -1
  4. package/dist/chronicle/project-server.js +94 -38
  5. package/dist/chronicle/query.d.ts +1 -0
  6. package/dist/chronicle/sqlite-journal-schema.d.ts +2 -1
  7. package/dist/chronicle/types.d.ts +2 -0
  8. package/dist/{agent-status-helpers.d.ts → coordination/agent-status-helpers.d.ts} +1 -1
  9. package/dist/{agent-status-tracker.d.ts → coordination/agent-status-tracker.d.ts} +2 -2
  10. package/dist/{middleware → coordination}/collab-pause.d.ts +1 -1
  11. package/dist/coordination/director-kanban-queue-helpers.d.ts +1 -1
  12. package/dist/coordination/director.d.ts +7 -0
  13. package/dist/coordination/explore-companion.d.ts +9 -6
  14. package/dist/coordination/fleet-status-tool.d.ts +1 -1
  15. package/dist/coordination/index.d.ts +5 -1
  16. package/dist/coordination/index.js +2392 -405
  17. package/dist/coordination/kanban-dispatch-port.d.ts +30 -0
  18. package/dist/coordination/kanban-ops-port.d.ts +21 -0
  19. package/dist/coordination/mailbox-hooks.d.ts +1 -1
  20. package/dist/coordination/mailbox-project-server.js +14 -9
  21. package/dist/coordination/mutation-engine.d.ts +5 -3
  22. package/dist/core/context.d.ts +35 -44
  23. package/dist/core/conversation-state.d.ts +16 -52
  24. package/dist/core/index.js +92 -25
  25. package/dist/core/provider-runner.d.ts +2 -2
  26. package/dist/core/run-env.d.ts +7 -28
  27. package/dist/core/streaming-response-builder.d.ts +2 -2
  28. package/dist/execution/index.js +138 -162
  29. package/dist/goal/index.js +100 -22
  30. package/dist/hq/auth-store.d.ts +9 -0
  31. package/dist/hq/cost-bridge.d.ts +1 -1
  32. package/dist/hq/index.js +69 -7
  33. package/dist/index.d.ts +12 -5
  34. package/dist/index.js +21185 -26807
  35. package/dist/infrastructure/index.js +232 -135
  36. package/dist/infrastructure/provider-cache-ledger.d.ts +1 -1
  37. package/dist/infrastructure/token-counter.d.ts +5 -1
  38. package/dist/kernel/events/file-events.d.ts +6 -0
  39. package/dist/kernel/events/provider-events.d.ts +10 -7
  40. package/dist/kernel/events/session-events.d.ts +4 -4
  41. package/dist/kernel/events/tool-events.d.ts +12 -2
  42. package/dist/observability/index.js +1 -1
  43. package/dist/plugin/index.js +218 -47
  44. package/dist/prompts/index.js +360 -3
  45. package/dist/security/auto-approve-policy.d.ts +2 -2
  46. package/dist/security/index.d.ts +1 -0
  47. package/dist/security/index.js +224 -68
  48. package/dist/security/kanban-boundary.d.ts +1 -1
  49. package/dist/security/kanban-governance-port.d.ts +28 -0
  50. package/dist/security/permission-helpers.d.ts +11 -0
  51. package/dist/security/permission-policy.d.ts +10 -1
  52. package/dist/security/yolo-risk.d.ts +17 -0
  53. package/dist/session-catalog/index.js +34 -5
  54. package/dist/session-catalog/project-server.js +34 -5
  55. package/dist/session-catalog/protocol.d.ts +1 -1
  56. package/dist/session-catalog/registry.d.ts +1 -1
  57. package/dist/session-catalog/store-schema.d.ts +1 -1
  58. package/dist/session-catalog/store.d.ts +1 -1
  59. package/dist/skills/index.js +39 -6
  60. package/dist/storage/annotations-store.d.ts +1 -1
  61. package/dist/storage/board-store-port.d.ts +45 -0
  62. package/dist/storage/completed-work-checkpoint.d.ts +1 -1
  63. package/dist/storage/config-loader/types.d.ts +1 -1
  64. package/dist/storage/event-bus-port.d.ts +27 -0
  65. package/dist/storage/file-session-writer.d.ts +47 -5
  66. package/dist/storage/goal-coordination.d.ts +1 -1
  67. package/dist/storage/goal-store.d.ts +1 -1
  68. package/dist/storage/index.d.ts +3 -4
  69. package/dist/storage/index.js +1107 -1462
  70. package/dist/storage/plan-store.d.ts +1 -1
  71. package/dist/storage/queue-store.d.ts +1 -1
  72. package/dist/storage/replay-log-store.d.ts +1 -1
  73. package/dist/storage/session-recovery.d.ts +10 -0
  74. package/dist/storage/session-resume-validation.d.ts +13 -1
  75. package/dist/storage/session-store/events.d.ts +1 -1
  76. package/dist/storage/session-store/load-session-data.d.ts +1 -1
  77. package/dist/storage/session-store/rename-session.d.ts +1 -1
  78. package/dist/storage/session-store/resume-session.d.ts +3 -1
  79. package/dist/storage/session-store/session-store-index.d.ts +2 -1
  80. package/dist/storage/session-store/types.d.ts +1 -1
  81. package/dist/storage/session-store.d.ts +70 -0
  82. package/dist/storage/session-summary-tracker.d.ts +8 -0
  83. package/dist/storage/session-write-buffer.d.ts +31 -2
  84. package/dist/storage/task-store.d.ts +1 -1
  85. package/dist/storage/todos-checkpoint.d.ts +1 -1
  86. package/dist/storage/tool-audit-log.d.ts +1 -1
  87. package/dist/tasking/index.js +100 -22
  88. package/dist/tasking/task-tracker.d.ts +24 -1
  89. package/dist/types/compactor.d.ts +2 -2
  90. package/dist/types/context.d.ts +212 -0
  91. package/dist/types/conversation-state.d.ts +109 -0
  92. package/dist/types/error-handler.d.ts +2 -2
  93. package/dist/types/file-event-record.d.ts +6 -0
  94. package/dist/types/index.d.ts +3 -3
  95. package/dist/types/index.js +17 -1
  96. package/dist/types/permission.d.ts +3 -3
  97. package/dist/types/plugin.d.ts +3 -3
  98. package/dist/types/provider-runner.d.ts +2 -2
  99. package/dist/types/provider.d.ts +10 -0
  100. package/dist/types/run-env.d.ts +32 -0
  101. package/dist/types/session.d.ts +3 -0
  102. package/dist/types/slash-command.d.ts +2 -2
  103. package/dist/types/token-counter.d.ts +30 -1
  104. package/dist/types/tool-executor.d.ts +2 -2
  105. package/dist/types/tool.d.ts +20 -5
  106. package/dist/utils/context-breakdown.d.ts +2 -2
  107. package/dist/utils/context-evidence.d.ts +12 -12
  108. package/dist/utils/crash-shield.d.ts +9 -0
  109. package/dist/utils/heap-watchdog.js +11 -3
  110. package/dist/utils/index.d.ts +2 -1
  111. package/dist/utils/index.js +126 -160
  112. package/dist/utils/regex-guard.d.ts +7 -30
  113. package/dist/utils/terminal-sanitize.d.ts +41 -0
  114. package/dist/utils/todos-format.d.ts +1 -1
  115. package/dist/utils/tool-subject.d.ts +1 -1
  116. package/dist/utils/tree-kill.d.ts +2 -0
  117. package/dist/utils/tree-kill.js +1 -0
  118. package/instructions/agents/chaos-monkey.md +5 -1
  119. package/instructions/coordination/subagent-baseline.md +10 -0
  120. package/instructions/system-lite.md +2 -0
  121. package/instructions/system-pro.md +40 -0
  122. package/instructions/system.md +15 -0
  123. package/package.json +7 -10
  124. package/dist/defaults/index.d.ts +0 -69
  125. package/dist/defaults/index.js +0 -37755
  126. /package/dist/{fleet-notifier.d.ts → coordination/fleet-notifier.d.ts} +0 -0
  127. /package/dist/{session-registry-atomic-file.d.ts → session-catalog/session-registry-atomic-file.d.ts} +0 -0
  128. /package/dist/{session-registry-types.d.ts → session-catalog/session-registry-types.d.ts} +0 -0
  129. /package/dist/{session-registry.d.ts → session-catalog/session-registry.d.ts} +0 -0
@@ -140,7 +140,10 @@ var withFileLock = primitives.withFileLock;
140
140
  import * as fs from "node:fs";
141
141
  import * as fsp2 from "node:fs/promises";
142
142
  import * as path3 from "node:path";
143
- import { PerformanceObserver, constants as performanceConstants } from "node:perf_hooks";
143
+ import {
144
+ PerformanceObserver,
145
+ constants as performanceConstants
146
+ } from "node:perf_hooks";
144
147
  import * as v8 from "node:v8";
145
148
 
146
149
  // src/utils/memory-flight-recorder.ts
@@ -446,7 +449,8 @@ function createMemoryFlightRecorder(options = {}) {
446
449
  const now = options.now ?? Date.now;
447
450
  const startedAt2 = now();
448
451
  const root = options.diagnosticsRoot ?? path2.join(wstackGlobalRoot(), "diagnostics", "memory");
449
- const enabled = options.enabled ?? (process.env["WRONGSTACK_MEMORY_FLIGHT_RECORDER"] !== "0" && process.env["NODE_ENV"] !== "test");
452
+ const isBunRuntime = typeof globalThis.Bun !== "undefined";
453
+ const enabled = options.enabled ?? (!isBunRuntime && process.env["WRONGSTACK_MEMORY_FLIGHT_RECORDER"] !== "0" && process.env["NODE_ENV"] !== "test");
450
454
  const writer = options.captureWriter ?? (enabled ? new ContinuousMemoryCaptureWriter(root) : disabledWriter(path2.join(root, `${timestampSlug()}-pid-${process.pid}`)));
451
455
  const observations = [];
452
456
  const windowMs = options.windowMs ?? DEFAULT_WINDOW_MS;
@@ -556,7 +560,11 @@ function defaultHeapLogPath() {
556
560
  function takeHeapSample() {
557
561
  const m = process.memoryUsage();
558
562
  const heap = v8.getHeapStatistics();
559
- const spaces = v8.getHeapSpaceStatistics();
563
+ let spaces = [];
564
+ try {
565
+ spaces = v8.getHeapSpaceStatistics();
566
+ } catch {
567
+ }
560
568
  const spaceUsed = (name) => spaces.find((space) => space.space_name === name)?.space_used_size ?? 0;
561
569
  const limit = heap.heap_size_limit || 0;
562
570
  let activeResources = 0;
@@ -2706,7 +2714,11 @@ function relationKeys(event) {
2706
2714
  add("attempt", event.correlation.attemptId, "explicit");
2707
2715
  add("decision", event.attributes?.decisionId, "explicit");
2708
2716
  add("network_request", event.attributes?.requestId, "explicit");
2709
- add("prompt_manifest", event.attributes?.promptManifest?.manifestId, "explicit");
2717
+ add(
2718
+ "prompt_manifest",
2719
+ event.correlation.promptManifestId ?? event.attributes?.promptManifest?.manifestId,
2720
+ "explicit"
2721
+ );
2710
2722
  add("resource_lineage", event.resource?.id, "inferred");
2711
2723
  if (event.eventType === "metrics.rollup" && event.attributes?.signal === "tool.resource.observed") {
2712
2724
  const resources = event.attributes.resources;
@@ -2728,6 +2740,7 @@ function matches(event, query) {
2728
2740
  if (!equal(query.agentId, event.scope.agentId) || !equal(query.taskId, event.scope.taskId)) return false;
2729
2741
  if (!equal(query.providerId, event.runtime?.providerId) || !equal(query.modelId, event.runtime?.modelId)) return false;
2730
2742
  if (!equal(query.traceId, event.correlation.traceId) || !equal(query.logicalRequestId, event.correlation.logicalRequestId)) return false;
2743
+ if (!equal(query.promptManifestId, event.correlation.promptManifestId)) return false;
2731
2744
  if (!equal(query.attemptId, event.correlation.attemptId) || !equal(query.toolCallId, event.correlation.toolCallId)) return false;
2732
2745
  if (!equal(query.resourceKind, event.resource?.kind) || !equal(query.resourceId, event.resource?.id)) return false;
2733
2746
  if (query.path && normalize2(event.resource?.path) !== normalize2(query.path)) return false;
@@ -2868,6 +2881,7 @@ function isChronicleEvent(value) {
2868
2881
  ]) && typeof value.correlation.traceId === "string" && typeof value.correlation.spanId === "string" && optionalStrings(value.correlation, [
2869
2882
  "parentSpanId",
2870
2883
  "logicalRequestId",
2884
+ "promptManifestId",
2871
2885
  "attemptId",
2872
2886
  "toolCallId"
2873
2887
  ]) && isRuntime(value.runtime) && isResource(value.resource) && (value.attributes === void 0 || isRecord(value.attributes)) && (value.tags === void 0 || isStringRecord(value.tags));
@@ -3057,7 +3071,7 @@ var ChronicleQuotaManager = class {
3057
3071
  };
3058
3072
 
3059
3073
  // src/chronicle/sqlite-journal-schema.ts
3060
- import { createRequire } from "node:module";
3074
+ import { loadRuntimeDatabaseSync } from "@wrongstack/persistence";
3061
3075
 
3062
3076
  // src/utils/sqlite-warning.ts
3063
3077
  var SQLITE_EXPERIMENTAL_WARNING_RE = /sqlite is an experimental feature/i;
@@ -3087,20 +3101,18 @@ var CHRONICLE_SQLITE_FILE = "chronicle.sqlite";
3087
3101
  var LEGACY_JSONL_MIGRATION_KEY = "legacy-jsonl-v1";
3088
3102
  var LEGACY_JSONL_QUARANTINE_KEY = "legacy-jsonl-v1:quarantine";
3089
3103
  var LEGACY_JSONL_BOUNDARY_KEY = "legacy-jsonl-v1:boundary";
3090
- var SCHEMA_VERSION = 2;
3104
+ var SCHEMA_VERSION = 3;
3091
3105
  var Ctor;
3092
3106
  function loadDatabaseSync() {
3093
3107
  if (Ctor) return Ctor;
3094
- if (Ctor === null) throw new Error("node:sqlite is unavailable in this runtime");
3108
+ if (Ctor === null) throw new Error("SQLite is unavailable in this runtime");
3095
3109
  try {
3096
- Ctor = withSqliteExperimentalWarningSuppressed(
3097
- () => createRequire(import.meta.url)("node:sqlite").DatabaseSync
3098
- );
3110
+ Ctor = withSqliteExperimentalWarningSuppressed(loadRuntimeDatabaseSync);
3099
3111
  return Ctor;
3100
3112
  } catch (error) {
3101
3113
  Ctor = null;
3102
3114
  throw new Error(
3103
- "The Chronicle journal needs Node's built-in SQLite (node:sqlite, Node >= 22.5): " + (error instanceof Error ? error.message : String(error))
3115
+ "The Chronicle journal needs node:sqlite (Node >= 22.5) or bun:sqlite: " + (error instanceof Error ? error.message : String(error))
3104
3116
  );
3105
3117
  }
3106
3118
  }
@@ -3115,6 +3127,7 @@ function projectEvent(event) {
3115
3127
  taskId: event.scope.taskId ?? null,
3116
3128
  traceId: event.correlation?.traceId ?? null,
3117
3129
  logicalRequestId: event.correlation?.logicalRequestId ?? null,
3130
+ promptManifestId: event.correlation?.promptManifestId ?? null,
3118
3131
  resourceKind: event.resource?.kind ?? null,
3119
3132
  resourceId: event.resource?.id ?? null,
3120
3133
  resourcePath: event.resource?.path ?? null,
@@ -3139,6 +3152,7 @@ function ensureChronicleSchema(db) {
3139
3152
  task_id TEXT,
3140
3153
  trace_id TEXT,
3141
3154
  logical_request_id TEXT,
3155
+ prompt_manifest_id TEXT,
3142
3156
  resource_kind TEXT,
3143
3157
  resource_id TEXT,
3144
3158
  resource_path TEXT,
@@ -3166,6 +3180,10 @@ function ensureChronicleSchema(db) {
3166
3180
  if (version < 2) {
3167
3181
  db.exec("DROP INDEX IF EXISTS events_resource_path");
3168
3182
  }
3183
+ if (version > 0 && version < 3) {
3184
+ db.exec("ALTER TABLE events ADD COLUMN prompt_manifest_id TEXT");
3185
+ }
3186
+ db.exec("CREATE INDEX IF NOT EXISTS events_prompt_manifest ON events(prompt_manifest_id)");
3169
3187
  if (version !== SCHEMA_VERSION) {
3170
3188
  db.exec(`PRAGMA user_version = ${SCHEMA_VERSION}`);
3171
3189
  }
@@ -3202,6 +3220,7 @@ function pushDown(query) {
3202
3220
  eq("task_id", query.taskId);
3203
3221
  eq("trace_id", query.traceId);
3204
3222
  eq("logical_request_id", query.logicalRequestId);
3223
+ eq("prompt_manifest_id", query.promptManifestId);
3205
3224
  eq("resource_kind", query.resourceKind);
3206
3225
  eq("resource_id", query.resourceId);
3207
3226
  if (query.eventTypes?.length) {
@@ -3558,6 +3577,7 @@ var ChronicleSqliteJournal = class {
3558
3577
  row.taskId,
3559
3578
  row.traceId,
3560
3579
  row.logicalRequestId,
3580
+ row.promptManifestId,
3561
3581
  row.resourceKind,
3562
3582
  row.resourceId,
3563
3583
  row.resourcePath,
@@ -3717,9 +3737,9 @@ var ChronicleSqliteJournal = class {
3717
3737
  const insert = this.db.prepare(
3718
3738
  `INSERT INTO events (
3719
3739
  day, sequence, event_id, hash, previous_hash, occurred_at, event_type, outcome,
3720
- project_id, session_id, agent_id, task_id, trace_id, logical_request_id,
3740
+ project_id, session_id, agent_id, task_id, trace_id, logical_request_id, prompt_manifest_id,
3721
3741
  resource_kind, resource_id, resource_path, duration_ns, payload
3722
- ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`
3742
+ ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`
3723
3743
  );
3724
3744
  const checkpoint = this.db.prepare(
3725
3745
  `INSERT INTO chain_checkpoint (day, sequence, hash) VALUES (?, ?, ?)
@@ -3748,6 +3768,7 @@ var ChronicleSqliteJournal = class {
3748
3768
  row.taskId,
3749
3769
  row.traceId,
3750
3770
  row.logicalRequestId,
3771
+ row.promptManifestId,
3751
3772
  row.resourceKind,
3752
3773
  row.resourceId,
3753
3774
  row.resourcePath,
@@ -3834,9 +3855,9 @@ var ChronicleSqliteJournal = class {
3834
3855
  insert: this.db.prepare(
3835
3856
  `INSERT INTO events (
3836
3857
  day, sequence, event_id, hash, previous_hash, occurred_at, event_type, outcome,
3837
- project_id, session_id, agent_id, task_id, trace_id, logical_request_id,
3858
+ project_id, session_id, agent_id, task_id, trace_id, logical_request_id, prompt_manifest_id,
3838
3859
  resource_kind, resource_id, resource_path, duration_ns, payload
3839
- ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`
3860
+ ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`
3840
3861
  ),
3841
3862
  trimBoundary: this.db.prepare(
3842
3863
  "SELECT day, sequence, hash FROM events ORDER BY day, sequence LIMIT 1 OFFSET ?"
@@ -3877,8 +3898,8 @@ var ChronicleSqliteJournal = class {
3877
3898
  };
3878
3899
 
3879
3900
  // src/chronicle/metrics-schema.ts
3880
- import { createRequire as createRequire2 } from "node:module";
3881
- var SCHEMA_VERSION2 = 3;
3901
+ import { loadRuntimeDatabaseSync as loadRuntimeDatabaseSync2 } from "@wrongstack/persistence";
3902
+ var SCHEMA_VERSION2 = 4;
3882
3903
  var READ_CHUNK_BYTES = 1024 * 1024;
3883
3904
  var SQLITE_SOURCE_PREFIX = "sqlite:";
3884
3905
  var SQLITE_INGEST_BATCH = 2e3;
@@ -3896,16 +3917,14 @@ var EMPTY_FAMILIES = {
3896
3917
  var Ctor2;
3897
3918
  function loadDatabaseSync2() {
3898
3919
  if (Ctor2) return Ctor2;
3899
- if (Ctor2 === null) throw new Error("node:sqlite is unavailable in this runtime");
3920
+ if (Ctor2 === null) throw new Error("SQLite is unavailable in this runtime");
3900
3921
  try {
3901
- Ctor2 = withSqliteExperimentalWarningSuppressed(
3902
- () => createRequire2(import.meta.url)("node:sqlite").DatabaseSync
3903
- );
3922
+ Ctor2 = withSqliteExperimentalWarningSuppressed(loadRuntimeDatabaseSync2);
3904
3923
  return Ctor2;
3905
3924
  } catch (error) {
3906
3925
  Ctor2 = null;
3907
3926
  throw new Error(
3908
- "Chronicle metrics need Node's built-in SQLite (node:sqlite, Node >= 22.5): " + (error instanceof Error ? error.message : String(error))
3927
+ "Chronicle metrics need node:sqlite (Node >= 22.5) or bun:sqlite: " + (error instanceof Error ? error.message : String(error))
3909
3928
  );
3910
3929
  }
3911
3930
  }
@@ -3966,6 +3985,9 @@ function ensureMetricsSchema(db) {
3966
3985
  tool_name TEXT NOT NULL DEFAULT '',
3967
3986
  provider_id TEXT NOT NULL DEFAULT '',
3968
3987
  model_id TEXT NOT NULL DEFAULT '',
3988
+ logical_request_id TEXT NOT NULL DEFAULT '',
3989
+ prompt_manifest_id TEXT NOT NULL DEFAULT '',
3990
+ provenance_confidence TEXT NOT NULL DEFAULT 'unknown',
3969
3991
  source TEXT NOT NULL DEFAULT ''
3970
3992
  );
3971
3993
  CREATE INDEX IF NOT EXISTS idx_file_lineage_path ON file_lineage(path_key, occurred_at);
@@ -4058,6 +4080,20 @@ var ChronicleMetricsIngester = class {
4058
4080
  db;
4059
4081
  directory;
4060
4082
  dbPath;
4083
+ /**
4084
+ * Prepared-statement cache for the per-event ingest hot paths. Preparing
4085
+ * the same SQL on every event was the dominant ingest cost; node:sqlite
4086
+ * statements are reusable, so each distinct SQL string is prepared once.
4087
+ */
4088
+ stmtCache = /* @__PURE__ */ new Map();
4089
+ stmt(sql) {
4090
+ let s = this.stmtCache.get(sql);
4091
+ if (!s) {
4092
+ s = this.db.prepare(sql);
4093
+ this.stmtCache.set(sql, s);
4094
+ }
4095
+ return s;
4096
+ }
4061
4097
  async refresh() {
4062
4098
  const result = {
4063
4099
  ingestedEvents: 0,
@@ -4087,7 +4123,7 @@ var ChronicleMetricsIngester = class {
4087
4123
  let base;
4088
4124
  if (!migrated) {
4089
4125
  base = offsets.get(key) ?? 0;
4090
- } else if (boundary !== null && boundary.has(key)) {
4126
+ } else if (boundary?.has(key)) {
4091
4127
  base = Math.max(offsets.get(key) ?? 0, boundary.get(key));
4092
4128
  } else {
4093
4129
  base = rebuilt ? 0 : offsets.get(key) ?? 0;
@@ -4310,11 +4346,11 @@ var ChronicleMetricsIngester = class {
4310
4346
  }
4311
4347
  ingestDailyCounters(event) {
4312
4348
  const day = eventDay(event);
4313
- this.db.prepare("INSERT OR IGNORE INTO daily_counters (day) VALUES (?)").run(day);
4314
- const bump = (sql, ...params) => this.db.prepare(`UPDATE daily_counters SET ${sql} WHERE day = ?`).run(...params, day);
4349
+ this.stmt("INSERT OR IGNORE INTO daily_counters (day) VALUES (?)").run(day);
4350
+ const bump = (sql, ...params) => this.stmt(`UPDATE daily_counters SET ${sql} WHERE day = ?`).run(...params, day);
4315
4351
  const family = signalFamily(event);
4316
4352
  const failed = isTerminalFailure(event) ? 1 : 0;
4317
- this.db.prepare(
4353
+ this.stmt(
4318
4354
  `INSERT INTO family_daily (day, family, count, failure_count) VALUES (?, ?, 1, ?)
4319
4355
  ON CONFLICT(day, family) DO UPDATE SET count = count + 1, failure_count = failure_count + excluded.failure_count`
4320
4356
  ).run(day, family, failed);
@@ -4323,12 +4359,15 @@ var ChronicleMetricsIngester = class {
4323
4359
  bump("cancellations = cancellations + 1");
4324
4360
  if (family === "agent") bump("agent_events = agent_events + 1");
4325
4361
  if (event.correlation.logicalRequestId) {
4326
- this.db.prepare(
4362
+ this.stmt(
4327
4363
  "INSERT OR IGNORE INTO logical_request_daily (day, logical_request_id) VALUES (?, ?)"
4328
4364
  ).run(day, event.correlation.logicalRequestId);
4329
4365
  }
4330
4366
  if (event.scope.agentId) {
4331
- this.db.prepare("INSERT OR IGNORE INTO agent_daily (day, agent_id) VALUES (?, ?)").run(day, event.scope.agentId);
4367
+ this.stmt("INSERT OR IGNORE INTO agent_daily (day, agent_id) VALUES (?, ?)").run(
4368
+ day,
4369
+ event.scope.agentId
4370
+ );
4332
4371
  }
4333
4372
  const type = event.eventType;
4334
4373
  if (type === "decision.requested") bump("decisions = decisions + 1");
@@ -4350,7 +4389,10 @@ var ChronicleMetricsIngester = class {
4350
4389
  if (event.resource?.kind === "file" || type.startsWith("file.")) {
4351
4390
  bump("file_events_all = file_events_all + 1");
4352
4391
  if (event.resource?.path) {
4353
- this.db.prepare("INSERT OR IGNORE INTO file_seen_daily (day, path_key) VALUES (?, ?)").run(day, normalizePathKey(event.resource.path));
4392
+ this.stmt("INSERT OR IGNORE INTO file_seen_daily (day, path_key) VALUES (?, ?)").run(
4393
+ day,
4394
+ normalizePathKey(event.resource.path)
4395
+ );
4354
4396
  }
4355
4397
  }
4356
4398
  }
@@ -4359,8 +4401,10 @@ var ChronicleMetricsIngester = class {
4359
4401
  const providerId = event.runtime?.providerId ?? asString(readPath2(event.attributes ?? {}, "from.providerId")) ?? "";
4360
4402
  const modelId = event.runtime?.modelId ?? asString(readPath2(event.attributes ?? {}, "from.model")) ?? "";
4361
4403
  if (!providerId && !modelId) return;
4362
- this.db.prepare("INSERT OR IGNORE INTO provider_daily (day, provider_id, model_id) VALUES (?, ?, ?)").run(day, providerId, modelId);
4363
- const update = (sql, ...params) => this.db.prepare(
4404
+ this.stmt(
4405
+ "INSERT OR IGNORE INTO provider_daily (day, provider_id, model_id) VALUES (?, ?, ?)"
4406
+ ).run(day, providerId, modelId);
4407
+ const update = (sql, ...params) => this.stmt(
4364
4408
  `UPDATE provider_daily SET ${sql} WHERE day = ? AND provider_id = ? AND model_id = ?`
4365
4409
  ).run(...params, day, providerId, modelId);
4366
4410
  const duration = durationMs2(event);
@@ -4401,7 +4445,7 @@ var ChronicleMetricsIngester = class {
4401
4445
  if (typeof cost !== "number" || !Number.isFinite(cost)) return;
4402
4446
  const scopeKey2 = `${event.scope.projectId ?? ""}\0${event.scope.sessionId ?? ""}\0${event.scope.agentId ?? ""}`;
4403
4447
  const occurredAt = event.occurredAt ?? event.observedAt;
4404
- this.db.prepare(
4448
+ this.stmt(
4405
4449
  `INSERT INTO token_cost (scope_key, day, occurred_at, sequence, cost) VALUES (?, ?, ?, ?, ?)
4406
4450
  ON CONFLICT(scope_key) DO UPDATE SET
4407
4451
  day = excluded.day, occurred_at = excluded.occurred_at,
@@ -4415,8 +4459,8 @@ var ChronicleMetricsIngester = class {
4415
4459
  const taskId = event.scope.taskId ?? stringAt(attributes, "taskId");
4416
4460
  if (!taskId) return;
4417
4461
  const occurredAt = event.occurredAt ?? event.observedAt;
4418
- this.db.prepare("INSERT OR IGNORE INTO task_outcomes (task_id) VALUES (?)").run(taskId);
4419
- const set = (sql, ...params) => this.db.prepare(`UPDATE task_outcomes SET ${sql} WHERE task_id = ?`).run(...params, taskId);
4462
+ this.stmt("INSERT OR IGNORE INTO task_outcomes (task_id) VALUES (?)").run(taskId);
4463
+ const set = (sql, ...params) => this.stmt(`UPDATE task_outcomes SET ${sql} WHERE task_id = ?`).run(...params, taskId);
4420
4464
  const lineage = [
4421
4465
  ["run_id", stringAt(attributes, "runId")],
4422
4466
  ["board_id", event.scope.kanbanBoardId ?? stringAt(attributes, "boardId")],
@@ -4463,11 +4507,12 @@ var ChronicleMetricsIngester = class {
4463
4507
  if (!operation || operation === "read") return;
4464
4508
  const filePath = event.resource?.path ?? stringAt(attributes, "filePath");
4465
4509
  if (!filePath) return;
4466
- this.db.prepare(
4510
+ this.stmt(
4467
4511
  `INSERT OR IGNORE INTO file_lineage
4468
4512
  (event_id, path, path_key, operation, occurred_at, session_id, agent_id, task_id, board_id, run_id,
4469
- tool_name, provider_id, model_id, source)
4470
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
4513
+ tool_name, provider_id, model_id, logical_request_id, prompt_manifest_id,
4514
+ provenance_confidence, source)
4515
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
4471
4516
  ).run(
4472
4517
  event.eventId,
4473
4518
  normalizeKey(filePath),
@@ -4482,10 +4527,17 @@ var ChronicleMetricsIngester = class {
4482
4527
  stringAt(attributes, "toolName") ?? "",
4483
4528
  event.runtime?.providerId ?? stringAt(attributes, "provider") ?? "",
4484
4529
  event.runtime?.modelId ?? stringAt(attributes, "model") ?? "",
4530
+ event.correlation.logicalRequestId ?? stringAt(attributes, "logicalRequestId") ?? "",
4531
+ event.correlation.promptManifestId ?? stringAt(attributes, "promptManifestId") ?? "",
4532
+ provenanceConfidence(attributes),
4485
4533
  stringAt(attributes, "source") ?? (event.eventType === "file.event" ? "tool" : "external")
4486
4534
  );
4487
4535
  }
4488
4536
  };
4537
+ function provenanceConfidence(attributes) {
4538
+ const value = attributes["provenanceConfidence"];
4539
+ return value === "explicit" || value === "correlated" || value === "inferred" ? value : "unknown";
4540
+ }
4489
4541
 
4490
4542
  // src/chronicle/metrics-store.ts
4491
4543
  var ChronicleMetricsStore = class _ChronicleMetricsStore {
@@ -4617,7 +4669,8 @@ var ChronicleMetricsStore = class _ChronicleMetricsStore {
4617
4669
  const where = clauses.length > 0 ? ` WHERE ${clauses.join(" AND ")}` : "";
4618
4670
  params.push(clampLimit(options.limit, 200));
4619
4671
  const projection = `path, operation, occurred_at, session_id, agent_id, task_id, board_id, run_id,
4620
- tool_name, provider_id, model_id, source`;
4672
+ tool_name, provider_id, model_id, logical_request_id, prompt_manifest_id,
4673
+ provenance_confidence, source`;
4621
4674
  const sql = options.latestPerPath ? `SELECT ${projection} FROM (
4622
4675
  SELECT ${projection}, ROW_NUMBER() OVER (
4623
4676
  PARTITION BY path_key ORDER BY occurred_at DESC, event_id DESC
@@ -4638,6 +4691,9 @@ var ChronicleMetricsStore = class _ChronicleMetricsStore {
4638
4691
  toolName: row.tool_name,
4639
4692
  providerId: row.provider_id,
4640
4693
  modelId: row.model_id,
4694
+ logicalRequestId: row.logical_request_id,
4695
+ promptManifestId: row.prompt_manifest_id,
4696
+ provenanceConfidence: row.provenance_confidence,
4641
4697
  source: row.source
4642
4698
  }));
4643
4699
  }
@@ -14,6 +14,7 @@ export interface ChronicleQuery {
14
14
  modelId?: string;
15
15
  traceId?: string;
16
16
  logicalRequestId?: string;
17
+ promptManifestId?: string;
17
18
  attemptId?: string;
18
19
  toolCallId?: string;
19
20
  resourceKind?: ChronicleResourceRef['kind'];
@@ -4,7 +4,7 @@ export declare const CHRONICLE_SQLITE_FILE = "chronicle.sqlite";
4
4
  export declare const LEGACY_JSONL_MIGRATION_KEY = "legacy-jsonl-v1";
5
5
  export declare const LEGACY_JSONL_QUARANTINE_KEY = "legacy-jsonl-v1:quarantine";
6
6
  export declare const LEGACY_JSONL_BOUNDARY_KEY = "legacy-jsonl-v1:boundary";
7
- export declare const SCHEMA_VERSION = 2;
7
+ export declare const SCHEMA_VERSION = 3;
8
8
  export declare function loadDatabaseSync(): typeof DatabaseSync;
9
9
  export interface ProjectedRow {
10
10
  occurredAt: string;
@@ -15,6 +15,7 @@ export interface ProjectedRow {
15
15
  taskId: string | null;
16
16
  traceId: string | null;
17
17
  logicalRequestId: string | null;
18
+ promptManifestId: string | null;
18
19
  resourceKind: string | null;
19
20
  resourceId: string | null;
20
21
  resourcePath: string | null;
@@ -23,6 +23,8 @@ export interface ChronicleCorrelation {
23
23
  spanId: string;
24
24
  parentSpanId?: string | undefined;
25
25
  logicalRequestId?: string | undefined;
26
+ /** Content-addressed identity of the exact provider-visible prompt composition. */
27
+ promptManifestId?: string | undefined;
26
28
  attemptId?: string | undefined;
27
29
  toolCallId?: string | undefined;
28
30
  }
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * @module agent-status-helpers
10
10
  */
11
- import type { AgentActivityTotals, AgentRecentMail, AgentRecentTool, AgentTodoItem } from './session-registry.js';
11
+ import type { AgentActivityTotals, AgentRecentMail, AgentRecentTool, AgentTodoItem } from '../session-catalog/session-registry.js';
12
12
  export interface PendingTool {
13
13
  name: string;
14
14
  input?: unknown | undefined;
@@ -1,5 +1,5 @@
1
- import type { EventBus } from './kernel/events.js';
2
- import type { AgentEntry } from './session-registry.js';
1
+ import type { EventBus } from '../kernel/events.js';
2
+ import type { AgentEntry } from '../session-catalog/session-registry.js';
3
3
  interface SessionPresenceRegistry {
4
4
  updateAgents(agents: AgentEntry[]): Promise<void>;
5
5
  }
@@ -1,4 +1,4 @@
1
- import type { CollaborationBus, InjectedToolResult } from '../coordination/collab-bus.js';
1
+ import type { CollaborationBus, InjectedToolResult } from './collab-bus.js';
2
2
  import type { ToolCallPipelinePayload } from '../core/agent.js';
3
3
  import type { Middleware } from '../kernel/pipeline.js';
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { type KanbanBoard, type KanbanTask } from '@wrongstack/kanban';
1
+ import type { KanbanBoard, KanbanTask } from '@wrongstack/kanban';
2
2
  import type { SubagentConfig, TaskResult } from '../types/multi-agent.js';
3
3
  export interface KanbanQueueInput {
4
4
  action?: 'dispatch_ready' | undefined;
@@ -56,6 +56,13 @@ export declare class Director implements DirectorFleetHost, ICoordinator {
56
56
  private readonly subagentIdleTimeoutMs;
57
57
  private readonly retireSubagentOnTaskComplete;
58
58
  private readonly subagentIdleTimers;
59
+ /**
60
+ * Effective idle window per subagent (spawn-time `idleTimeoutMs` override
61
+ * or the Director-wide default; undefined = no window). Internal-task
62
+ * completion re-arms with THIS value, not the Director-wide default, so
63
+ * a subagent-configured window survives its first internal probe.
64
+ */
65
+ private readonly subagentIdleDelayMs;
59
66
  readonly sharedScratchpadPath: string | null;
60
67
  readonly maxSpawns: number;
61
68
  readonly maxSpawnDepth: number;
@@ -76,12 +76,15 @@ export interface ExploreCompanionOptions {
76
76
  /** Project mailbox the companion polls for explicit asks and acks them. */
77
77
  mailbox: Mailbox;
78
78
  /**
79
- * Leader session id used to filter out subagent events. The companion
80
- * subscribes to global events (tool.executed, error, session.agents_updated)
81
- * which fire for BOTH the leader and subagents. When set, any event whose
82
- * `sessionId` differs from this value is skipped. Events without a
83
- * `sessionId` field always pass through (backward compatibility). Pass a
84
- * lazy getter when the session id may change at runtime.
79
+ * Leader session id used to filter events down to this leader only. The
80
+ * companion subscribes to global events (tool.executed, error,
81
+ * session.agents_updated) which fire for BOTH the leader and subagents.
82
+ * Strict, fail-closed: an event passes only when its `sessionId` equals
83
+ * this value unstamped events are dropped (production emitters always
84
+ * stamp; an unstamped event is assumed to be a subagent's), and a
85
+ * transiently unresolved getter drops everything rather than probing on
86
+ * unattributed activity. Pass a lazy getter when the session id may
87
+ * change at runtime.
85
88
  */
86
89
  leaderSessionId: string | (() => string | undefined);
87
90
  /**
@@ -15,7 +15,7 @@
15
15
  * @module fleet-status-tool
16
16
  */
17
17
  import type { EventBus } from '../kernel/events.js';
18
- import type { AgentEntry } from '../session-registry.js';
18
+ import type { AgentEntry } from '../session-catalog/session-registry.js';
19
19
  import type { Tool } from '../types/tool.js';
20
20
  import { type MailboxResolver } from './mailbox-tool.js';
21
21
  export interface FleetStatusToolOptions {
@@ -72,7 +72,9 @@ export { formatSubagentStructuredReport, MAX_SUBAGENT_STRUCTURED_REPORT_CHARS, m
72
72
  export { startTechStackConsumer, type TechStackConsumerOptions, } from './techstack-mailbox-consumer.js';
73
73
  export { composeBoundedTaskDescription, type TaskBoundary, parseTaskBoundary, renderTaskBoundaryBlock, taskBoundarySchemaProperties, } from './task-boundary.js';
74
74
  export { type FleetWorktreePolicy, resolveSubagentWorktreeDecision, subagentNeedsWorktree, WorktreeIntegrationError, type WorktreeIsolationDecision, type WorktreeTaskRunnerOptions, type WorktreeTaskStateUpdate, wrapSubagentRunnerWithWorktrees, } from './worktree-task-runner.js';
75
- export { collabInjectMiddleware, collabPauseMiddleware, } from '../middleware/collab-pause.js';
75
+ export { collabInjectMiddleware, collabPauseMiddleware, } from './collab-pause.js';
76
+ export { kanbanBoundaryOps, type KanbanBoundaryOpsPort, setKanbanBoundaryOps, } from './kanban-ops-port.js';
77
+ export { kanbanDispatch, type KanbanDispatchPort, setKanbanDispatch, } from './kanban-dispatch-port.js';
76
78
  export { AdaptiveConcurrencyController, type AdaptiveConcurrencyState, } from './adaptive-concurrency.js';
77
79
  /** Agent Monitor — virtual chat history, timeline streaming, HQ bridge */
78
80
  export { type AgentMonitorOptions, AgentMonitorService, type AgentTimelineEntry, type AgentVirtualSession, createAgentMonitorService, } from './agent-monitor.js';
@@ -97,4 +99,6 @@ export { TaskAuctioneer } from './task-auctioneer.js';
97
99
  export type { DAGEdgeEvent, DAGEdgeHandler, DAGNode, DAGNodeStatus, RunnablesHandler, } from './task-dag.js';
98
100
  /** Task DAG — dependency graph with fork/join semantics */
99
101
  export { TaskDAG } from './task-dag.js';
102
+ export { AgentStatusTracker, type AgentStatusTrackerOptions, } from './agent-status-tracker.js';
103
+ export { FleetNotifier, type FleetNotifierOptions } from './fleet-notifier.js';
100
104
  //# sourceMappingURL=index.d.ts.map