@wrongstack/core 0.313.0 → 0.316.1

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 (343) hide show
  1. package/dist/chronicle/index.js +84 -6391
  2. package/dist/chronicle/legacy-journal-import.d.ts +0 -6
  3. package/dist/chronicle/metrics-ingest.d.ts +14 -0
  4. package/dist/chronicle/metrics-schema.d.ts +10 -1
  5. package/dist/chronicle/metrics-store.d.ts +20 -2
  6. package/dist/chronicle/project-server.js +98 -4874
  7. package/dist/chronicle/sink.d.ts +13 -0
  8. package/dist/chronicle/sqlite-journal.d.ts +20 -2
  9. package/dist/chunk-25LSLC3G.js +334 -0
  10. package/dist/chunk-27QIURLN.js +1073 -0
  11. package/dist/chunk-2FK4WTFF.js +207 -0
  12. package/dist/chunk-2YU4WVBW.js +134 -0
  13. package/dist/chunk-3AGWVSS7.js +4608 -0
  14. package/dist/chunk-3BDV7RL3.js +211 -0
  15. package/dist/chunk-3ECENVHL.js +325 -0
  16. package/dist/chunk-3XPVB7BA.js +135 -0
  17. package/dist/chunk-45WI72ZB.js +16884 -0
  18. package/dist/chunk-4BMVPOHO.js +3748 -0
  19. package/dist/chunk-4I7HGVVA.js +363 -0
  20. package/dist/chunk-4LCZVJVF.js +317 -0
  21. package/dist/chunk-4SJNS7OB.js +217 -0
  22. package/dist/chunk-4VWO3ZXL.js +342 -0
  23. package/dist/chunk-57GEWK5X.js +26 -0
  24. package/dist/chunk-5BMIE7QG.js +46 -0
  25. package/dist/chunk-5S437PRC.js +50 -0
  26. package/dist/chunk-5XDUGTKN.js +511 -0
  27. package/dist/chunk-5YPSXQXM.js +1443 -0
  28. package/dist/chunk-6FHWXLPT.js +10 -0
  29. package/dist/chunk-6H5GEOET.js +2406 -0
  30. package/dist/chunk-6NWEVFEL.js +151 -0
  31. package/dist/chunk-AYW5YINX.js +58 -0
  32. package/dist/chunk-B4AMLZPB.js +9 -0
  33. package/dist/chunk-B7F4WVP4.js +65 -0
  34. package/dist/chunk-BJHVULHO.js +55 -0
  35. package/dist/chunk-BPBKKBUK.js +2085 -0
  36. package/dist/chunk-BYD345OX.js +589 -0
  37. package/dist/chunk-C27KDLOX.js +279 -0
  38. package/dist/chunk-CU546ESW.js +597 -0
  39. package/dist/chunk-DLHHXUAM.js +172 -0
  40. package/dist/chunk-DOTHQSJ2.js +429 -0
  41. package/dist/chunk-DYLPMV4Q.js +711 -0
  42. package/dist/chunk-EODDVJBM.js +82 -0
  43. package/dist/chunk-F3JWNST7.js +361 -0
  44. package/dist/chunk-FC2ZGRF3.js +140 -0
  45. package/dist/chunk-FCBTO76Z.js +5786 -0
  46. package/dist/chunk-FHZVFYSL.js +396 -0
  47. package/dist/chunk-FNXVT7HF.js +52 -0
  48. package/dist/chunk-FWNLEZYG.js +259 -0
  49. package/dist/chunk-FXQLIX3K.js +211 -0
  50. package/dist/chunk-G5S3S5ZN.js +38 -0
  51. package/dist/chunk-GDQ7CZRQ.js +116 -0
  52. package/dist/chunk-GJJGJB2R.js +1374 -0
  53. package/dist/chunk-GTCU6DZ3.js +1 -0
  54. package/dist/chunk-HA4ZYA6T.js +178 -0
  55. package/dist/chunk-HI3JGZR2.js +188 -0
  56. package/dist/chunk-HMLIGAU7.js +395 -0
  57. package/dist/chunk-HXKZ7OBQ.js +303 -0
  58. package/dist/chunk-I7DALG7J.js +292 -0
  59. package/dist/chunk-IRUTEHCE.js +960 -0
  60. package/dist/chunk-IYFBFX34.js +86 -0
  61. package/dist/chunk-J2WRWR37.js +1104 -0
  62. package/dist/chunk-JFPJ6LLQ.js +129 -0
  63. package/dist/chunk-JMULFFLN.js +9 -0
  64. package/dist/chunk-JO4MGB6Z.js +1264 -0
  65. package/dist/chunk-JVKB2TBL.js +48 -0
  66. package/dist/chunk-JX7VBZDK.js +31 -0
  67. package/dist/chunk-K6BXGITA.js +931 -0
  68. package/dist/chunk-KDQJCT2J.js +45 -0
  69. package/dist/chunk-KJ2ZTQSL.js +47 -0
  70. package/dist/chunk-KZMSZV32.js +187 -0
  71. package/dist/chunk-LA7CLDRW.js +129 -0
  72. package/dist/chunk-LHOA5DWA.js +28 -0
  73. package/dist/chunk-LSMMOS2Z.js +119 -0
  74. package/dist/chunk-LX5QWLBL.js +27 -0
  75. package/dist/chunk-LXWCMQNJ.js +789 -0
  76. package/dist/chunk-M27LIEKV.js +2829 -0
  77. package/dist/chunk-MJPHJRAL.js +663 -0
  78. package/dist/chunk-MTL4O5YR.js +228 -0
  79. package/dist/chunk-NDBIPFNY.js +102 -0
  80. package/dist/chunk-NEMIWEXC.js +1199 -0
  81. package/dist/chunk-NHJ75HXY.js +1 -0
  82. package/dist/chunk-NIOAGFPB.js +1510 -0
  83. package/dist/chunk-NS52ISWS.js +355 -0
  84. package/dist/chunk-NSOFPKGT.js +5352 -0
  85. package/dist/chunk-NVIZG63R.js +757 -0
  86. package/dist/chunk-O37BQ65S.js +21 -0
  87. package/dist/chunk-OOYZPOXM.js +308 -0
  88. package/dist/chunk-OSGLYW5J.js +28 -0
  89. package/dist/chunk-PFCMSSUF.js +1640 -0
  90. package/dist/chunk-PFZO3C6H.js +14 -0
  91. package/dist/chunk-PGRVXIMY.js +158 -0
  92. package/dist/chunk-PHH7LD45.js +113 -0
  93. package/dist/chunk-PISBFBJN.js +109 -0
  94. package/dist/chunk-POOOIWE5.js +9 -0
  95. package/dist/chunk-PQNS3U7Z.js +1240 -0
  96. package/dist/chunk-QSTSJOCK.js +402 -0
  97. package/dist/chunk-RFQMOKWK.js +282 -0
  98. package/dist/chunk-RJIZEJ42.js +30 -0
  99. package/dist/chunk-RTOTNK3P.js +484 -0
  100. package/dist/chunk-RXKSDUAU.js +1172 -0
  101. package/dist/chunk-S45JPKQN.js +3317 -0
  102. package/dist/chunk-SAFHACFA.js +152 -0
  103. package/dist/chunk-SQJVFEBV.js +41 -0
  104. package/dist/chunk-SVT4RNTR.js +49 -0
  105. package/dist/chunk-SWUFN7XM.js +43 -0
  106. package/dist/chunk-SXMVYC5H.js +174 -0
  107. package/dist/chunk-SZ6AYUIZ.js +23 -0
  108. package/dist/chunk-TBRL2RCC.js +9 -0
  109. package/dist/chunk-TCCHINEF.js +655 -0
  110. package/dist/chunk-THEGTRAG.js +316 -0
  111. package/dist/chunk-TR4LQE7L.js +2256 -0
  112. package/dist/chunk-TRT2HRWZ.js +18 -0
  113. package/dist/chunk-TWJMGXCI.js +900 -0
  114. package/dist/chunk-U45AXT5D.js +1023 -0
  115. package/dist/chunk-U4FWBSO3.js +509 -0
  116. package/dist/chunk-UBGDX6FI.js +147 -0
  117. package/dist/chunk-UJILKYES.js +75 -0
  118. package/dist/chunk-ULMAQV3T.js +234 -0
  119. package/dist/chunk-VVBP6KGT.js +9 -0
  120. package/dist/chunk-W5VITDM2.js +168 -0
  121. package/dist/chunk-WAHQVNWT.js +194 -0
  122. package/dist/chunk-WBPVKEEE.js +227 -0
  123. package/dist/chunk-WGGYRBXH.js +5434 -0
  124. package/dist/chunk-WLYKU45P.js +5770 -0
  125. package/dist/chunk-WP7BVANJ.js +53 -0
  126. package/dist/chunk-WQQON3SV.js +473 -0
  127. package/dist/chunk-WQTOVMGV.js +119 -0
  128. package/dist/chunk-XBDP4QPW.js +7 -0
  129. package/dist/chunk-XEBHSJLT.js +103 -0
  130. package/dist/chunk-XF4VUMKW.js +231 -0
  131. package/dist/chunk-XQ2ECNK3.js +1 -0
  132. package/dist/chunk-Y5YXDM7D.js +74 -0
  133. package/dist/chunk-YOPAUVU4.js +2588 -0
  134. package/dist/chunk-YPT4A46F.js +362 -0
  135. package/dist/chunk-YWXT3JNM.js +425 -0
  136. package/dist/chunk-YY6APYUM.js +49 -0
  137. package/dist/chunk-Z2IJUO45.js +691 -0
  138. package/dist/chunk-ZHZ2Y2DH.js +1643 -0
  139. package/dist/chunk-ZT7JNIGX.js +152 -0
  140. package/dist/coordination/agent-monitor.d.ts +9 -1
  141. package/dist/coordination/agent-subagent-runner.d.ts +1 -1
  142. package/dist/coordination/agents/agent-prompts.d.ts +8 -0
  143. package/dist/coordination/agents/index.d.ts +33 -1
  144. package/dist/coordination/agents/index.js +184 -6269
  145. package/dist/coordination/agents/phase3-wave1-platform.d.ts +1 -3
  146. package/dist/coordination/agents/phase3-wave2-meta.d.ts +1 -3
  147. package/dist/coordination/agents/phase8-wave3-products.d.ts +1 -3
  148. package/dist/coordination/agents/phase9-wave4-platform-meta.d.ts +1 -3
  149. package/dist/coordination/agents/project-agent-identity.d.ts +11 -11
  150. package/dist/coordination/agents/types.d.ts +13 -2
  151. package/dist/coordination/brain-monitor.d.ts +30 -7
  152. package/dist/coordination/collab-debug.d.ts +1 -1
  153. package/dist/coordination/collab-pause.d.ts +1 -1
  154. package/dist/coordination/delegate-tool.d.ts +7 -5
  155. package/dist/coordination/director-kanban-queue-helpers.d.ts +1 -0
  156. package/dist/coordination/director-options.d.ts +7 -0
  157. package/dist/coordination/director-spawn-model.d.ts +17 -0
  158. package/dist/coordination/director-tools.d.ts +2 -2
  159. package/dist/coordination/director.d.ts +12 -0
  160. package/dist/coordination/dispatcher.d.ts +8 -0
  161. package/dist/coordination/fleet-bus.d.ts +35 -4
  162. package/dist/coordination/fleet-supervisor.d.ts +10 -2
  163. package/dist/coordination/fleet.d.ts +16 -7
  164. package/dist/coordination/index.d.ts +4 -0
  165. package/dist/coordination/index.js +402 -34324
  166. package/dist/coordination/kanban-dispatch-port.d.ts +2 -2
  167. package/dist/coordination/mailbox-http-router.d.ts +4 -3
  168. package/dist/coordination/mailbox-http-validation.d.ts +1 -1
  169. package/dist/coordination/mailbox-project-server.js +48 -3276
  170. package/dist/coordination/mailbox-types.d.ts +24 -6
  171. package/dist/coordination/model-tier-leader.d.ts +122 -0
  172. package/dist/coordination/model-tier.d.ts +122 -0
  173. package/dist/coordination/multi-agent-coordinator.d.ts +24 -0
  174. package/dist/coordination/origin-session.d.ts +16 -0
  175. package/dist/coordination/provider-status-tracker.d.ts +41 -5
  176. package/dist/coordination/session-note-hub.d.ts +44 -0
  177. package/dist/coordination/session-note-tool.d.ts +10 -0
  178. package/dist/core/agent.d.ts +15 -2
  179. package/dist/core/context.d.ts +22 -3
  180. package/dist/core/index.d.ts +2 -0
  181. package/dist/core/index.js +239 -12360
  182. package/dist/core/model-ref.js +5 -23
  183. package/dist/core/provider-runner.d.ts +36 -1
  184. package/dist/core/request-conversation-binding.d.ts +37 -0
  185. package/dist/core/session-notes.d.ts +25 -0
  186. package/dist/core/system-prompt-builder.d.ts +11 -2
  187. package/dist/core/system-prompt-variants.d.ts +78 -0
  188. package/dist/design/index.js +50 -1087
  189. package/dist/execution/auto-compaction-middleware.d.ts +11 -0
  190. package/dist/execution/autonomy-brain.d.ts +2 -1
  191. package/dist/execution/autonomy-prompt-contributor.d.ts +7 -2
  192. package/dist/execution/compaction-core.d.ts +4 -4
  193. package/dist/execution/eternal-autonomy.d.ts +1 -1
  194. package/dist/execution/index.d.ts +1 -1
  195. package/dist/execution/index.js +1615 -21895
  196. package/dist/execution/model-runtime.d.ts +0 -7
  197. package/dist/execution/parallel-eternal-engine.d.ts +7 -7
  198. package/dist/execution/prompt-enhancer.js +16 -535
  199. package/dist/execution/retry-policy.d.ts +31 -1
  200. package/dist/extension/index.js +7 -311
  201. package/dist/goal/index.js +33 -3435
  202. package/dist/hooks/index.js +14 -1138
  203. package/dist/hq/index.js +114 -5139
  204. package/dist/hq/persistence/event-log.d.ts +0 -1
  205. package/dist/hq/persistence.d.ts +4 -4
  206. package/dist/hq/protocol.js +21 -668
  207. package/dist/hq/publisher.d.ts +2 -0
  208. package/dist/index.d.ts +14 -11
  209. package/dist/index.js +1502 -92655
  210. package/dist/infrastructure/index.d.ts +4 -4
  211. package/dist/infrastructure/index.js +504 -5230
  212. package/dist/infrastructure/token-counter.d.ts +9 -0
  213. package/dist/kernel/events/agent-events.d.ts +77 -3
  214. package/dist/kernel/events/brain-events.d.ts +12 -0
  215. package/dist/kernel/events/provider-events.d.ts +22 -1
  216. package/dist/kernel/events/session-events.d.ts +14 -0
  217. package/dist/kernel/events/tool-events.d.ts +13 -0
  218. package/dist/kernel/index.js +14 -992
  219. package/dist/mailbox-attach.d.ts +1 -1
  220. package/dist/models/index.js +41 -1117
  221. package/dist/notifications/index.js +3 -108
  222. package/dist/observability/event-bridge.d.ts +25 -5
  223. package/dist/observability/index.d.ts +9 -8
  224. package/dist/observability/index.js +477 -631
  225. package/dist/observability/tool-usage-source.d.ts +65 -0
  226. package/dist/plugin/index.d.ts +5 -0
  227. package/dist/plugin/index.js +600 -14835
  228. package/dist/plugins/auto-review-plugin.d.ts +3 -2
  229. package/dist/plugins/review-finding-commands.d.ts +0 -8
  230. package/dist/plugins/review-finding-store.js +22 -0
  231. package/dist/plugins/review-finding-types.js +19 -0
  232. package/dist/plugins/review-report-integration.js +21 -0
  233. package/dist/plugins/review-report-store.js +20 -0
  234. package/dist/plugins/review-report-types.js +13 -0
  235. package/dist/prompts/index.js +14 -948
  236. package/dist/registry/index.js +9 -822
  237. package/dist/registry/tool-registry.d.ts +59 -9
  238. package/dist/registry-7N4O3E7W.js +14 -0
  239. package/dist/replay/index.js +6 -84
  240. package/dist/security/capabilities.d.ts +6 -0
  241. package/dist/security/file-permissions.d.ts +1 -1
  242. package/dist/security/index.js +161 -2235
  243. package/dist/security/permission-policy.d.ts +12 -1
  244. package/dist/security/secret-scrubber.d.ts +15 -0
  245. package/dist/session-catalog/index.d.ts +1 -0
  246. package/dist/session-catalog/index.js +41 -2103
  247. package/dist/session-catalog/project-server.js +59 -1435
  248. package/dist/session-catalog/protocol.d.ts +32 -1
  249. package/dist/session-catalog/registry.d.ts +17 -1
  250. package/dist/session-catalog/session-agents.d.ts +56 -0
  251. package/dist/session-catalog/store-rebuild.d.ts +14 -0
  252. package/dist/session-catalog/store-schema.d.ts +26 -0
  253. package/dist/session-catalog/store.d.ts +27 -1
  254. package/dist/session-note-attach.d.ts +9 -0
  255. package/dist/skills/index.js +35 -1578
  256. package/dist/statusline/index.d.ts +43 -0
  257. package/dist/statusline/index.js +102 -0
  258. package/dist/storage/board-store-port.d.ts +2 -2
  259. package/dist/storage/config-loader/in-project-policy.d.ts +29 -0
  260. package/dist/storage/config-loader.d.ts +3 -2
  261. package/dist/storage/file-session-writer.d.ts +4 -2
  262. package/dist/storage/goal-coordination.d.ts +6 -1
  263. package/dist/storage/goal-kanban.d.ts +4 -1
  264. package/dist/storage/index.d.ts +12 -4
  265. package/dist/storage/index.js +198 -15601
  266. package/dist/storage/input-history-store.d.ts +2 -4
  267. package/dist/storage/memory-curator.d.ts +133 -0
  268. package/dist/storage/session-agent-attribution.d.ts +39 -0
  269. package/dist/storage/session-doctor.d.ts +109 -0
  270. package/dist/storage/session-event-bridge.d.ts +5 -7
  271. package/dist/storage/session-outcome.d.ts +42 -0
  272. package/dist/storage/session-recovery.d.ts +55 -0
  273. package/dist/storage/session-store/load-session-data.d.ts +11 -0
  274. package/dist/storage/session-store/prune-helpers.d.ts +1 -1
  275. package/dist/storage/session-store/resume-session.d.ts +0 -2
  276. package/dist/storage/session-store/types.d.ts +8 -0
  277. package/dist/storage/session-store.d.ts +3 -3
  278. package/dist/storage/session-summary-tracker.d.ts +8 -1
  279. package/dist/storage/session-write-buffer.d.ts +18 -0
  280. package/dist/storage/session-writer-truncate.d.ts +2 -0
  281. package/dist/tasking/index.js +10 -676
  282. package/dist/tools/fallback-manage-tools.d.ts +6 -4
  283. package/dist/tools/index.js +52 -9590
  284. package/dist/tools/model-tier-set-tool.d.ts +66 -0
  285. package/dist/types/agent-bridge.d.ts +2 -1
  286. package/dist/types/config/autonomy.d.ts +5 -0
  287. package/dist/types/config/mcp-features.d.ts +7 -0
  288. package/dist/types/config/model-tiers.d.ts +148 -0
  289. package/dist/types/config/root.d.ts +9 -0
  290. package/dist/types/config/tools.d.ts +73 -0
  291. package/dist/types/config/ui.d.ts +1 -1
  292. package/dist/types/config.d.ts +1 -0
  293. package/dist/types/context.d.ts +2 -0
  294. package/dist/types/default-config.d.ts +6 -0
  295. package/dist/types/errors.d.ts +20 -1
  296. package/dist/types/index.d.ts +11 -9
  297. package/dist/types/index.js +131 -1342
  298. package/dist/types/multi-agent.d.ts +43 -0
  299. package/dist/types/plugin.d.ts +1 -1
  300. package/dist/types/provider-runner.d.ts +8 -0
  301. package/dist/types/provider.d.ts +15 -0
  302. package/dist/types/runtime-capability-manifest.d.ts +1 -1
  303. package/dist/types/secret-scrubber.d.ts +15 -0
  304. package/dist/types/session-markers.d.ts +37 -10
  305. package/dist/types/session-markers.js +8 -144
  306. package/dist/types/session-timeline.d.ts +197 -0
  307. package/dist/types/session-timeline.js +12 -0
  308. package/dist/types/session.d.ts +172 -11
  309. package/dist/types/system-prompt.d.ts +27 -0
  310. package/dist/utils/config-backup.d.ts +9 -1
  311. package/dist/utils/error.js +3 -4
  312. package/dist/utils/expect-defined.js +3 -9
  313. package/dist/utils/heap-watchdog.js +6 -706
  314. package/dist/utils/index.js +271 -5685
  315. package/dist/utils/message-invariants.d.ts +4 -1
  316. package/dist/utils/regex-guard.d.ts +1 -1
  317. package/dist/utils/sage-output-block.js +5 -42
  318. package/dist/utils/socket-path.d.ts +1 -1
  319. package/dist/utils/token-estimate.d.ts +6 -2
  320. package/dist/utils/wstack-paths.d.ts +2 -0
  321. package/dist/wiring/proxy-rewrite.d.ts +46 -0
  322. package/dist/wiring/proxy-rewrite.js +24 -121
  323. package/dist/worktree/index.js +6 -887
  324. package/instructions/agents/explore-companion.md +45 -18
  325. package/instructions/agents/memory-curator.md +34 -22
  326. package/instructions/coordination/director-preamble.md +12 -7
  327. package/instructions/coordination/subagent-baseline.md +26 -5
  328. package/instructions/leader-after-task.md +4 -1
  329. package/instructions/llm/chimera-review.md +30 -9
  330. package/instructions/llm/memory-curator.md +31 -0
  331. package/instructions/sections/tool/delegation-compact.md +2 -0
  332. package/instructions/sections/tool/delegation-full.md +5 -1
  333. package/instructions/sections/tool/mailbox-compact.md +5 -1
  334. package/instructions/sections/tool/mailbox-full.md +3 -0
  335. package/instructions/sections/tool/session-note-compact.md +3 -0
  336. package/instructions/sections/tool/session-note-full.md +15 -0
  337. package/instructions/system-lite.md +9 -4
  338. package/instructions/system-pro.md +66 -143
  339. package/instructions/system.md +73 -175
  340. package/package.json +32 -4
  341. package/dist/coordination/agents.d.ts +0 -8
  342. package/dist/coordination/transport.d.ts +0 -2
  343. package/dist/storage/session-writer/session-writer-summary-tracker.d.ts +0 -28
