@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,395 @@
1
+ // src/utils/tool-wire-compact.ts
2
+ var TOOL_DESCRIPTION_MAX_CHARS = 400;
3
+ var SCHEMA_DESCRIPTION_MAX_CHARS = 120;
4
+ var compactCache = /* @__PURE__ */ new WeakMap();
5
+ function compactToolDefinitionForWire(tool, opts = {}) {
6
+ const useDefaultOptions = opts.descriptionMaxChars === void 0 && opts.schemaDescriptionMaxChars === void 0;
7
+ if (useDefaultOptions && typeof tool === "object" && tool !== null) {
8
+ const cached = compactCache.get(tool);
9
+ if (cached) return cached;
10
+ }
11
+ const compact = {
12
+ name: tool.name,
13
+ description: compactDescription(
14
+ tool.description ?? "",
15
+ opts.descriptionMaxChars ?? TOOL_DESCRIPTION_MAX_CHARS
16
+ ),
17
+ inputSchema: normalizeTopLevelToolSchema(
18
+ compactSchemaDescriptions(
19
+ tool.inputSchema,
20
+ opts.schemaDescriptionMaxChars ?? SCHEMA_DESCRIPTION_MAX_CHARS
21
+ )
22
+ )
23
+ };
24
+ if (useDefaultOptions && typeof tool === "object" && tool !== null) {
25
+ compactCache.set(tool, compact);
26
+ }
27
+ return compact;
28
+ }
29
+ function normalizeTopLevelToolSchema(schema) {
30
+ const combinators = ["oneOf", "anyOf", "allOf"].map((keyword) => ({ keyword, branches: schema[keyword] })).filter(
31
+ (entry) => Array.isArray(entry.branches)
32
+ );
33
+ if (combinators.length === 0) return schema;
34
+ const out = { ...schema, type: "object" };
35
+ delete out["oneOf"];
36
+ delete out["anyOf"];
37
+ delete out["allOf"];
38
+ const properties = isRecord(schema["properties"]) ? { ...schema["properties"] } : {};
39
+ let required = stringSet(schema["required"]);
40
+ for (const { keyword, branches } of combinators) {
41
+ const objectBranches = branches.filter(isRecord);
42
+ for (const branch of objectBranches) {
43
+ if (isRecord(branch["properties"])) Object.assign(properties, branch["properties"]);
44
+ }
45
+ const branchRequired = objectBranches.map((branch) => stringSet(branch["required"]));
46
+ if (keyword === "allOf") {
47
+ for (const fields of branchRequired) for (const field of fields) required.add(field);
48
+ } else if (branchRequired.length > 0) {
49
+ const common = new Set(
50
+ [...branchRequired[0]].filter(
51
+ (field) => branchRequired.slice(1).every((fields) => fields.has(field))
52
+ )
53
+ );
54
+ required = /* @__PURE__ */ new Set([...required, ...common]);
55
+ }
56
+ }
57
+ out["properties"] = properties;
58
+ if (required.size > 0) out["required"] = [...required];
59
+ else delete out["required"];
60
+ return out;
61
+ }
62
+ function stringSet(value) {
63
+ return new Set(
64
+ Array.isArray(value) ? value.filter((item) => typeof item === "string") : []
65
+ );
66
+ }
67
+ function compactSchemaDescriptions(schema, maxDescriptionChars = SCHEMA_DESCRIPTION_MAX_CHARS) {
68
+ const compact = compactSchemaNode(schema, maxDescriptionChars);
69
+ return isRecord(compact) ? compact : { type: "object", properties: {} };
70
+ }
71
+ function compactSchemaNode(node, maxDescriptionChars) {
72
+ if (Array.isArray(node)) {
73
+ return node.map((item) => compactSchemaNode(item, maxDescriptionChars));
74
+ }
75
+ if (!isRecord(node)) return node;
76
+ const out = {};
77
+ for (const [key, value] of Object.entries(node)) {
78
+ if (key === "description" && typeof value === "string") {
79
+ out[key] = compactDescription(value, maxDescriptionChars);
80
+ } else {
81
+ out[key] = compactSchemaNode(value, maxDescriptionChars);
82
+ }
83
+ }
84
+ return out;
85
+ }
86
+ function compactDescription(text, maxChars) {
87
+ const normalized = text.replace(/\s+/g, " ").trim();
88
+ if (normalized.length <= maxChars) return normalized;
89
+ if (maxChars <= 20) return normalized.slice(0, maxChars);
90
+ const hardLimit = maxChars - 12;
91
+ const boundary = findSemanticBoundary(normalized, hardLimit);
92
+ const head = normalized.slice(0, boundary > 0 ? boundary : hardLimit).trimEnd();
93
+ return `${head} ...`;
94
+ }
95
+ function findSemanticBoundary(text, limit) {
96
+ const punctuation = Math.max(
97
+ text.lastIndexOf(". ", limit),
98
+ text.lastIndexOf("; ", limit),
99
+ text.lastIndexOf(": ", limit)
100
+ );
101
+ if (punctuation >= Math.floor(limit * 0.45)) return punctuation + 1;
102
+ const comma = text.lastIndexOf(", ", limit);
103
+ if (comma >= Math.floor(limit * 0.6)) return comma + 1;
104
+ const space = text.lastIndexOf(" ", limit);
105
+ return space >= Math.floor(limit * 0.6) ? space : limit;
106
+ }
107
+ function isRecord(value) {
108
+ return !!value && typeof value === "object" && !Array.isArray(value);
109
+ }
110
+
111
+ // src/utils/token-estimate.ts
112
+ var RoughTokenEstimate = (text, charsPerToken = 3.5) => Math.max(1, Math.ceil(text.length / charsPerToken));
113
+ var CAL_ALPHA = 0.3;
114
+ var CALIBRATION_GLOBAL_KEY = "__global__";
115
+ var _cals = /* @__PURE__ */ new Map();
116
+ function calState(key) {
117
+ let state = _cals.get(key);
118
+ if (!state) {
119
+ state = { ratio: 1, count: 0, prevEst: 0 };
120
+ _cals.set(key, state);
121
+ }
122
+ return state;
123
+ }
124
+ var MIN_SAMPLES_FOR_CALIBRATION = 3;
125
+ var MODEL_FAMILY_RATIO = {
126
+ // Anthropic: ~3.8-4.0 chars/token depending on model
127
+ claude: 3.8,
128
+ // OpenAI: ~4.0 chars/token
129
+ "gpt-4": 4,
130
+ "gpt-3.5": 4,
131
+ // Google: ~3.5 chars/token
132
+ gemini: 3.5,
133
+ // DeepSeek: ~3.5 chars/token
134
+ deepseek: 3.5
135
+ };
136
+ var PAYLOAD_TOKEN_MEMO = /* @__PURE__ */ new WeakMap();
137
+ function memoizedPayloadTokens(payload) {
138
+ const cached = PAYLOAD_TOKEN_MEMO.get(payload);
139
+ if (cached !== void 0) return cached;
140
+ let str;
141
+ try {
142
+ str = JSON.stringify(payload) ?? "";
143
+ } catch {
144
+ str = String(payload);
145
+ }
146
+ const estimate = RoughTokenEstimate(str);
147
+ PAYLOAD_TOKEN_MEMO.set(payload, estimate);
148
+ return estimate;
149
+ }
150
+ function estimateToolInputTokens(input) {
151
+ if (typeof input === "string") return RoughTokenEstimate(input);
152
+ if (input === null || typeof input !== "object") {
153
+ return RoughTokenEstimate(String(input));
154
+ }
155
+ return memoizedPayloadTokens(input);
156
+ }
157
+ function estimateToolResultTokens(content) {
158
+ if (typeof content === "string") return RoughTokenEstimate(content);
159
+ if (content === null || typeof content !== "object") {
160
+ return RoughTokenEstimate(String(content));
161
+ }
162
+ return memoizedPayloadTokens(content);
163
+ }
164
+ function estimateTextTokens(text) {
165
+ return RoughTokenEstimate(text);
166
+ }
167
+ function computeMessageTokens(msg) {
168
+ if (typeof msg.content === "string") return estimateTextTokens(msg.content);
169
+ let total = 0;
170
+ for (const b of msg.content) {
171
+ if (b.type === "text") total += estimateTextTokens(b.text);
172
+ else if (b.type === "tool_use") total += estimateToolInputTokens(b.input);
173
+ else if (b.type === "tool_result") total += estimateToolResultTokens(b.content);
174
+ else {
175
+ let str;
176
+ try {
177
+ str = JSON.stringify(b) ?? "";
178
+ } catch {
179
+ str = String(b);
180
+ }
181
+ total += RoughTokenEstimate(str);
182
+ }
183
+ }
184
+ return total;
185
+ }
186
+ function estimateMessageTokens(messages) {
187
+ let total = 0;
188
+ for (const m of messages) {
189
+ if (typeof m._estTokens === "number" && m._estTokens > 0) {
190
+ total += m._estTokens;
191
+ continue;
192
+ }
193
+ total += computeMessageTokens(m);
194
+ }
195
+ return total;
196
+ }
197
+ function realAnchoredInputTokens(messages, anchorTokens, anchorMsgCount) {
198
+ if (typeof anchorTokens !== "number" || anchorTokens <= 0) return null;
199
+ if (typeof anchorMsgCount !== "number" || anchorMsgCount < 0) return null;
200
+ if (messages.length < anchorMsgCount) return null;
201
+ const delta = anchorMsgCount === messages.length ? 0 : estimateMessageTokens(messages.slice(anchorMsgCount));
202
+ return anchorTokens + delta;
203
+ }
204
+ function estimateToolDefTokens(tool) {
205
+ const cached = tool._estDefTokens;
206
+ if (typeof cached === "number" && cached > 0) return cached;
207
+ const compact = compactToolDefinitionForWire(tool);
208
+ return RoughTokenEstimate(tool.name) + RoughTokenEstimate(compact.description) + RoughTokenEstimate(JSON.stringify(compact.inputSchema));
209
+ }
210
+ function estimateRequestTokens(messages, systemPrompt, tools, calibrationKey = CALIBRATION_GLOBAL_KEY) {
211
+ let messagesTokens = 0;
212
+ if (typeof messages === "string") {
213
+ messagesTokens = RoughTokenEstimate(messages);
214
+ } else if (Array.isArray(messages)) {
215
+ for (const m of messages) {
216
+ if (typeof m === "object" && m !== null && "content" in m) {
217
+ const cached = m._estTokens;
218
+ if (typeof cached === "number" && cached > 0) {
219
+ messagesTokens += cached;
220
+ continue;
221
+ }
222
+ const content = m.content;
223
+ if (typeof content === "string") {
224
+ messagesTokens += RoughTokenEstimate(content);
225
+ } else if (Array.isArray(content)) {
226
+ for (const b of content) {
227
+ if (typeof b === "object" && b !== null) {
228
+ if (b.type === "text") {
229
+ messagesTokens += RoughTokenEstimate(b.text);
230
+ } else {
231
+ messagesTokens += RoughTokenEstimate(JSON.stringify(b));
232
+ }
233
+ }
234
+ }
235
+ }
236
+ }
237
+ }
238
+ }
239
+ let systemTokens = 0;
240
+ if (typeof systemPrompt === "string") {
241
+ systemTokens = RoughTokenEstimate(systemPrompt);
242
+ } else if (Array.isArray(systemPrompt)) {
243
+ for (const b of systemPrompt) {
244
+ if (typeof b === "object" && b !== null && b.type === "text") {
245
+ systemTokens += RoughTokenEstimate(b.text);
246
+ }
247
+ }
248
+ }
249
+ let toolsTokens = 0;
250
+ for (const t of tools) {
251
+ toolsTokens += estimateToolDefTokens(t);
252
+ }
253
+ const total = messagesTokens + systemTokens + toolsTokens;
254
+ calState(calibrationKey).prevEst = total;
255
+ return {
256
+ messages: messagesTokens,
257
+ systemPrompt: systemTokens,
258
+ tools: toolsTokens,
259
+ total
260
+ };
261
+ }
262
+ function recordActualUsage(actualInputTokens, estimatedInputTokens, calibrationKey = CALIBRATION_GLOBAL_KEY) {
263
+ if (actualInputTokens <= 0) return;
264
+ const cal = calState(calibrationKey);
265
+ const est = estimatedInputTokens ?? cal.prevEst;
266
+ if (est <= 0) return;
267
+ const sampleRatio = actualInputTokens / est;
268
+ if (cal.count === 0) {
269
+ cal.ratio = sampleRatio;
270
+ } else {
271
+ cal.ratio = CAL_ALPHA * sampleRatio + (1 - CAL_ALPHA) * cal.ratio;
272
+ }
273
+ cal.ratio = Math.min(1.5, Math.max(0.5, cal.ratio));
274
+ cal.count++;
275
+ }
276
+ function getCalibrationState(calibrationKey = CALIBRATION_GLOBAL_KEY) {
277
+ const cal = calState(calibrationKey);
278
+ return {
279
+ ratio: cal.ratio,
280
+ count: cal.count,
281
+ calibrated: cal.count >= MIN_SAMPLES_FOR_CALIBRATION
282
+ };
283
+ }
284
+ function estimateRequestTokensCalibrated(messages, systemPrompt, tools, calibrationKey = CALIBRATION_GLOBAL_KEY) {
285
+ const result = estimateRequestTokens(messages, systemPrompt, tools, calibrationKey);
286
+ const cal = calState(calibrationKey);
287
+ if (cal.count >= MIN_SAMPLES_FOR_CALIBRATION) {
288
+ const safeRatio = Math.min(1.5, Math.max(0.5, cal.ratio));
289
+ return {
290
+ messages: Math.round(result.messages * safeRatio),
291
+ systemPrompt: Math.round(result.systemPrompt * safeRatio),
292
+ tools: Math.round(result.tools * safeRatio),
293
+ total: Math.round(result.total * safeRatio)
294
+ };
295
+ }
296
+ const fallbackRatio = getModelFamilyRatio(calibrationKey);
297
+ if (fallbackRatio !== null) {
298
+ return {
299
+ messages: Math.round(result.messages * fallbackRatio),
300
+ systemPrompt: Math.round(result.systemPrompt * fallbackRatio),
301
+ tools: Math.round(result.tools * fallbackRatio),
302
+ total: Math.round(result.total * fallbackRatio)
303
+ };
304
+ }
305
+ return result;
306
+ }
307
+ var DENSITY_SAMPLE_PER_BLOCK = 4096;
308
+ var DENSITY_SAMPLE_TOTAL_CAP = 2e6;
309
+ function textDensityMultiplier(messages) {
310
+ let sampled = 0;
311
+ let nonAscii = 0;
312
+ let maxRun = 0;
313
+ const consider = (s) => {
314
+ const n = Math.min(s.length, DENSITY_SAMPLE_PER_BLOCK);
315
+ let run = 0;
316
+ for (let i = 0; i < n; i++) {
317
+ const c = s.charCodeAt(i);
318
+ if (c > 127) nonAscii++;
319
+ if (c === 32 || c === 9 || c === 10 || c === 13) {
320
+ if (run > maxRun) maxRun = run;
321
+ run = 0;
322
+ } else {
323
+ run++;
324
+ }
325
+ }
326
+ if (run > maxRun) maxRun = run;
327
+ sampled += n;
328
+ };
329
+ for (const m of messages) {
330
+ if (typeof m.content === "string") {
331
+ consider(m.content);
332
+ } else if (Array.isArray(m.content)) {
333
+ for (const b of m.content) {
334
+ if (b.type === "text") consider(b.text);
335
+ else if (b.type === "tool_result" && typeof b.content === "string") consider(b.content);
336
+ else if (b.type === "thinking") consider(b.thinking);
337
+ }
338
+ }
339
+ if (sampled >= DENSITY_SAMPLE_TOTAL_CAP) break;
340
+ }
341
+ if (sampled === 0) return 1;
342
+ const nonAsciiRatio = nonAscii / sampled;
343
+ let charsPerToken = 3.5 - 2 * nonAsciiRatio;
344
+ if (maxRun > 2e3 && nonAsciiRatio < 0.1) charsPerToken = Math.min(charsPerToken, 3);
345
+ const multiplier = 3.5 / Math.max(1.4, charsPerToken);
346
+ return Math.min(2.5, Math.max(1, multiplier));
347
+ }
348
+ function estimateRequestTokensUpperBound(messages, systemPrompt, tools, calibrationKey = CALIBRATION_GLOBAL_KEY) {
349
+ const base = estimateRequestTokens(messages, systemPrompt, tools, calibrationKey);
350
+ const density = Array.isArray(messages) ? textDensityMultiplier(messages) : 1;
351
+ const cal = calState(calibrationKey);
352
+ const calCeiling = cal.count >= MIN_SAMPLES_FOR_CALIBRATION ? Math.min(1.5, Math.max(1, cal.ratio)) : 1;
353
+ const mult = Math.max(density, calCeiling);
354
+ if (mult <= 1) return base;
355
+ return {
356
+ messages: Math.ceil(base.messages * mult),
357
+ systemPrompt: Math.ceil(base.systemPrompt * mult),
358
+ tools: Math.ceil(base.tools * mult),
359
+ total: Math.ceil(base.total * mult)
360
+ };
361
+ }
362
+ function getModelFamilyRatio(calibrationKey) {
363
+ const lower = calibrationKey.toLowerCase();
364
+ for (const [family, ratio] of Object.entries(MODEL_FAMILY_RATIO)) {
365
+ if (lower.includes(family)) return ratio / 3.5;
366
+ }
367
+ return null;
368
+ }
369
+ function resetCalibration(calibrationKey) {
370
+ if (calibrationKey === void 0) {
371
+ _cals.clear();
372
+ return;
373
+ }
374
+ _cals.delete(calibrationKey);
375
+ }
376
+
377
+ export {
378
+ compactToolDefinitionForWire,
379
+ normalizeTopLevelToolSchema,
380
+ compactSchemaDescriptions,
381
+ estimateToolInputTokens,
382
+ estimateToolResultTokens,
383
+ estimateTextTokens,
384
+ computeMessageTokens,
385
+ estimateMessageTokens,
386
+ realAnchoredInputTokens,
387
+ estimateToolDefTokens,
388
+ estimateRequestTokens,
389
+ recordActualUsage,
390
+ getCalibrationState,
391
+ estimateRequestTokensCalibrated,
392
+ estimateRequestTokensUpperBound,
393
+ resetCalibration
394
+ };
395
+ //# sourceMappingURL=chunk-HMLIGAU7.js.map
@@ -0,0 +1,303 @@
1
+ import {
2
+ reportEventTypeFor,
3
+ validateReportTransition
4
+ } from "./chunk-WP7BVANJ.js";
5
+ import {
6
+ SECRET_FILE_MODE
7
+ } from "./chunk-6FHWXLPT.js";
8
+ import {
9
+ atomicWrite,
10
+ withFileLock
11
+ } from "./chunk-OSGLYW5J.js";
12
+
13
+ // src/plugins/review-report-store.ts
14
+ import { randomUUID } from "node:crypto";
15
+ import * as fsp from "node:fs/promises";
16
+ import * as path from "node:path";
17
+ var REPORT_RETENTION_MS = 90 * 24 * 60 * 60 * 1e3;
18
+ var REPORT_DEFAULT_PAGE_SIZE = 25;
19
+ var NL = "\n";
20
+ var REPORT_STORE_FILE = "review-reports.jsonl";
21
+ function resolveReportStorePath(projectDir) {
22
+ return path.join(projectDir, REPORT_STORE_FILE);
23
+ }
24
+ var JsonlReportStore = class {
25
+ filePath;
26
+ constructor(projectDir) {
27
+ this.filePath = resolveReportStorePath(projectDir);
28
+ }
29
+ get storePath() {
30
+ return this.filePath;
31
+ }
32
+ // ── Persist (create or reopen) ───────────────────────────────────
33
+ async persist(input) {
34
+ return withFileLock(this.filePath, async () => {
35
+ const existing = await this._findRecord(input.id);
36
+ if (existing) {
37
+ const updated = {
38
+ ...existing,
39
+ counts: input.counts,
40
+ totalFindings: input.totalFindings,
41
+ unparseableCount: input.unparseableCount,
42
+ durationSeconds: input.durationSeconds ?? existing.durationSeconds,
43
+ rawText: input.rawText || existing.rawText,
44
+ files: input.files.length > 0 ? input.files : existing.files,
45
+ ...input.evidenceStatus !== void 0 ? { evidenceStatus: input.evidenceStatus } : {},
46
+ ...input.evidenceChecks !== void 0 ? { evidenceChecks: input.evidenceChecks } : {}
47
+ };
48
+ await fsp.appendFile(this.filePath, JSON.stringify({ __report: 1, data: updated }) + NL, {
49
+ encoding: "utf8",
50
+ mode: SECRET_FILE_MODE
51
+ });
52
+ return updated;
53
+ }
54
+ const report = {
55
+ id: input.id,
56
+ reviewedAt: (/* @__PURE__ */ new Date()).toISOString(),
57
+ sessionId: input.sessionId,
58
+ agentId: input.agentId,
59
+ reviewerModel: input.reviewerModel,
60
+ source: input.source,
61
+ reviewStatus: input.reviewStatus,
62
+ lifecycle: "open",
63
+ files: input.files,
64
+ counts: input.counts,
65
+ totalFindings: input.totalFindings,
66
+ unparseableCount: input.unparseableCount,
67
+ durationSeconds: input.durationSeconds,
68
+ rawText: input.rawText,
69
+ ...input.cascadeDepth !== void 0 ? { cascadeDepth: input.cascadeDepth } : {},
70
+ ...input.evidenceStatus !== void 0 ? { evidenceStatus: input.evidenceStatus } : {},
71
+ ...input.evidenceChecks !== void 0 ? { evidenceChecks: input.evidenceChecks } : {}
72
+ };
73
+ const createdEvent = {
74
+ id: randomUUID(),
75
+ reportId: report.id,
76
+ eventType: "created",
77
+ fromLifecycle: null,
78
+ toLifecycle: "open",
79
+ actorId: "system",
80
+ actorKind: "system",
81
+ timestamp: report.reviewedAt
82
+ };
83
+ const lines = JSON.stringify({ __report: 1, data: report }) + NL + JSON.stringify({ __reportEvent: 1, data: createdEvent }) + NL;
84
+ await fsp.appendFile(this.filePath, lines, { encoding: "utf8", mode: SECRET_FILE_MODE });
85
+ return report;
86
+ });
87
+ }
88
+ // ── Lifecycle transitions ────────────────────────────────────────
89
+ async transition(reportId, to, actor, opts) {
90
+ return withFileLock(this.filePath, async () => {
91
+ const all = await this._readAll();
92
+ const entry = all.find((e) => e.report.id === reportId);
93
+ if (!entry) throw new Error(`Review report not found: ${reportId}`);
94
+ const from = this._materialize(entry).lifecycle;
95
+ validateReportTransition(from, to);
96
+ const event = {
97
+ id: randomUUID(),
98
+ reportId,
99
+ eventType: reportEventTypeFor(to),
100
+ fromLifecycle: from,
101
+ toLifecycle: to,
102
+ actorId: actor.id,
103
+ actorKind: actor.kind,
104
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
105
+ reason: opts?.reason
106
+ };
107
+ entry.report.lifecycle = to;
108
+ await fsp.appendFile(this.filePath, JSON.stringify({ __reportEvent: 1, data: event }) + NL, {
109
+ encoding: "utf8",
110
+ mode: SECRET_FILE_MODE
111
+ });
112
+ return { ...entry.report };
113
+ });
114
+ }
115
+ async updateEvidence(reportId, status, checks) {
116
+ return withFileLock(this.filePath, async () => {
117
+ const all = await this._readAll();
118
+ const entry = all.find((candidate) => candidate.report.id === reportId);
119
+ if (!entry) throw new Error(`Review report not found: ${reportId}`);
120
+ const updated = {
121
+ ...this._materialize(entry),
122
+ evidenceStatus: status,
123
+ evidenceChecks: checks
124
+ };
125
+ await fsp.appendFile(
126
+ this.filePath,
127
+ `${JSON.stringify({ __report: 1, data: updated })}${NL}`,
128
+ { encoding: "utf8", mode: SECRET_FILE_MODE }
129
+ );
130
+ return updated;
131
+ });
132
+ }
133
+ async addNote(reportId, actor, note) {
134
+ return withFileLock(this.filePath, async () => {
135
+ const all = await this._readAll();
136
+ const entry = all.find((e) => e.report.id === reportId);
137
+ if (!entry) throw new Error(`Review report not found: ${reportId}`);
138
+ const materialized = this._materialize(entry);
139
+ const event = {
140
+ id: randomUUID(),
141
+ reportId,
142
+ eventType: "note_added",
143
+ fromLifecycle: materialized.lifecycle,
144
+ toLifecycle: materialized.lifecycle,
145
+ actorId: actor.id,
146
+ actorKind: actor.kind,
147
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
148
+ reason: note
149
+ };
150
+ await fsp.appendFile(this.filePath, JSON.stringify({ __reportEvent: 1, data: event }) + NL, {
151
+ encoding: "utf8",
152
+ mode: SECRET_FILE_MODE
153
+ });
154
+ return materialized;
155
+ });
156
+ }
157
+ // ── Query ────────────────────────────────────────────────────────
158
+ async list(opts) {
159
+ const all = await this._readAll();
160
+ let reports = all.map((e) => this._materialize(e));
161
+ if (opts?.statuses && opts.statuses.length > 0) {
162
+ const set = new Set(opts.statuses);
163
+ reports = reports.filter((r) => set.has(r.lifecycle));
164
+ }
165
+ if (opts?.sources && opts.sources.length > 0) {
166
+ const set = new Set(opts.sources);
167
+ reports = reports.filter((r) => set.has(r.source));
168
+ }
169
+ reports.sort((a, b) => b.reviewedAt.localeCompare(a.reviewedAt));
170
+ const limit = opts?.limit ?? REPORT_DEFAULT_PAGE_SIZE;
171
+ return reports.slice(0, limit);
172
+ }
173
+ async get(id) {
174
+ const all = await this._readAll();
175
+ const entry = all.find((e) => e.report.id === id);
176
+ return entry ? this._materialize(entry) : null;
177
+ }
178
+ async getEvents(reportId) {
179
+ const all = await this._readAllLines();
180
+ const events = [];
181
+ for (const line of all) {
182
+ try {
183
+ const parsed = JSON.parse(line);
184
+ if (this._isEventRecord(parsed) && parsed.data.reportId === reportId) {
185
+ events.push(parsed.data);
186
+ }
187
+ } catch {
188
+ }
189
+ }
190
+ return events.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
191
+ }
192
+ // ── Compaction ───────────────────────────────────────────────────
193
+ async compact(opts) {
194
+ return withFileLock(this.filePath, async () => {
195
+ const maxAge = opts?.maxAgeMs ?? REPORT_RETENTION_MS;
196
+ const now = Date.now();
197
+ const all = await this._readAll();
198
+ const kept = [];
199
+ let removed = 0;
200
+ let eventsFolded = 0;
201
+ for (const entry of all) {
202
+ const age = now - new Date(entry.report.reviewedAt).getTime();
203
+ const materialized = this._materialize(entry);
204
+ const isTerminal = materialized.lifecycle === "completed" || materialized.lifecycle === "skipped";
205
+ if (isTerminal && age > maxAge) {
206
+ removed++;
207
+ eventsFolded += entry.events.length;
208
+ continue;
209
+ }
210
+ const oldEvents = entry.events.filter(
211
+ (ev) => now - new Date(ev.timestamp).getTime() > maxAge
212
+ );
213
+ if (oldEvents.length > 1) {
214
+ eventsFolded += oldEvents.length - 1;
215
+ const newestOld = oldEvents.sort((a, b) => b.timestamp.localeCompare(a.timestamp))[0];
216
+ entry.events = [
217
+ newestOld,
218
+ ...entry.events.filter((ev) => now - new Date(ev.timestamp).getTime() <= maxAge)
219
+ ];
220
+ }
221
+ kept.push({ record: { __report: 1, data: entry.report }, events: entry.events });
222
+ }
223
+ const lines = [];
224
+ for (const { record, events } of kept) {
225
+ if (record) lines.push(JSON.stringify(record));
226
+ for (const ev of events) {
227
+ lines.push(JSON.stringify({ __reportEvent: 1, data: ev }));
228
+ }
229
+ }
230
+ lines.push(
231
+ JSON.stringify({
232
+ __reportCompact: 1,
233
+ compactedAt: (/* @__PURE__ */ new Date()).toISOString(),
234
+ removedReports: removed,
235
+ foldedEvents: eventsFolded
236
+ })
237
+ );
238
+ await atomicWrite(this.filePath, lines.join(NL) + NL, { mode: 384 });
239
+ return { removed, eventsFolded };
240
+ });
241
+ }
242
+ // ── Private helpers ──────────────────────────────────────────────
243
+ async _readAllLines() {
244
+ try {
245
+ const raw = await fsp.readFile(this.filePath, "utf8");
246
+ return raw.split(NL).filter((l) => l.trim().length > 0);
247
+ } catch (err) {
248
+ if (err.code === "ENOENT") return [];
249
+ throw err;
250
+ }
251
+ }
252
+ _isReportRecord(v) {
253
+ return typeof v === "object" && v !== null && v["__report"] === 1;
254
+ }
255
+ _isEventRecord(v) {
256
+ return typeof v === "object" && v !== null && v["__reportEvent"] === 1;
257
+ }
258
+ async _readAll() {
259
+ const lines = await this._readAllLines();
260
+ const reports = /* @__PURE__ */ new Map();
261
+ const eventsMap = /* @__PURE__ */ new Map();
262
+ for (const line of lines) {
263
+ try {
264
+ const parsed = JSON.parse(line);
265
+ if (this._isReportRecord(parsed)) {
266
+ reports.set(parsed.data.id, parsed.data);
267
+ if (!eventsMap.has(parsed.data.id)) eventsMap.set(parsed.data.id, []);
268
+ } else if (this._isEventRecord(parsed)) {
269
+ const list = eventsMap.get(parsed.data.reportId);
270
+ if (list) list.push(parsed.data);
271
+ }
272
+ } catch {
273
+ }
274
+ }
275
+ return Array.from(reports.entries()).map(([id, report]) => ({
276
+ report,
277
+ events: eventsMap.get(id) ?? []
278
+ }));
279
+ }
280
+ async _findRecord(id) {
281
+ const all = await this._readAll();
282
+ const entry = all.find((e) => e.report.id === id);
283
+ return entry ? this._materialize(entry) : null;
284
+ }
285
+ _materialize(entry) {
286
+ if (entry.events.length === 0) return { ...entry.report };
287
+ const sorted = [...entry.events].sort((a, b) => a.timestamp.localeCompare(b.timestamp));
288
+ const latest = sorted[sorted.length - 1];
289
+ if (latest.eventType !== "note_added") {
290
+ return { ...entry.report, lifecycle: latest.toLifecycle };
291
+ }
292
+ return { ...entry.report };
293
+ }
294
+ };
295
+
296
+ export {
297
+ REPORT_RETENTION_MS,
298
+ REPORT_DEFAULT_PAGE_SIZE,
299
+ REPORT_STORE_FILE,
300
+ resolveReportStorePath,
301
+ JsonlReportStore
302
+ };
303
+ //# sourceMappingURL=chunk-HXKZ7OBQ.js.map