@@ -0,0 +1,1199 @@
1
+ import {
2
+ isPidAlive
3
+ } from "./chunk-TRT2HRWZ.js";
4
+ import {
5
+ withSqliteExperimentalWarningSuppressed
6
+ } from "./chunk-LX5QWLBL.js";
7
+
8
+ // src/chronicle/sqlite-compaction.ts
9
+ import { existsSync, readFileSync, statSync } from "node:fs";
10
+ import { loadRuntimeDatabaseSync } from "@wrongstack/persistence";
11
+ var ChronicleCompactionBusyError = class extends Error {
12
+ constructor(pid) {
13
+ super(`Chronicle project server is still running (pid ${pid}); stop it before compacting`);
14
+ this.name = "ChronicleCompactionBusyError";
15
+ }
16
+ };
17
+ function chronicleSqliteAllocatedBytes(dbPath) {
18
+ return [dbPath, `${dbPath}-wal`, `${dbPath}-shm`].reduce((total, file) => {
19
+ try {
20
+ return total + statSync(file).size;
21
+ } catch (error) {
22
+ if (error.code === "ENOENT") return total;
23
+ throw error;
24
+ }
25
+ }, 0);
26
+ }
27
+ function compactChronicleSqlite(options) {
28
+ assertProjectServerStopped(options.endpointMetadataPath);
29
+ const beforeBytes = chronicleSqliteAllocatedBytes(options.dbPath);
30
+ if (!existsSync(options.dbPath)) {
31
+ return { beforeBytes, afterBytes: beforeBytes, reclaimedBytes: 0 };
32
+ }
33
+ const Database = withSqliteExperimentalWarningSuppressed(loadRuntimeDatabaseSync);
34
+ const db = new Database(options.dbPath);
35
+ try {
36
+ db.exec("PRAGMA busy_timeout = 1");
37
+ db.exec("PRAGMA wal_checkpoint(TRUNCATE)");
38
+ db.exec("VACUUM");
39
+ db.exec("PRAGMA wal_checkpoint(TRUNCATE)");
40
+ } finally {
41
+ db.close();
42
+ }
43
+ const afterBytes = chronicleSqliteAllocatedBytes(options.dbPath);
44
+ return {
45
+ beforeBytes,
46
+ afterBytes,
47
+ reclaimedBytes: Math.max(0, beforeBytes - afterBytes)
48
+ };
49
+ }
50
+ function assertProjectServerStopped(endpointMetadataPath) {
51
+ if (!endpointMetadataPath || !existsSync(endpointMetadataPath)) return;
52
+ try {
53
+ const metadata = JSON.parse(readFileSync(endpointMetadataPath, "utf8"));
54
+ if (typeof metadata.pid === "number" && isPidAlive(metadata.pid)) {
55
+ throw new ChronicleCompactionBusyError(metadata.pid);
56
+ }
57
+ } catch (error) {
58
+ if (error instanceof ChronicleCompactionBusyError) throw error;
59
+ }
60
+ }
61
+
62
+ // src/chronicle/provider-adapter.ts
63
+ function wireProviderAttemptsToChronicle(options) {
64
+ const seenToolManifests = /* @__PURE__ */ new Set();
65
+ const unsubs = [
66
+ options.events.on("provider.attempt.started", (event) => persist(options, event, {
67
+ eventType: "provider.attempt.started",
68
+ outcome: "started",
69
+ occurredAt: event.startedAt
70
+ }, seenToolManifests)),
71
+ options.events.on("provider.attempt.completed", (event) => persist(options, event, {
72
+ eventType: "provider.attempt.completed",
73
+ outcome: "success",
74
+ occurredAt: event.endedAt,
75
+ durationNs: millisecondsToNanoseconds(event.durationMs)
76
+ })),
77
+ options.events.on("provider.attempt.failed", (event) => persist(options, event, {
78
+ eventType: "provider.attempt.failed",
79
+ outcome: "failure",
80
+ occurredAt: event.endedAt,
81
+ durationNs: millisecondsToNanoseconds(event.durationMs)
82
+ }))
83
+ ];
84
+ return () => unsubs.forEach((unsubscribe) => {
85
+ unsubscribe();
86
+ });
87
+ }
88
+ function persist(options, event, base, seenToolManifests) {
89
+ const context = typeof options.context === "function" ? options.context() : options.context;
90
+ const input = {
91
+ ...base,
92
+ scope: {
93
+ ...context.scope,
94
+ sessionId: event.sessionId,
95
+ ...event.agentId ? { agentId: event.agentId } : {},
96
+ ...event.taskId ? { taskId: event.taskId } : {},
97
+ ...event.boardId ? { kanbanBoardId: event.boardId } : {}
98
+ },
99
+ correlation: {
100
+ ...context.correlation,
101
+ ...event.traceId ? { traceId: event.traceId } : {},
102
+ logicalRequestId: event.logicalRequestId,
103
+ ...event.promptManifestId ? { promptManifestId: event.promptManifestId } : {},
104
+ attemptId: event.attemptId
105
+ },
106
+ runtime: { providerId: event.providerId, modelId: event.model },
107
+ attributes: providerAttributes(event, seenToolManifests)
108
+ };
109
+ void options.journal.append(input).catch((error) => options.onPersistError?.(error, input));
110
+ }
111
+ function providerAttributes(event, seenToolManifests) {
112
+ const {
113
+ sessionId: _sessionId,
114
+ traceId: _traceId,
115
+ agentId: _agentId,
116
+ providerId: _providerId,
117
+ model: _model,
118
+ logicalRequestId: _logicalRequestId,
119
+ promptManifestId: _promptManifestId,
120
+ attemptId: _attemptId,
121
+ ...rest
122
+ } = event;
123
+ const attributes = rest;
124
+ if (seenToolManifests && isManifest(attributes["promptManifest"])) {
125
+ attributes["promptManifest"] = compactManifest(attributes["promptManifest"], seenToolManifests);
126
+ }
127
+ return attributes;
128
+ }
129
+ var MANIFEST_MESSAGE_TAIL = 8;
130
+ var SEEN_TOOL_MANIFEST_CAP = 256;
131
+ function isManifest(value) {
132
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
133
+ }
134
+ function compactManifest(manifest, seenToolManifests) {
135
+ const compacted = { ...manifest };
136
+ const tools = compacted["tools"];
137
+ if (isManifest(tools) && typeof tools["manifestHash"] === "string") {
138
+ const manifestHash = tools["manifestHash"];
139
+ if (seenToolManifests.has(manifestHash)) {
140
+ const { names: _names, ...toolsWithoutNames } = tools;
141
+ compacted["tools"] = { ...toolsWithoutNames, namesRef: manifestHash };
142
+ } else {
143
+ if (seenToolManifests.size >= SEEN_TOOL_MANIFEST_CAP) seenToolManifests.clear();
144
+ seenToolManifests.add(manifestHash);
145
+ }
146
+ }
147
+ const messages = compacted["messages"];
148
+ if (Array.isArray(messages) && messages.length > MANIFEST_MESSAGE_TAIL) {
149
+ compacted["messages"] = messages.slice(-MANIFEST_MESSAGE_TAIL);
150
+ compacted["messagesTruncated"] = messages.length - MANIFEST_MESSAGE_TAIL;
151
+ }
152
+ return compacted;
153
+ }
154
+ function millisecondsToNanoseconds(durationMs) {
155
+ return Math.round(durationMs * 1e6).toString();
156
+ }
157
+
158
+ // src/chronicle/tool-adapter.ts
159
+ import { createHash } from "node:crypto";
160
+ var PREVIEW_MAX_BYTES = 2048;
161
+ function wireToolsToChronicle(options) {
162
+ const unsubs = [
163
+ options.events.on("tool.started", (event) => {
164
+ const input = scrubValue(options.scrubber, event.input);
165
+ persist2(options, event, {
166
+ eventType: "tool.started",
167
+ outcome: "started",
168
+ attributes: {
169
+ toolName: event.name,
170
+ input: capPreview(input),
171
+ inputHash: hashText(input),
172
+ inputBytes: Buffer.byteLength(input)
173
+ }
174
+ });
175
+ }),
176
+ options.events.on("permission.evaluated", (event) => {
177
+ persist2(options, event, {
178
+ eventType: "permission.evaluated",
179
+ outcome: event.effectiveDecision === "deny" ? "denied" : "success",
180
+ attributes: {
181
+ toolName: event.name,
182
+ inputHash: event.inputHash,
183
+ policyDecision: event.policyDecision,
184
+ effectiveDecision: event.effectiveDecision,
185
+ decisionSource: event.decisionSource,
186
+ reason: event.reason ? options.scrubber.scrub(event.reason) : void 0,
187
+ riskTier: event.riskTier,
188
+ yoloEnabled: event.yoloEnabled,
189
+ boundaryDecision: event.boundaryDecision,
190
+ boundaryReason: event.boundaryReason ? options.scrubber.scrub(event.boundaryReason) : void 0,
191
+ capabilityDowngraded: event.capabilityDowngraded
192
+ }
193
+ });
194
+ }),
195
+ options.events.on("tool.executed", (event) => {
196
+ const output = options.scrubber.scrub(event.output ?? "");
197
+ persist2(options, event, {
198
+ eventType: "tool.executed",
199
+ outcome: event.ok ? "success" : "failure",
200
+ durationNs: millisecondsToNanoseconds2(event.durationMs),
201
+ attributes: {
202
+ toolName: event.name,
203
+ ok: event.ok,
204
+ outputPreview: capPreview(output),
205
+ outputHash: hashText(output),
206
+ outputBytes: event.outputBytes,
207
+ outputTokens: event.outputTokens,
208
+ outputLines: event.outputLines,
209
+ metadata: event.metadata
210
+ }
211
+ });
212
+ }),
213
+ options.events.on("tool.failed", (event) => persist2(options, event, {
214
+ eventType: "tool.failed",
215
+ outcome: "failure",
216
+ durationNs: millisecondsToNanoseconds2(event.durationMs),
217
+ attributes: {
218
+ toolName: event.name,
219
+ category: event.category,
220
+ retryable: event.retryable,
221
+ detail: event.detail,
222
+ errorCode: event.errorCode,
223
+ errorSubsystem: event.errorSubsystem,
224
+ errorSeverity: event.errorSeverity
225
+ }
226
+ })),
227
+ options.events.on("tool.progress", (event) => {
228
+ if (event.event.type !== "file_changed") return;
229
+ const resource = progressResource(event);
230
+ persist2(options, event, {
231
+ eventType: "file.mutation.observed",
232
+ outcome: "started",
233
+ ...resource ? { resource } : {},
234
+ attributes: {
235
+ toolName: event.name,
236
+ progressType: event.event.type,
237
+ text: capPreview(options.scrubber.scrub(event.event.text ?? "")),
238
+ data: capPreview(scrubValue(options.scrubber, event.event.data)),
239
+ operation: event.event.operation
240
+ }
241
+ });
242
+ })
243
+ ];
244
+ return () => unsubs.forEach((unsubscribe) => {
245
+ unsubscribe();
246
+ });
247
+ }
248
+ function persist2(options, event, fields) {
249
+ const context = typeof options.context === "function" ? options.context() : options.context;
250
+ const input = {
251
+ ...fields,
252
+ scope: {
253
+ ...context.scope,
254
+ ...event.sessionId ? { sessionId: event.sessionId } : {},
255
+ ...event.agentId ? { agentId: event.agentId } : {},
256
+ ...event.taskId ? { taskId: event.taskId } : {},
257
+ ...event.boardId ? { kanbanBoardId: event.boardId } : {}
258
+ },
259
+ correlation: {
260
+ ...context.correlation,
261
+ ...event.traceId ? { traceId: event.traceId } : {},
262
+ ...event.logicalRequestId ? { logicalRequestId: event.logicalRequestId } : {},
263
+ ...event.promptManifestId ? { promptManifestId: event.promptManifestId } : {},
264
+ ...event.id ? { toolCallId: event.id } : {}
265
+ },
266
+ ...event.provider || event.model ? {
267
+ runtime: {
268
+ ...event.provider ? { providerId: event.provider } : {},
269
+ ...event.model ? { modelId: event.model } : {}
270
+ }
271
+ } : {}
272
+ };
273
+ void options.journal.append(input).catch((error) => options.onPersistError?.(error, input));
274
+ }
275
+ function progressResource(event) {
276
+ if (event.event.type !== "file_changed" || !event.event.path) return void 0;
277
+ return {
278
+ kind: "file",
279
+ id: resourceId("file", event.event.path),
280
+ path: event.event.path,
281
+ ...event.event.line !== void 0 ? { lineStart: event.event.line } : {},
282
+ ...event.event.endLine !== void 0 ? { lineEnd: event.event.endLine } : {}
283
+ };
284
+ }
285
+ function scrubValue(scrubber, value) {
286
+ if (value === void 0) return "";
287
+ try {
288
+ return scrubber.scrub(JSON.stringify(value));
289
+ } catch {
290
+ return scrubber.scrub(String(value));
291
+ }
292
+ }
293
+ function resourceId(kind, value) {
294
+ return `${kind}_${hashText(value).slice(0, 24)}`;
295
+ }
296
+ function hashText(value) {
297
+ return createHash("sha256").update(value).digest("hex");
298
+ }
299
+ function capPreview(value) {
300
+ if (value.length <= PREVIEW_MAX_BYTES) {
301
+ if (Buffer.byteLength(value, "utf8") <= PREVIEW_MAX_BYTES) return value;
302
+ }
303
+ const buf = Buffer.from(value, "utf8");
304
+ if (buf.length <= PREVIEW_MAX_BYTES) return value;
305
+ let end = PREVIEW_MAX_BYTES;
306
+ while (end > 0 && (buf[end] & 192) === 128) end--;
307
+ return { preview: buf.subarray(0, end).toString("utf8"), truncated: true, totalBytes: buf.length };
308
+ }
309
+ function millisecondsToNanoseconds2(durationMs) {
310
+ return Math.round(durationMs * 1e6).toString();
311
+ }
312
+
313
+ // src/chronicle/process-adapter.ts
314
+ import { createHash as createHash2 } from "node:crypto";
315
+ function wireProcessesToChronicle(options) {
316
+ const unsubs = [
317
+ options.events.on("process.started", (event) => persist3(options, event, {
318
+ eventType: "process.started",
319
+ outcome: "started",
320
+ occurredAt: event.startedAt,
321
+ attributes: {
322
+ command: options.scrubber.scrub(event.command),
323
+ args: event.args.map((arg) => options.scrubber.scrub(arg)),
324
+ cwd: event.cwd,
325
+ parentPid: event.parentPid,
326
+ background: event.background
327
+ }
328
+ })),
329
+ options.events.on("process.completed", (event) => persist3(options, event, {
330
+ eventType: "process.completed",
331
+ outcome: event.exitCode === 0 ? "success" : event.timedOut ? "cancelled" : "failure",
332
+ occurredAt: event.endedAt,
333
+ durationNs: Math.round(event.durationMs * 1e6).toString(),
334
+ attributes: {
335
+ exitCode: event.exitCode,
336
+ signal: event.signal,
337
+ stdoutBytes: event.stdoutBytes,
338
+ stderrBytes: event.stderrBytes,
339
+ timedOut: event.timedOut
340
+ }
341
+ }))
342
+ ];
343
+ return () => unsubs.forEach((unsubscribe) => {
344
+ unsubscribe();
345
+ });
346
+ }
347
+ function persist3(options, event, fields) {
348
+ const context = typeof options.context === "function" ? options.context() : options.context;
349
+ const processKey = `${event.sessionId}\0${event.pid ?? "unknown"}\0${event.toolCallId}`;
350
+ const input = {
351
+ ...fields,
352
+ scope: {
353
+ ...context.scope,
354
+ sessionId: event.sessionId,
355
+ ...event.agentId ? { agentId: event.agentId } : {}
356
+ },
357
+ correlation: {
358
+ ...context.correlation,
359
+ ...event.traceId ? { traceId: event.traceId } : {},
360
+ toolCallId: event.toolCallId
361
+ },
362
+ runtime: {
363
+ ...event.pid !== void 0 ? { processId: event.pid } : {},
364
+ ..."parentPid" in event ? { parentProcessId: event.parentPid } : {}
365
+ },
366
+ resource: {
367
+ kind: "process",
368
+ id: `process_${createHash2("sha256").update(processKey).digest("hex").slice(0, 24)}`
369
+ }
370
+ };
371
+ void options.journal.append(input).catch((error) => options.onPersistError?.(error, input));
372
+ }
373
+
374
+ // src/chronicle/health-monitor.ts
375
+ import { monitorEventLoopDelay, performance } from "node:perf_hooks";
376
+ function startChronicleHealthMonitor(options) {
377
+ const intervalMs = Math.max(5e3, options.intervalMs ?? 3e4);
378
+ const delay = monitorEventLoopDelay({ resolution: 20 });
379
+ delay.enable();
380
+ let previousCpu = process.cpuUsage();
381
+ let previousElu = performance.eventLoopUtilization();
382
+ const sample = () => {
383
+ const context = typeof options.context === "function" ? options.context() : options.context;
384
+ const memory = process.memoryUsage();
385
+ const cpu = process.cpuUsage(previousCpu);
386
+ previousCpu = process.cpuUsage();
387
+ const elu = performance.eventLoopUtilization(previousElu);
388
+ previousElu = performance.eventLoopUtilization();
389
+ const journalBeforeSample = options.journal.stats();
390
+ try {
391
+ options.events.emit("runtime.health.sampled", {
392
+ sessionId: context.scope.sessionId,
393
+ uptimeSeconds: process.uptime(),
394
+ eventLoop: {
395
+ utilization: elu.utilization,
396
+ activeMs: elu.active,
397
+ idleMs: elu.idle,
398
+ delayMeanMs: Number(delay.mean) / 1e6,
399
+ delayP95Ms: Number(delay.percentile(95)) / 1e6,
400
+ delayMaxMs: Number(delay.max) / 1e6
401
+ },
402
+ cpu: { userMicros: cpu.user, systemMicros: cpu.system },
403
+ memory: {
404
+ rssBytes: memory.rss,
405
+ heapTotalBytes: memory.heapTotal,
406
+ heapUsedBytes: memory.heapUsed,
407
+ externalBytes: memory.external,
408
+ arrayBuffersBytes: memory.arrayBuffers
409
+ },
410
+ chronicle: journalBeforeSample
411
+ });
412
+ } catch (error) {
413
+ options.onPersistError?.(error);
414
+ }
415
+ delay.reset();
416
+ };
417
+ const timer = setInterval(sample, intervalMs);
418
+ timer.unref?.();
419
+ return () => {
420
+ clearInterval(timer);
421
+ delay.disable();
422
+ };
423
+ }
424
+
425
+ // src/chronicle/decision-adapter.ts
426
+ import { createHash as createHash3 } from "node:crypto";
427
+ function wireDecisionsToChronicle(options) {
428
+ const write = (eventType, at, sessionId, requestId, attributes, outcome) => {
429
+ const context = typeof options.context === "function" ? options.context() : options.context;
430
+ const input = {
431
+ eventType,
432
+ occurredAt: new Date(at).toISOString(),
433
+ outcome,
434
+ scope: { ...context.scope, ...sessionId ? { sessionId } : {} },
435
+ correlation: context.correlation,
436
+ resource: { kind: "other", id: `decision:${requestId}` },
437
+ attributes: { decisionId: requestId, ...attributes }
438
+ };
439
+ void options.journal.append(input).catch((error) => options.onPersistError?.(error, input));
440
+ };
441
+ const requestAttrs = (request) => ({
442
+ source: request.source,
443
+ risk: request.risk,
444
+ fallback: request.fallback,
445
+ questionHash: hash(request.question),
446
+ contextHash: hash(request.context),
447
+ optionCount: request.options?.length ?? 0,
448
+ options: request.options?.map((option) => ({
449
+ id: option.id,
450
+ risk: option.risk,
451
+ recommended: option.recommended ?? false,
452
+ labelHash: hash(option.label),
453
+ consequenceHash: hash(option.consequence)
454
+ }))
455
+ });
456
+ const decisionAttrs = (decision) => ({
457
+ type: decision.type,
458
+ ..."optionId" in decision && decision.optionId ? { optionId: decision.optionId } : {},
459
+ contentHash: hash("text" in decision ? decision.text : "prompt" in decision ? decision.prompt : decision.reason),
460
+ rationaleHash: hash("rationale" in decision ? decision.rationale : void 0)
461
+ });
462
+ const offs = [
463
+ options.events.on("brain.decision_requested", (e) => write("decision.requested", e.at, e.sessionId, e.request.id, requestAttrs(e.request), "started")),
464
+ options.events.on("brain.decision_answered", (e) => write("decision.resolved", e.at, e.sessionId, e.request.id, { ...requestAttrs(e.request), ...decisionAttrs(e.decision), resolver: "brain" }, "success")),
465
+ options.events.on("brain.decision_ask_human", (e) => write("decision.escalated", e.at, e.sessionId, e.request.id, { ...requestAttrs(e.request), ...decisionAttrs(e.decision) }, "started")),
466
+ options.events.on("brain.decision_denied", (e) => write("decision.denied", e.at, e.sessionId, e.request.id, { ...requestAttrs(e.request), ...decisionAttrs(e.decision) }, "denied")),
467
+ options.events.on("brain.human_answered", (e) => write("decision.human_answered", e.at, e.sessionId, e.id, { resolver: "human", optionId: e.optionId, denied: e.deny ?? false, answerHash: hash(e.text) }, e.deny ? "denied" : "success")),
468
+ options.events.on("brain.outcome", (e) => write("decision.outcome_observed", e.at, e.sessionId, e.requestId, { observedOutcome: e.outcome, detailHash: hash(e.detail) }, e.outcome))
469
+ ];
470
+ return () => offs.forEach((off) => {
471
+ off();
472
+ });
473
+ }
474
+ function hash(value) {
475
+ return value ? createHash3("sha256").update(value).digest("hex") : void 0;
476
+ }
477
+
478
+ // src/chronicle/domain-adapter.ts
479
+ import { createHash as createHash4 } from "node:crypto";
480
+ var SPECIALIZED_RE = /^(?:provider\.attempt\.|tool\.|process\.|brain\.decision_|brain\.human_answered$|brain\.outcome$|file\.activity$|provider\.(?:text_delta|thinking_delta)$|ctx\.pct$|subagent\.ctx_pct$|countdown\.tick$|coordinator\.stats$|session\.agents_updated$|network\.request\.(?:started|completed)$|runtime\.health\.sampled$|provider\.tool_use_(?:start|stop)$)/;
481
+ var CODING_SIGNAL_RE = /^(?:(?:agent|subagent|delegate|fleet|session|iteration|context|compaction|checkpoint|in_flight|memory|storage|trust|sdd|worktree|kanban|brain|token|budget|concurrency|provider|mcp|network)\.|file\.event$|error$)/;
482
+ var SENSITIVE_KEY = /(content|text|prompt|question|rationale|reason|detail|summary|description|context|input|output|error|message|secret|token|password|key)$/i;
483
+ var PRESERVE_STRING_KEY = /(^|_)(id|status|state|kind|type|source|model|provider|phase|risk|fallback|path|name|role|sha|branch|mode)$/i;
484
+ var TRUNCATED_ARRAYS = /* @__PURE__ */ new Set([
485
+ "recentMail",
486
+ "recentTools",
487
+ "recentCommands",
488
+ "activated",
489
+ "injected",
490
+ // SAGE per-memory rejection evidence — same cap (5) as activated/injected
491
+ // so the journal stays bounded under burst conditions. Each entry is
492
+ // ~120 bytes serialized; cap × entry-count = ~600B per injector_run.
493
+ "rejectedDetail"
494
+ ]);
495
+ var TRUNCATED_ARRAY_MAX = 5;
496
+ var DEFAULT_ARRAY_MAX = 20;
497
+ function wireDomainEventsToChronicle(options) {
498
+ return options.events.onAny((eventName, payload) => {
499
+ if (SPECIALIZED_RE.test(eventName)) return;
500
+ if (!CODING_SIGNAL_RE.test(eventName)) return;
501
+ const record = eventName === "memory.injector_run" ? dedupInjectorTrace(objectPayload(payload)) : objectPayload(payload);
502
+ if (eventName === "file.event" && record.operation === "read") return;
503
+ const context = typeof options.context === "function" ? options.context() : options.context;
504
+ const sessionId = stringField(record, "sessionId");
505
+ const agentId = stringField(record, "agentId") ?? stringField(record, "subagentId");
506
+ const taskId = stringField(record, "taskId");
507
+ const kanbanBoardId = stringField(record, "kanbanBoardId") ?? stringField(record, "boardId");
508
+ const input = {
509
+ eventType: eventName,
510
+ occurredAt: eventTime(record),
511
+ scope: {
512
+ ...context.scope,
513
+ ...sessionId ? { sessionId } : {},
514
+ ...agentId ? { agentId } : {},
515
+ ...taskId ? { taskId } : {},
516
+ ...kanbanBoardId ? { kanbanBoardId } : {}
517
+ },
518
+ correlation: {
519
+ ...context.correlation,
520
+ ...stringField(record, "traceId") ? { traceId: stringField(record, "traceId") } : {},
521
+ ...stringField(record, "toolCallId") ? { toolCallId: stringField(record, "toolCallId") } : {},
522
+ ...stringField(record, "attemptId") ? { attemptId: stringField(record, "attemptId") } : {},
523
+ ...stringField(record, "logicalRequestId") ? { logicalRequestId: stringField(record, "logicalRequestId") } : {},
524
+ ...stringField(record, "promptManifestId") ? { promptManifestId: stringField(record, "promptManifestId") } : {}
525
+ },
526
+ outcome: inferOutcome(eventName, record),
527
+ runtime: {
528
+ ...stringField(record, "providerId") ?? stringField(record, "provider") ? { providerId: stringField(record, "providerId") ?? stringField(record, "provider") } : {},
529
+ ...stringField(record, "modelId") ?? stringField(record, "model") ? { modelId: stringField(record, "modelId") ?? stringField(record, "model") } : {}
530
+ },
531
+ resource: inferResource(record, eventName),
532
+ attributes: sanitize(record),
533
+ tags: { collector: "eventbus-domain", family: eventName.split(".")[0] ?? "unknown" }
534
+ };
535
+ void options.journal.append(input).catch((error) => options.onPersistError?.(error, input));
536
+ });
537
+ }
538
+ function objectPayload(value) {
539
+ return value && typeof value === "object" ? value : { value };
540
+ }
541
+ function dedupInjectorTrace(record) {
542
+ const activated = Array.isArray(record.activated) ? record.activated : [];
543
+ const injected = Array.isArray(record.injected) ? record.injected : [];
544
+ const activatedIds = new Set(
545
+ activated.map((item) => item && typeof item === "object" ? item.id : void 0).filter((id) => typeof id === "string")
546
+ );
547
+ return {
548
+ ...record,
549
+ injected: injected.map((item) => {
550
+ const id = item && typeof item === "object" ? item.id : void 0;
551
+ return typeof id === "string" && activatedIds.has(id) ? { id, ref: "activated" } : item;
552
+ })
553
+ };
554
+ }
555
+ function stringField(value, key) {
556
+ return typeof value[key] === "string" ? value[key] : void 0;
557
+ }
558
+ function eventTime(value) {
559
+ const raw = value.at ?? value.ts ?? value.timestamp;
560
+ if (typeof raw === "number" && Number.isFinite(raw)) return new Date(raw).toISOString();
561
+ if (typeof raw === "string" && Number.isFinite(Date.parse(raw)))
562
+ return new Date(raw).toISOString();
563
+ return void 0;
564
+ }
565
+ function inferOutcome(name, payload) {
566
+ if (payload.ok === false || /(?:failed|error|damaged|conflict|deadlock|denied|rejected|blocked)$/.test(name))
567
+ return "failure";
568
+ if (/(?:started|starting|retrying|threshold_reached)$/.test(name)) return "started";
569
+ if (/(?:cancelled|aborted)$/.test(name)) return "cancelled";
570
+ if (/(?:completed|finished|committed|merged|written|persisted|accepted|recovered|verified|connected|success)$/.test(
571
+ name
572
+ ) || payload.ok === true)
573
+ return "success";
574
+ return "unknown";
575
+ }
576
+ function inferResource(payload, eventName) {
577
+ if (eventName === "file.event" && typeof payload.filePath === "string" && payload.filePath.length > 0) {
578
+ return { kind: "file", id: `path:${payload.filePath}`, path: payload.filePath };
579
+ }
580
+ const candidates = [
581
+ ["memory", "memoryId", payload.memoryId],
582
+ ["task", "taskId", payload.taskId],
583
+ ["kanban", "boardId", payload.boardId ?? payload.runId],
584
+ ["artifact", "worktreeId", payload.worktreeId ?? payload.handleId],
585
+ ["file", "path", payload.filePath ?? payload.path],
586
+ ["other", "agentId", payload.agentId ?? payload.subagentId],
587
+ ["network", "serverAddress", payload.serverAddress],
588
+ ["other", "sessionId", payload.sessionId]
589
+ ];
590
+ const found = candidates.find(([, , value2]) => typeof value2 === "string" && value2.length > 0);
591
+ if (!found) return void 0;
592
+ const [kind, label, value] = found;
593
+ return { kind, id: `${label}:${value}`, ...kind === "file" ? { path: value } : {} };
594
+ }
595
+ function sanitize(value, key = "", depth = 0, seen = /* @__PURE__ */ new WeakSet()) {
596
+ if (value === null || typeof value === "boolean" || typeof value === "number") return value;
597
+ if (typeof value === "bigint") return value.toString();
598
+ if (typeof value === "function") return { type: "function" };
599
+ if (typeof value === "string") {
600
+ if (PRESERVE_STRING_KEY.test(key) && !SENSITIVE_KEY.test(key)) return value.slice(0, 512);
601
+ if (SENSITIVE_KEY.test(key))
602
+ return { hash: digest(value), length: value.length, redacted: true };
603
+ return value.length <= 256 ? value : { hash: digest(value), length: value.length, truncated: true };
604
+ }
605
+ if (typeof value !== "object") return String(value);
606
+ if (seen.has(value)) return { circular: true };
607
+ if (depth >= 5) return { hash: digest(safeString(value)), depthLimited: true };
608
+ seen.add(value);
609
+ if (Array.isArray(value)) {
610
+ const cap = TRUNCATED_ARRAYS.has(key) ? TRUNCATED_ARRAY_MAX : DEFAULT_ARRAY_MAX;
611
+ const items = value.slice(0, cap).map((item) => sanitize(item, key, depth + 1, seen));
612
+ return value.length > cap ? { items, total: value.length, truncated: true } : items;
613
+ }
614
+ const output = {};
615
+ const entries = Object.entries(value);
616
+ for (const [childKey, child] of entries.slice(0, 100)) {
617
+ if (childKey === "ctx" || childKey === "provider" || childKey === "resolve" || childKey === "extend" || childKey === "deny")
618
+ continue;
619
+ output[childKey] = sanitize(child, childKey, depth + 1, seen);
620
+ }
621
+ if (entries.length > 100) output._truncatedKeys = entries.length - 100;
622
+ return output;
623
+ }
624
+ function safeString(value) {
625
+ try {
626
+ return JSON.stringify(value) ?? String(value);
627
+ } catch {
628
+ return String(value);
629
+ }
630
+ }
631
+ function digest(value) {
632
+ return createHash4("sha256").update(value).digest("hex");
633
+ }
634
+
635
+ // src/chronicle/stream-adapter.ts
636
+ import { createHash as createHash5 } from "node:crypto";
637
+ var MAX_STATE_AGE_MS = 3e5;
638
+ var STALE_STATE_SWEEP_INTERVAL_MS = Math.round(MAX_STATE_AGE_MS / 6);
639
+ function wireProviderStreamsToChronicle(options) {
640
+ const states = /* @__PURE__ */ new Map();
641
+ const key = (sessionId, agentId) => `${sessionId ?? "__default__"}\0${agentId ?? "__leader__"}`;
642
+ const update = (sessionId, agentId, text2, thinking) => {
643
+ const now = Date.now();
644
+ sweepStaleStates(states, flush, now);
645
+ const k = key(sessionId, agentId);
646
+ const state = states.get(k);
647
+ if (!state) return;
648
+ const bytes = Buffer.byteLength(text2);
649
+ state.firstChunkAtMs ??= now;
650
+ state.lastChunkAtMs = now;
651
+ if (thinking) {
652
+ state.thinkingChunks++;
653
+ state.thinkingBytes += bytes;
654
+ state.thinkingHash.update(text2);
655
+ } else {
656
+ state.textChunks++;
657
+ state.textBytes += bytes;
658
+ state.textHash.update(text2);
659
+ }
660
+ };
661
+ const flush = (sessionId, agentId, outcome) => {
662
+ const state = states.get(key(sessionId, agentId));
663
+ if (!state) return;
664
+ states.delete(key(sessionId, agentId));
665
+ const context = typeof options.context === "function" ? options.context() : options.context;
666
+ const endedAtMs = Date.now();
667
+ const input = {
668
+ eventType: "provider.stream.summarized",
669
+ outcome,
670
+ scope: { ...context.scope, ...state.sessionId ? { sessionId: state.sessionId } : {}, ...state.agentId ? { agentId: state.agentId } : {} },
671
+ correlation: { ...context.correlation, attemptId: state.attemptId, logicalRequestId: state.logicalRequestId },
672
+ runtime: { providerId: state.providerId, modelId: state.model },
673
+ durationNs: String(Math.max(0, endedAtMs - state.startedAtMs) * 1e6),
674
+ attributes: {
675
+ textChunks: state.textChunks,
676
+ textBytes: state.textBytes,
677
+ thinkingChunks: state.thinkingChunks,
678
+ thinkingBytes: state.thinkingBytes,
679
+ textHash: state.textHash.digest("hex"),
680
+ thinkingHash: state.thinkingHash.digest("hex"),
681
+ firstChunkLatencyMs: state.firstChunkAtMs === void 0 ? void 0 : state.firstChunkAtMs - state.startedAtMs,
682
+ streamActiveMs: state.firstChunkAtMs === void 0 || state.lastChunkAtMs === void 0 ? 0 : state.lastChunkAtMs - state.firstChunkAtMs
683
+ }
684
+ };
685
+ void options.journal.append(input).catch((error) => options.onPersistError?.(error, input));
686
+ };
687
+ const offs = [
688
+ options.events.on("provider.attempt.started", (event) => states.set(key(event.sessionId, event.agentId), {
689
+ sessionId: event.sessionId,
690
+ ...event.agentId ? { agentId: event.agentId } : {},
691
+ attemptId: event.attemptId,
692
+ logicalRequestId: event.logicalRequestId,
693
+ providerId: event.providerId,
694
+ model: event.model,
695
+ startedAtMs: Date.parse(event.startedAt),
696
+ textChunks: 0,
697
+ textBytes: 0,
698
+ thinkingChunks: 0,
699
+ thinkingBytes: 0,
700
+ textHash: createHash5("sha256"),
701
+ thinkingHash: createHash5("sha256")
702
+ })),
703
+ options.events.on("provider.text_delta", (event) => update(event.sessionId, event.ctx.agentId, event.text, false)),
704
+ options.events.on("provider.thinking_delta", (event) => update(event.sessionId, event.ctx.agentId, event.text, true)),
705
+ options.events.on("provider.attempt.completed", (event) => flush(event.sessionId, event.agentId, "success")),
706
+ options.events.on("provider.attempt.failed", (event) => flush(event.sessionId, event.agentId, "failure"))
707
+ ];
708
+ const reaperTimer = setInterval(
709
+ () => sweepStaleStates(states, flush, Date.now()),
710
+ STALE_STATE_SWEEP_INTERVAL_MS
711
+ );
712
+ if (typeof reaperTimer.unref === "function") reaperTimer.unref();
713
+ return () => {
714
+ clearInterval(reaperTimer);
715
+ for (const state of [...states.values()]) flush(state.sessionId, state.agentId, "failure");
716
+ offs.forEach((off) => {
717
+ off();
718
+ });
719
+ };
720
+ }
721
+ function sweepStaleStates(states, flushFn, now) {
722
+ if (states.size === 0) return;
723
+ for (const s of states.values()) {
724
+ if (now - s.startedAtMs > MAX_STATE_AGE_MS) {
725
+ const sid = s.sessionId;
726
+ const aid = s.agentId;
727
+ flushFn(sid, aid, "failure");
728
+ }
729
+ }
730
+ }
731
+
732
+ // src/chronicle/review-adapter.ts
733
+ import { createHash as createHash6, randomUUID } from "node:crypto";
734
+ function wireReviewFindingsToChronicle(options) {
735
+ const unsubscribe = options.events.onPattern(
736
+ "chimera.review_complete",
737
+ (_event, raw) => {
738
+ const payload = raw;
739
+ if (!payload?.reviewText) return;
740
+ if (payload.status !== "success") return;
741
+ const context = typeof options.context === "function" ? options.context() : options.context;
742
+ const sessionId = payload.sessionId ?? payload.bundle?.cwd;
743
+ const agentId = payload.bundle?.fileProvenance?.find((e) => e.agentId)?.agentId;
744
+ const taskId = payload.bundle?.kanbanCard?.id;
745
+ const provider = payload.bundle?.config?.provider;
746
+ const model = payload.bundle?.config?.model;
747
+ const cascadeDepth = payload.bundle?.cascadeDepth ?? 0;
748
+ const now = (/* @__PURE__ */ new Date()).toISOString();
749
+ const findings = parseFindings(payload.reviewText);
750
+ for (const finding of findings) {
751
+ const eventId = randomUUID();
752
+ const input = {
753
+ eventType: `finding.${finding.severity}`,
754
+ occurredAt: now,
755
+ scope: {
756
+ ...context.scope,
757
+ ...sessionId ? { sessionId } : {},
758
+ ...agentId ? { agentId } : {},
759
+ ...taskId ? { taskId } : {}
760
+ },
761
+ correlation: context.correlation,
762
+ resource: finding.file ? {
763
+ kind: "file",
764
+ id: `finding:${finding.fingerprint}`,
765
+ path: finding.file,
766
+ ...finding.line !== void 0 ? { lineStart: finding.line } : {}
767
+ } : void 0,
768
+ outcome: "success",
769
+ attributes: {
770
+ findingId: eventId,
771
+ fingerprint: finding.fingerprint,
772
+ severity: finding.severity,
773
+ title: finding.title,
774
+ file: finding.file,
775
+ line: finding.line,
776
+ source: "chimera",
777
+ model,
778
+ provider,
779
+ cascadeDepth
780
+ },
781
+ tags: {
782
+ collector: "review-adapter",
783
+ family: "finding",
784
+ severity: finding.severity
785
+ }
786
+ };
787
+ options.journal.append(input).catch((error) => options.onPersistError?.(error, input));
788
+ }
789
+ if (findings.length === 0) return;
790
+ const summaryInput = {
791
+ eventType: "review.completed",
792
+ occurredAt: now,
793
+ scope: {
794
+ ...context.scope,
795
+ ...sessionId ? { sessionId } : {},
796
+ ...agentId ? { agentId } : {},
797
+ ...taskId ? { taskId } : {}
798
+ },
799
+ correlation: context.correlation,
800
+ outcome: "success",
801
+ attributes: {
802
+ totalFindings: findings.length,
803
+ severityCounts: aggregateSeverities(findings),
804
+ files: payload.bundle?.files?.map((f) => f.path),
805
+ model,
806
+ provider,
807
+ cascadeDepth,
808
+ status: payload.status
809
+ },
810
+ tags: {
811
+ collector: "review-adapter",
812
+ family: "review"
813
+ }
814
+ };
815
+ options.journal.append(summaryInput).catch((error) => options.onPersistError?.(error, summaryInput));
816
+ }
817
+ );
818
+ return unsubscribe;
819
+ }
820
+ var SEVERITY_HEADING = /^###\s+(critical|high|medium|low)\b/i;
821
+ var ITEM_CAPTURE = /^\d+\.\s+(.*)$/;
822
+ var TAG_PREFIX = /^\[(\w+)\]\s*/;
823
+ var FILE_REF = /^(.+?)(?::(\d+))?\s+[—–]\s*(.+)$/;
824
+ var PATH_REF = /^([a-zA-Z_./\\][a-zA-Z0-9_./\\-]*\.\w+)(?::(\d+))?/;
825
+ function parseFindings(reviewText) {
826
+ const findings = [];
827
+ let currentSeverity = null;
828
+ for (const rawLine of reviewText.split("\n")) {
829
+ const line = rawLine.trim();
830
+ if (!line) continue;
831
+ const heading = line.match(SEVERITY_HEADING);
832
+ if (heading) {
833
+ currentSeverity = heading[1].toLowerCase();
834
+ continue;
835
+ }
836
+ if (!currentSeverity) continue;
837
+ const item = line.match(ITEM_CAPTURE);
838
+ if (!item) continue;
839
+ let remaining = item[1].trim();
840
+ if (!remaining) continue;
841
+ const tag = remaining.match(TAG_PREFIX);
842
+ if (tag) remaining = remaining.slice(tag[0].length).trim();
843
+ const refMatch = remaining.match(FILE_REF);
844
+ let file;
845
+ let lineNum;
846
+ let desc;
847
+ if (refMatch) {
848
+ file = refMatch[1].trim();
849
+ lineNum = refMatch[2] !== void 0 ? Number.parseInt(refMatch[2], 10) : void 0;
850
+ desc = refMatch[3].trim();
851
+ } else {
852
+ const pathFallback = remaining.match(PATH_REF);
853
+ if (pathFallback) {
854
+ file = pathFallback[1].trim();
855
+ lineNum = pathFallback[2] !== void 0 ? Number.parseInt(pathFallback[2], 10) : void 0;
856
+ const afterFile = remaining.slice(pathFallback[0].length).trim();
857
+ desc = afterFile.replace(/^[—–-]\s*/, "").trim() || remaining;
858
+ } else {
859
+ desc = remaining;
860
+ }
861
+ }
862
+ if (file && !file.includes("/") && !file.includes("\\") && !file.includes(".")) {
863
+ file = void 0;
864
+ desc = remaining;
865
+ }
866
+ const title = desc.split(/\.\s/)[0].trim() || desc;
867
+ const fingerprint = computeFingerprint(file ?? "", lineNum ?? null, title);
868
+ findings.push({
869
+ severity: currentSeverity,
870
+ file,
871
+ line: lineNum,
872
+ title,
873
+ fingerprint
874
+ });
875
+ }
876
+ return findings;
877
+ }
878
+ function computeFingerprint(file, line, title) {
879
+ const normalizedFile = file.replace(/\\/g, "/").trim().toLowerCase();
880
+ const lineStr = line != null && line >= 0 ? String(line) : "0";
881
+ const normalizedTitle = title.trim().toLowerCase().replace(/[^\w\s]/g, "").replace(/\s+/g, " ").trim();
882
+ const hash2 = createHash6("sha256");
883
+ hash2.update(`${normalizedFile}:${lineStr}:${normalizedTitle}`);
884
+ return hash2.digest("hex");
885
+ }
886
+ function aggregateSeverities(findings) {
887
+ const counts = {
888
+ critical: 0,
889
+ high: 0,
890
+ medium: 0,
891
+ low: 0
892
+ };
893
+ for (const f of findings) {
894
+ const sev = f.severity;
895
+ if (sev in counts) counts[sev]++;
896
+ }
897
+ return counts;
898
+ }
899
+
900
+ // src/chronicle/rollup-adapter.ts
901
+ import { createHash as createHash7 } from "node:crypto";
902
+ var MAX_ROLLUP_RESOURCES = 100;
903
+ var DEFAULT_GAUGE_WINDOW_MS = 12e4;
904
+ function wireRollupsToChronicle(options) {
905
+ const buckets = /* @__PURE__ */ new Map();
906
+ const windowMs = Math.max(1e3, options.windowMs ?? 1e4);
907
+ const gaugeWindowMs = Math.max(windowMs, options.gaugeWindowMs ?? DEFAULT_GAUGE_WINDOW_MS);
908
+ const bucket = (key, seed) => {
909
+ let value = buckets.get(key);
910
+ if (!value) {
911
+ const now = Date.now();
912
+ value = {
913
+ ...seed,
914
+ startedAt: now,
915
+ updatedAt: now,
916
+ count: 0,
917
+ metrics: {},
918
+ categories: {},
919
+ digest: createHash7("sha256"),
920
+ resources: /* @__PURE__ */ new Map()
921
+ };
922
+ buckets.set(key, value);
923
+ }
924
+ return value;
925
+ };
926
+ const sample = (target, values, category, digest2) => {
927
+ target.count++;
928
+ target.updatedAt = Date.now();
929
+ for (const [name, value] of Object.entries(values)) {
930
+ const metric = target.metrics[name];
931
+ target.metrics[name] = metric ? {
932
+ sum: metric.sum + value,
933
+ min: Math.min(metric.min, value),
934
+ max: Math.max(metric.max, value),
935
+ last: value
936
+ } : { sum: value, min: value, max: value, last: value };
937
+ }
938
+ if (category) target.categories[category] = (target.categories[category] ?? 0) + 1;
939
+ if (digest2) target.digest.update(digest2);
940
+ };
941
+ const flush = (key) => {
942
+ const value = buckets.get(key);
943
+ if (!value || value.count === 0) return;
944
+ buckets.delete(key);
945
+ const context = typeof options.context === "function" ? options.context() : options.context;
946
+ const stats = Object.fromEntries(
947
+ Object.entries(value.metrics).map(([name, metric]) => [
948
+ name,
949
+ { ...metric, avg: metric.sum / value.count }
950
+ ])
951
+ );
952
+ const resources = value.resources.size > 0 ? [...value.resources].slice(0, MAX_ROLLUP_RESOURCES).map(([id, r]) => ({ id, kind: r.kind, ...r.path ? { path: r.path } : {} })) : void 0;
953
+ const input = {
954
+ eventType: "metrics.rollup",
955
+ outcome: "success",
956
+ occurredAt: new Date(value.updatedAt).toISOString(),
957
+ scope: {
958
+ ...context.scope,
959
+ ...value.sessionId ? { sessionId: value.sessionId } : {},
960
+ ...value.agentId ? { agentId: value.agentId } : {}
961
+ },
962
+ correlation: {
963
+ ...context.correlation,
964
+ ...value.toolCallId ? { toolCallId: value.toolCallId } : {}
965
+ },
966
+ durationNs: String(Math.max(0, value.updatedAt - value.startedAt) * 1e6),
967
+ attributes: {
968
+ signal: value.signal,
969
+ windowStart: new Date(value.startedAt).toISOString(),
970
+ windowEnd: new Date(value.updatedAt).toISOString(),
971
+ samples: value.count,
972
+ dimensions: value.dimensions,
973
+ stats,
974
+ categories: value.categories,
975
+ digest: value.digest.digest("hex"),
976
+ rawEventsRetained: false,
977
+ ...resources ? { resources, resourceCount: value.resources.size } : {}
978
+ }
979
+ };
980
+ void options.journal.append(input).catch((error) => options.onPersistError?.(error, input));
981
+ };
982
+ const gauge = (signal, event, dimension) => {
983
+ const sessionId = text(event.sessionId);
984
+ const dimensionValue = dimension ? text(event[dimension]) : void 0;
985
+ const key = `${signal}\0${sessionId ?? ""}\0${dimensionValue ?? ""}`;
986
+ const target = bucket(key, {
987
+ signal,
988
+ aggregateMs: gaugeWindowMs,
989
+ ...sessionId ? { sessionId } : {},
990
+ ...dimensionValue ? { agentId: dimensionValue } : {},
991
+ dimensions: dimensionValue && dimension ? { [dimension]: dimensionValue } : {}
992
+ });
993
+ sample(
994
+ target,
995
+ Object.fromEntries(
996
+ Object.entries(event).filter(([, value]) => typeof value === "number")
997
+ )
998
+ );
999
+ };
1000
+ const offs = [
1001
+ options.events.on("process.output", (event) => {
1002
+ const key = `process.output\0${event.sessionId}\0${event.toolCallId}\0${event.pid ?? ""}\0${event.stream}`;
1003
+ const target = bucket(key, {
1004
+ signal: "process.output",
1005
+ sessionId: event.sessionId,
1006
+ ...event.agentId ? { agentId: event.agentId } : {},
1007
+ toolCallId: event.toolCallId,
1008
+ dimensions: {
1009
+ stream: event.stream,
1010
+ toolName: event.toolName,
1011
+ pid: String(event.pid ?? "")
1012
+ }
1013
+ });
1014
+ sample(target, { bytes: event.bytes }, event.stream, event.chunkHash);
1015
+ }),
1016
+ options.events.on("process.completed", (event) => {
1017
+ for (const key of [...buckets.keys()])
1018
+ if (key.startsWith(`process.output\0${event.sessionId}\0${event.toolCallId}\0`)) flush(key);
1019
+ }),
1020
+ options.events.on("tool.progress", (event) => {
1021
+ if (event.event.type === "file_changed") return;
1022
+ const key = `tool.progress\0${event.sessionId ?? ""}\0${event.id}`;
1023
+ const target = bucket(key, {
1024
+ signal: "tool.progress",
1025
+ ...event.sessionId ? { sessionId: event.sessionId } : {},
1026
+ ...event.agentId ? { agentId: event.agentId } : {},
1027
+ toolCallId: event.id,
1028
+ dimensions: { toolName: event.name }
1029
+ });
1030
+ sample(
1031
+ target,
1032
+ { textBytes: Buffer.byteLength(event.event.text ?? "") },
1033
+ event.event.type,
1034
+ safeDigest(event.event)
1035
+ );
1036
+ }),
1037
+ options.events.on("tool.executed", (event) => {
1038
+ flush(`tool.progress\0${event.sessionId ?? ""}\0${event.id ?? ""}`);
1039
+ const metadata = event.metadata;
1040
+ if (!metadata || metadata.files.length === 0 && metadata.symbols.length === 0 && metadata.commands.length === 0)
1041
+ return;
1042
+ const key = `tool.resource\0${event.sessionId ?? ""}\0${event.id ?? ""}`;
1043
+ const target = bucket(key, {
1044
+ signal: "tool.resource.observed",
1045
+ ...event.sessionId ? { sessionId: event.sessionId } : {},
1046
+ ...event.agentId ? { agentId: event.agentId } : {},
1047
+ ...event.id ? { toolCallId: event.id } : {},
1048
+ dimensions: { toolName: event.name }
1049
+ });
1050
+ for (const file of metadata.files) {
1051
+ target.resources.set(resourceId2("file", file), { kind: "file", path: file });
1052
+ sample(target, {}, "file");
1053
+ }
1054
+ for (const symbol of metadata.symbols) {
1055
+ target.resources.set(resourceId2("symbol", symbol), { kind: "symbol" });
1056
+ sample(target, {}, "symbol");
1057
+ }
1058
+ for (const command of metadata.commands) {
1059
+ target.resources.set(resourceId2("command", command), { kind: "process" });
1060
+ sample(target, {}, "command");
1061
+ }
1062
+ flush(key);
1063
+ }),
1064
+ options.events.on(
1065
+ "tool.failed",
1066
+ (event) => flush(`tool.progress\0${event.sessionId}\0${event.id}`)
1067
+ ),
1068
+ options.events.on("ctx.pct", (event) => gauge("ctx.pct", event)),
1069
+ options.events.on(
1070
+ "subagent.ctx_pct",
1071
+ (event) => gauge("subagent.ctx_pct", event, "subagentId")
1072
+ ),
1073
+ options.events.on("countdown.tick", (event) => gauge("countdown.tick", event)),
1074
+ options.events.on("coordinator.stats", (event) => gauge("coordinator.stats", event)),
1075
+ // Periodic self-observation gauge (nested fields, so the flat gauge()
1076
+ // helper can't be reused directly — flatten before sampling).
1077
+ options.events.on("runtime.health.sampled", (event) => {
1078
+ const key = `runtime.health\0${event.sessionId ?? ""}`;
1079
+ const target = bucket(key, {
1080
+ signal: "runtime.health",
1081
+ aggregateMs: gaugeWindowMs,
1082
+ ...event.sessionId ? { sessionId: event.sessionId } : {},
1083
+ dimensions: {}
1084
+ });
1085
+ const chronicle = event.chronicle;
1086
+ sample(target, {
1087
+ "eventLoop.utilization": event.eventLoop.utilization,
1088
+ "eventLoop.delayMeanMs": event.eventLoop.delayMeanMs,
1089
+ "eventLoop.delayP95Ms": event.eventLoop.delayP95Ms,
1090
+ "eventLoop.delayMaxMs": event.eventLoop.delayMaxMs,
1091
+ "cpu.userMicros": event.cpu.userMicros,
1092
+ "cpu.systemMicros": event.cpu.systemMicros,
1093
+ "memory.rssBytes": event.memory.rssBytes,
1094
+ "memory.heapUsedBytes": event.memory.heapUsedBytes,
1095
+ "memory.heapTotalBytes": event.memory.heapTotalBytes,
1096
+ ...typeof chronicle?.pendingEvents === "number" ? { "chronicle.pendingEvents": chronicle.pendingEvents } : {},
1097
+ ...typeof chronicle?.rejectedEvents === "number" ? { "chronicle.rejectedEvents": chronicle.rejectedEvents } : {}
1098
+ });
1099
+ }),
1100
+ // Full-fleet snapshots fired on every agent-state flush (~14KB each) are
1101
+ // reduced to one windowed aggregate per session; the raw event is excluded
1102
+ // from the domain adapter. Sums preserve the fleet-level metric trail.
1103
+ options.events.on("session.agents_updated", (event) => {
1104
+ const key = `session.agents\0${event.sessionId ?? ""}`;
1105
+ const target = bucket(key, {
1106
+ signal: "session.agents",
1107
+ aggregateMs: gaugeWindowMs,
1108
+ ...event.sessionId ? { sessionId: event.sessionId } : {},
1109
+ dimensions: {}
1110
+ });
1111
+ const sums = {
1112
+ agents: 0,
1113
+ running: 0,
1114
+ iterations: 0,
1115
+ toolCalls: 0,
1116
+ costUsd: 0,
1117
+ tokensIn: 0,
1118
+ tokensOut: 0
1119
+ };
1120
+ for (const agent of event.agents) {
1121
+ sums.agents++;
1122
+ if (agent.status === "running") sums.running++;
1123
+ sums.iterations += numeric(agent.iterations);
1124
+ sums.toolCalls += numeric(agent.toolCalls);
1125
+ sums.costUsd += numeric(agent.costUsd);
1126
+ sums.tokensIn += numeric(agent.tokensIn);
1127
+ sums.tokensOut += numeric(agent.tokensOut);
1128
+ }
1129
+ sample(target, sums);
1130
+ }),
1131
+ // Per-request network chatter (started/completed pairs were the 2nd most
1132
+ // frequent raw family) becomes one aggregate per session×initiator×host
1133
+ // window with status-class categories. network.request.failed stays raw.
1134
+ options.events.on("network.request.completed", (event) => {
1135
+ const key = `network.request\0${event.sessionId}\0${event.initiator}\0${event.serverAddress}`;
1136
+ const target = bucket(key, {
1137
+ signal: "network.request",
1138
+ sessionId: event.sessionId,
1139
+ dimensions: { initiator: event.initiator, serverAddress: event.serverAddress }
1140
+ });
1141
+ sample(
1142
+ target,
1143
+ {
1144
+ durationMs: event.durationMs,
1145
+ ...event.requestBytes !== void 0 ? { requestBytes: event.requestBytes } : {},
1146
+ ...event.responseBytes !== void 0 ? { responseBytes: event.responseBytes } : {}
1147
+ },
1148
+ `${Math.floor(event.statusCode / 100)}xx`,
1149
+ event.requestId
1150
+ );
1151
+ })
1152
+ ];
1153
+ const timer = setInterval(() => {
1154
+ const now = Date.now();
1155
+ for (const [key, value] of buckets) {
1156
+ const due = value.aggregateMs === void 0 ? value.updatedAt <= now - windowMs : value.startedAt <= now - value.aggregateMs;
1157
+ if (due) flush(key);
1158
+ }
1159
+ }, windowMs);
1160
+ timer.unref?.();
1161
+ return () => {
1162
+ clearInterval(timer);
1163
+ for (const key of [...buckets.keys()]) flush(key);
1164
+ offs.forEach((off) => {
1165
+ off();
1166
+ });
1167
+ };
1168
+ }
1169
+ function text(value) {
1170
+ return typeof value === "string" ? value : void 0;
1171
+ }
1172
+ function numeric(value) {
1173
+ return typeof value === "number" && Number.isFinite(value) ? value : 0;
1174
+ }
1175
+ function safeDigest(value) {
1176
+ try {
1177
+ return createHash7("sha256").update(JSON.stringify(value)).digest("hex");
1178
+ } catch {
1179
+ return "unhashable";
1180
+ }
1181
+ }
1182
+ function resourceId2(kind, value) {
1183
+ return `${kind}_${createHash7("sha256").update(value).digest("hex").slice(0, 24)}`;
1184
+ }
1185
+
1186
+ export {
1187
+ ChronicleCompactionBusyError,
1188
+ compactChronicleSqlite,
1189
+ wireProviderAttemptsToChronicle,
1190
+ wireToolsToChronicle,
1191
+ wireProcessesToChronicle,
1192
+ startChronicleHealthMonitor,
1193
+ wireDecisionsToChronicle,
1194
+ wireDomainEventsToChronicle,
1195
+ wireProviderStreamsToChronicle,
1196
+ wireReviewFindingsToChronicle,
1197
+ wireRollupsToChronicle
1198
+ };
1199
+ //# sourceMappingURL=chunk-NEMIWEXC.js.map