@iowarp/clio-coder 0.3.0 → 0.3.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 (988) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +50 -53
  3. package/dist/acp-FPR54DGL.js +138 -0
  4. package/dist/{agents-Q4MYPMUW.js → agents-OGPIHPJH.js} +33 -25
  5. package/dist/assets/codewiki.json +1 -0
  6. package/dist/assets/grammars/notices/@vscode__tree-sitter-wasm/LICENSE +21 -0
  7. package/dist/assets/grammars/notices/@vscode__tree-sitter-wasm/cgmanifest.json +16 -0
  8. package/dist/assets/grammars/notices/tree-sitter-wasms/LICENSE +24 -0
  9. package/dist/assets/grammars/tree-sitter-c-sharp.wasm +0 -0
  10. package/dist/assets/grammars/tree-sitter-c.wasm +0 -0
  11. package/dist/assets/grammars/tree-sitter-cpp.wasm +0 -0
  12. package/dist/assets/grammars/tree-sitter-go.wasm +0 -0
  13. package/dist/assets/grammars/tree-sitter-java.wasm +0 -0
  14. package/dist/assets/grammars/tree-sitter-javascript.wasm +0 -0
  15. package/dist/assets/grammars/tree-sitter-python.wasm +0 -0
  16. package/dist/assets/grammars/tree-sitter-ruby.wasm +0 -0
  17. package/dist/assets/grammars/tree-sitter-rust.wasm +0 -0
  18. package/dist/assets/grammars/tree-sitter-tsx.wasm +0 -0
  19. package/dist/assets/grammars/tree-sitter-typescript.wasm +0 -0
  20. package/dist/assets/grammars/tree-sitter.wasm +0 -0
  21. package/dist/{auth-O6HYIJ6J.js → auth-IC3K6NIZ.js} +22 -15
  22. package/dist/{chunk-KKKPTZLM.js → chunk-2STGEDFV.js} +8 -1
  23. package/dist/chunk-3I7MS7N2.js +40 -0
  24. package/dist/chunk-3R73A4XB.js +69 -0
  25. package/dist/{chunk-26BZQOAD.js → chunk-474KN5II.js} +86 -115
  26. package/dist/{chunk-NI4DEJMC.js → chunk-4QKXUHSR.js} +26 -3
  27. package/dist/{chunk-X3BR7HWV.js → chunk-5WIGXA4T.js} +7 -1
  28. package/dist/{chunk-TFSSEXL6.js → chunk-673JJUWJ.js} +14 -4
  29. package/dist/{chunk-GNGDQYDU.js → chunk-7SS2CTV2.js} +27922 -1249
  30. package/dist/{chunk-7RBKDI66.js → chunk-ASND7OZK.js} +104 -12
  31. package/dist/{chunk-X3NE4WVW.js → chunk-BNAZZHFG.js} +7 -1
  32. package/dist/{chunk-RQDWMVRB.js → chunk-BSU2YIWB.js} +9 -3
  33. package/dist/{chunk-CLJ5HLUD.js → chunk-C4PTHK7P.js} +24 -5
  34. package/dist/{chunk-QV47YRF4.js → chunk-CGKSTWHD.js} +7 -1
  35. package/dist/{chunk-BYEU76JP.js → chunk-DKGKUHFA.js} +34 -9
  36. package/dist/chunk-EYOKLTMF.js +170 -0
  37. package/dist/{chunk-PS4PFJQP.js → chunk-FCIH3BIZ.js} +15258 -14130
  38. package/dist/{chunk-2J63S4SF.js → chunk-FST4FYJB.js} +82 -14
  39. package/dist/{chunk-3DANZDGR.js → chunk-G34LV2PF.js} +34 -9
  40. package/dist/{chunk-BBUH4VAA.js → chunk-GAEBEQVI.js} +34 -21
  41. package/dist/chunk-GB6QRBXN.js +8543 -0
  42. package/dist/chunk-GEP36Y4X.js +12796 -0
  43. package/dist/{chunk-TKHQ4DGZ.js → chunk-H6F6BYOH.js} +496 -121
  44. package/dist/{chunk-UGYAX5YI.js → chunk-HQQID6OA.js} +10 -5
  45. package/dist/chunk-IHXBNWMM.js +137 -0
  46. package/dist/{chunk-ME6DNWIU.js → chunk-IS3ONKU3.js} +7 -1
  47. package/dist/{chunk-DXQNI4PC.js → chunk-IWHMRKLL.js} +8 -1
  48. package/dist/chunk-K2ITRMHZ.js +642 -0
  49. package/dist/{chunk-KBR4MZZR.js → chunk-K5XEMXTI.js} +7 -1
  50. package/dist/{chunk-AMFR5YA3.js → chunk-KKNLWXI6.js} +24 -10
  51. package/dist/{chunk-JWHCJDCI.js → chunk-KY56HMHH.js} +145 -61
  52. package/dist/{chunk-E3NYWENM.js → chunk-LU4TK2PR.js} +52 -7
  53. package/dist/{chunk-UWIJNAOB.js → chunk-M5T5VO65.js} +109 -42
  54. package/dist/{chunk-JPOWPFCU.js → chunk-MAR7Y6HW.js} +38 -16
  55. package/dist/chunk-N6F52NLF.js +6951 -0
  56. package/dist/{chunk-UHTSULZS.js → chunk-NMOX6HFD.js} +20 -7
  57. package/dist/{chunk-WD6AJM35.js → chunk-OLBBMFRD.js} +30 -13
  58. package/dist/{chunk-VOO7NYPP.js → chunk-PFEFKVGL.js} +22 -6
  59. package/dist/{chunk-6CWDTGUC.js → chunk-PIUMUEMV.js} +7 -1
  60. package/dist/chunk-PV4JUBVJ.js +462 -0
  61. package/dist/{chunk-527KG6XR.js → chunk-Q3RUPKEJ.js} +22 -4
  62. package/dist/{chunk-D5YD55AR.js → chunk-Q5WJOSJ7.js} +11 -1
  63. package/dist/{chunk-5N2FG33Q.js → chunk-R346GLFC.js} +7 -1
  64. package/dist/{chunk-4UQA7NCT.js → chunk-R5KLMSBV.js} +7 -2
  65. package/dist/{chunk-PIDUD6M2.js → chunk-RDLVBZEO.js} +11 -6
  66. package/dist/{chunk-O4EJEDHO.js → chunk-RPTR2H26.js} +40 -31
  67. package/dist/{chunk-HBU5MTAM.js → chunk-SVNXH4L2.js} +7 -1
  68. package/dist/{chunk-XNISANGE.js → chunk-TEKV33Q5.js} +122 -57
  69. package/dist/chunk-TXOTCRLG.js +15 -0
  70. package/dist/{chunk-VPAWTYLY.js → chunk-WEPFGWHJ.js} +7 -1
  71. package/dist/{chunk-HMYNFFY4.js → chunk-XPLRXC72.js} +7 -2
  72. package/dist/{chunk-UU3R62TT.js → chunk-XYWBQRDM.js} +13 -4
  73. package/dist/{chunk-7BHLZB3A.js → chunk-ZPY3JZ5E.js} +32 -10
  74. package/dist/cli/index.js +39 -33
  75. package/dist/clio-BZVGEUFJ.js +58 -0
  76. package/dist/{components-JVHMUBEB.js → components-DMAOEKFB.js} +26 -9
  77. package/dist/{config-ZFCDBMDC.js → config-IRUQ7SE4.js} +42 -31
  78. package/dist/configure-S7S6F6CL.js +32 -0
  79. package/dist/{context-CDXTP2MP.js → context-3KWFLHJG.js} +17 -11
  80. package/dist/{context-E3KIFVXI.js → context-5RADCKTR.js} +33 -28
  81. package/dist/{context-clear-3F4PLXOS.js → context-clear-7TSNPAAI.js} +36 -28
  82. package/dist/{context-index-Q7YSYTR3.js → context-index-W4RLWOQH.js} +10 -4
  83. package/dist/{docs-YIETIWZI.js → docs-5AWSPS37.js} +16 -10
  84. package/dist/doctor-UC5NAJYQ.js +77 -0
  85. package/dist/{eval-B3KZZESM.js → eval-U6TJHRLX.js} +77 -24
  86. package/dist/{evidence-V67CHM35.js → evidence-YEGUW4L3.js} +34 -26
  87. package/dist/{evolve-YDZSUQYA.js → evolve-TXARCTPG.js} +39 -26
  88. package/dist/{extensions-SRG7XCAH.js → extensions-OZFJ3A3G.js} +13 -7
  89. package/dist/{fleet-CA2CRTVG.js → fleet-6G3DHNYE.js} +45 -37
  90. package/dist/fleet-preflight-DSNT37JK.js +23 -0
  91. package/dist/{init-2OZDJE2D.js → init-KZ5QTF6M.js} +42 -34
  92. package/dist/{memory-3PIQQAKX.js → memory-73ESV5YC.js} +35 -27
  93. package/dist/{models-DY35XI7Y.js → models-A4PVNWJK.js} +34 -23
  94. package/dist/{paths-5OMXW7Z4.js → paths-C4H6IV77.js} +12 -6
  95. package/dist/preload-6WVMHX3A.js +13 -0
  96. package/dist/{reset-PIFYNOS3.js → reset-BGW6OGMV.js} +17 -11
  97. package/dist/{run-3VSPP24F.js → run-YTPEYQOH.js} +60 -48
  98. package/dist/{share-D36RQCXM.js → share-YIFFV4NQ.js} +16 -10
  99. package/dist/{skills-F2MRLELY.js → skills-2V6RA3OQ.js} +18 -11
  100. package/dist/{skills-eval-E2ZTW4PL.js → skills-eval-S2TVJO4F.js} +45 -36
  101. package/dist/{targets-DZMEZAH4.js → targets-TYXLPB23.js} +61 -59
  102. package/dist/{trace-7NYCUI2J.js → trace-GGOJ6Q6Z.js} +9 -3
  103. package/dist/{uninstall-AD3JWHBB.js → uninstall-LLLT4F4W.js} +14 -8
  104. package/dist/{upgrade-WYYBKGDY.js → upgrade-33G2LMM5.js} +45 -23
  105. package/dist/{usage-ULIDAGFF.js → usage-ZAFSXKKG.js} +35 -27
  106. package/dist/version-KGEG7EPO.js +21 -0
  107. package/dist/{wiki-generate-PKFIX6OB.js → wiki-generate-NUQCVOQ3.js} +55 -45
  108. package/dist/worker/entry.js +101 -43
  109. package/docs/README.md +12 -9
  110. package/docs/acp.md +28 -5
  111. package/docs/alcf-provider.md +1 -1
  112. package/docs/architecture.md +23 -2
  113. package/docs/artifact-placement.md +101 -0
  114. package/docs/artifact-versions.md +1 -1
  115. package/docs/built-in-agents.md +4 -2
  116. package/docs/capacity-and-scheduling.md +1 -1
  117. package/docs/commands-and-modes.md +125 -41
  118. package/docs/configuration-and-targets.md +88 -18
  119. package/docs/context-engine.md +6 -2
  120. package/docs/development-pipeline.md +77 -0
  121. package/docs/documentation-coverage.md +4 -4
  122. package/docs/documentation-guide.md +3 -3
  123. package/docs/environment-variables.md +2 -1
  124. package/docs/eval-runner.md +3 -3
  125. package/docs/evals-internal.md +2 -2
  126. package/docs/evidence-and-memory.md +6 -2
  127. package/docs/evolution.md +1 -1
  128. package/docs/exit-codes-and-output.md +1 -1
  129. package/docs/extensions-and-sharing.md +18 -11
  130. package/docs/fleet-demo-runbook.md +22 -23
  131. package/docs/fleet-dispatch.md +111 -12
  132. package/docs/glossary.md +107 -15
  133. package/docs/html/agents_blueprint.html +3 -3
  134. package/docs/html/alcf_blueprint.html +3 -3
  135. package/docs/html/architecture_blueprint.html +3 -3
  136. package/docs/html/commands_blueprint.html +187 -42
  137. package/docs/html/configuration_blueprint.html +7 -7
  138. package/docs/html/context_blueprint.html +3 -3
  139. package/docs/html/documentation_blueprint.html +1 -1
  140. package/docs/html/environment_blueprint.html +3 -3
  141. package/docs/html/eval_blueprint.html +4 -4
  142. package/docs/html/evals_internal_blueprint.html +3 -3
  143. package/docs/html/evolution_blueprint.html +3 -3
  144. package/docs/html/extensions_blueprint.html +3 -3
  145. package/docs/html/fleet_dispatch_blueprint.html +8 -8
  146. package/docs/html/index.html +5 -5
  147. package/docs/html/lifecycle_blueprint.html +4 -4
  148. package/docs/html/memory_blueprint.html +3 -3
  149. package/docs/html/middleware_blueprint.html +3 -3
  150. package/docs/html/models_blueprint.html +2 -2
  151. package/docs/html/observability_blueprint.html +2 -2
  152. package/docs/html/provider_adapter_blueprint.html +3 -3
  153. package/docs/html/safety_blueprint.html +3 -3
  154. package/docs/html/skills_blueprint.html +2 -2
  155. package/docs/html/soak_blueprint.html +3 -3
  156. package/docs/html/tool_usage_blueprint.html +4 -4
  157. package/docs/html/tools_blueprint.html +2 -2
  158. package/docs/html/trace_blueprint.html +3 -3
  159. package/docs/html/tui_design_blueprint.html +100 -40
  160. package/docs/html/validation_blueprint.html +1 -1
  161. package/docs/html/worker_dispatch_blueprint.html +3 -3
  162. package/docs/installation-and-lifecycle.md +62 -11
  163. package/docs/middleware-and-components.md +1 -1
  164. package/docs/model-catalog.md +2 -2
  165. package/docs/observability.md +3 -3
  166. package/docs/proactive-memory.md +12 -12
  167. package/docs/prompt-envelope-and-tools.md +2 -2
  168. package/docs/provider-adapter-cookbook.md +1 -1
  169. package/docs/release-cut-checklist.md +4 -0
  170. package/docs/safety-model.md +21 -5
  171. package/docs/scientific-validation.md +3 -3
  172. package/docs/session-lifecycle.md +2 -2
  173. package/docs/skills-marketplace.md +1 -1
  174. package/docs/time-conventions.md +101 -0
  175. package/docs/tool-usage.md +5 -4
  176. package/docs/trace-store.md +1 -1
  177. package/docs/troubleshooting.md +1 -1
  178. package/docs/tui-design.md +83 -27
  179. package/docs/worker-dispatch-mechanics.md +3 -3
  180. package/package.json +16 -16
  181. package/skills/README.md +5 -6
  182. package/skills/git/file-ticket/SKILL.md +107 -0
  183. package/skills/git/file-ticket/evals.md +54 -0
  184. package/skills/git/fix-issue/SKILL.md +106 -0
  185. package/skills/git/fix-issue/evals.md +71 -0
  186. package/skills/git/ship/SKILL.md +92 -0
  187. package/skills/git/ship/evals.md +72 -0
  188. package/skills/skill-marketplace.json +12 -20
  189. package/src/cli/acp.ts +88 -0
  190. package/src/cli/agents.ts +60 -0
  191. package/src/cli/args.ts +280 -0
  192. package/src/cli/argv.ts +170 -0
  193. package/src/cli/ask.ts +34 -0
  194. package/src/cli/auth.ts +468 -0
  195. package/src/cli/bootstrap-generate.ts +498 -0
  196. package/src/cli/clio.ts +34 -0
  197. package/src/cli/components.ts +195 -0
  198. package/src/cli/config-inspect.ts +330 -0
  199. package/src/cli/config.ts +72 -0
  200. package/src/cli/configure-interop.ts +67 -0
  201. package/src/cli/configure-layout.ts +172 -0
  202. package/src/cli/configure.ts +1487 -0
  203. package/src/cli/context-clear.ts +76 -0
  204. package/src/cli/context-index.ts +102 -0
  205. package/src/cli/context.ts +316 -0
  206. package/src/cli/default-target.ts +63 -0
  207. package/src/cli/docs.ts +340 -0
  208. package/src/cli/doctor.ts +54 -0
  209. package/src/cli/eval.ts +315 -0
  210. package/src/cli/evidence.ts +222 -0
  211. package/src/cli/evolve.ts +219 -0
  212. package/src/cli/extensions.ts +205 -0
  213. package/src/cli/fleet.ts +827 -0
  214. package/src/cli/index.ts +309 -0
  215. package/src/cli/init.ts +219 -0
  216. package/src/cli/initial-message.ts +47 -0
  217. package/src/cli/internal-dispatch.ts +55 -0
  218. package/src/cli/memory.ts +180 -0
  219. package/src/cli/models.ts +257 -0
  220. package/src/cli/modes/json-stream.ts +85 -0
  221. package/src/cli/modes/jsonl.ts +9 -0
  222. package/src/cli/modes/print.ts +589 -0
  223. package/src/cli/oauth-manual-input.ts +72 -0
  224. package/src/cli/oauth-select.ts +36 -0
  225. package/src/cli/output-guard.ts +48 -0
  226. package/src/cli/paths.ts +44 -0
  227. package/src/cli/provider-target.ts +113 -0
  228. package/src/cli/removal.ts +72 -0
  229. package/src/cli/reset.ts +253 -0
  230. package/src/cli/run.ts +497 -0
  231. package/src/cli/share.ts +243 -0
  232. package/src/cli/shared.ts +60 -0
  233. package/src/cli/skills-eval.ts +1225 -0
  234. package/src/cli/skills.ts +470 -0
  235. package/src/cli/steer-channel.ts +86 -0
  236. package/src/cli/targets.ts +1150 -0
  237. package/src/cli/text-layout.ts +102 -0
  238. package/src/cli/trace.ts +274 -0
  239. package/src/cli/uninstall.ts +405 -0
  240. package/src/cli/upgrade.ts +270 -0
  241. package/src/cli/usage.ts +869 -0
  242. package/src/cli/validate-model.ts +28 -0
  243. package/src/cli/version.ts +7 -0
  244. package/src/cli/wiki-generate.ts +509 -0
  245. package/src/core/artifact-paths.ts +43 -0
  246. package/src/core/bash-exec.ts +242 -0
  247. package/src/core/boot-trace.ts +37 -0
  248. package/src/core/bus-events.ts +728 -0
  249. package/src/core/bus-trace.ts +53 -0
  250. package/src/core/c-header-language.ts +265 -0
  251. package/src/core/clio-repo.ts +78 -0
  252. package/src/core/config.ts +1593 -0
  253. package/src/core/context-floor.ts +33 -0
  254. package/src/core/defaults.ts +625 -0
  255. package/src/core/domain-loader.ts +170 -0
  256. package/src/core/event-bus.ts +94 -0
  257. package/src/core/file-references.ts +282 -0
  258. package/src/core/guardrails.ts +185 -0
  259. package/src/core/headless-permission.ts +21 -0
  260. package/src/core/init.ts +223 -0
  261. package/src/core/json-payload.ts +58 -0
  262. package/src/core/package-root.ts +54 -0
  263. package/src/core/path-canonical.ts +37 -0
  264. package/src/core/process-identity.ts +41 -0
  265. package/src/core/recent-models.ts +91 -0
  266. package/src/core/release.ts +2 -0
  267. package/src/core/residency-protection.ts +56 -0
  268. package/src/core/resolve-config-value.ts +88 -0
  269. package/src/core/response-schema.ts +279 -0
  270. package/src/core/run-overrides.ts +77 -0
  271. package/src/core/safe-exec.ts +193 -0
  272. package/src/core/safe-id.ts +37 -0
  273. package/src/core/safe-resource-write.ts +162 -0
  274. package/src/core/session-routing.ts +339 -0
  275. package/src/core/settings-layers.ts +220 -0
  276. package/src/core/shared-bus.ts +8 -0
  277. package/src/core/shell-quote.ts +26 -0
  278. package/src/core/skill-activation.ts +190 -0
  279. package/src/core/startup-timer.ts +37 -0
  280. package/src/core/state-file-lock.ts +207 -0
  281. package/src/core/termination.ts +202 -0
  282. package/src/core/timers.ts +38 -0
  283. package/src/core/tool-names.ts +65 -0
  284. package/src/core/verification-scripts.ts +13 -0
  285. package/src/core/workspace-files.ts +492 -0
  286. package/src/core/xdg.ts +177 -0
  287. package/src/domains/agents/builtins/architect.md +4 -4
  288. package/src/domains/agents/builtins/coder.md +3 -2
  289. package/src/domains/agents/builtins/debugger.md +1 -1
  290. package/src/domains/agents/builtins/documenter.md +1 -1
  291. package/src/domains/agents/builtins/git-master.md +3 -3
  292. package/src/domains/agents/builtins/provenance.md +1 -1
  293. package/src/domains/agents/builtins/researcher.md +1 -1
  294. package/src/domains/agents/builtins/scout.md +1 -1
  295. package/src/domains/agents/builtins/tester.md +1 -1
  296. package/src/domains/agents/builtins/verifier.md +1 -1
  297. package/src/domains/agents/builtins/wiki-writer.md +1 -1
  298. package/src/domains/agents/catalog.ts +172 -0
  299. package/src/domains/agents/contract.ts +16 -0
  300. package/src/domains/agents/extension.ts +110 -0
  301. package/src/domains/agents/fleet-commands.ts +154 -0
  302. package/src/domains/agents/fleet-contract.ts +797 -0
  303. package/src/domains/agents/frontmatter.ts +40 -0
  304. package/src/domains/agents/index.ts +102 -0
  305. package/src/domains/agents/manifest.ts +6 -0
  306. package/src/domains/agents/recipe-schema.ts +202 -0
  307. package/src/domains/agents/recipe.ts +125 -0
  308. package/src/domains/agents/registry.ts +111 -0
  309. package/src/domains/agents/result-contract.ts +1265 -0
  310. package/src/domains/agents/spec.ts +371 -0
  311. package/src/domains/agents/write-boundary.ts +109 -0
  312. package/src/domains/components/diff.ts +99 -0
  313. package/src/domains/components/hash.ts +21 -0
  314. package/src/domains/components/index.ts +3 -0
  315. package/src/domains/components/scan.ts +304 -0
  316. package/src/domains/components/snapshot.ts +108 -0
  317. package/src/domains/components/types.ts +82 -0
  318. package/src/domains/config/agent-namespace.ts +13 -0
  319. package/src/domains/config/classify.ts +94 -0
  320. package/src/domains/config/contract.ts +22 -0
  321. package/src/domains/config/extension.ts +136 -0
  322. package/src/domains/config/index.ts +13 -0
  323. package/src/domains/config/keybindings.ts +164 -0
  324. package/src/domains/config/manifest.ts +6 -0
  325. package/src/domains/config/watcher.ts +41 -0
  326. package/src/domains/context/adoption.ts +880 -0
  327. package/src/domains/context/bootstrap-prompt.ts +273 -0
  328. package/src/domains/context/bootstrap.ts +1409 -0
  329. package/src/domains/context/clear.ts +86 -0
  330. package/src/domains/context/clio-md.ts +327 -0
  331. package/src/domains/context/codewiki/cmake.ts +356 -0
  332. package/src/domains/context/codewiki/cooperative.ts +46 -0
  333. package/src/domains/context/codewiki/digest.ts +135 -0
  334. package/src/domains/context/codewiki/grammar-assets.ts +33 -0
  335. package/src/domains/context/codewiki/indexer.ts +1614 -0
  336. package/src/domains/context/codewiki/tree-sitter.ts +771 -0
  337. package/src/domains/context/contract.ts +62 -0
  338. package/src/domains/context/excluded-dirs.ts +1 -0
  339. package/src/domains/context/extension.ts +407 -0
  340. package/src/domains/context/fingerprint.ts +196 -0
  341. package/src/domains/context/index.ts +164 -0
  342. package/src/domains/context/init-options.ts +69 -0
  343. package/src/domains/context/manifest.ts +6 -0
  344. package/src/domains/context/operator-profile.ts +157 -0
  345. package/src/domains/context/project-metadata.ts +510 -0
  346. package/src/domains/context/project-rules.ts +227 -0
  347. package/src/domains/context/prompt-context.ts +62 -0
  348. package/src/domains/context/refresh.ts +170 -0
  349. package/src/domains/context/sibling-files.ts +10 -0
  350. package/src/domains/context/state.ts +237 -0
  351. package/src/domains/context/wiki/assemble.ts +303 -0
  352. package/src/domains/context/wiki/frontmatter.ts +210 -0
  353. package/src/domains/context/wiki/generate.ts +590 -0
  354. package/src/domains/context/wiki/layout.ts +111 -0
  355. package/src/domains/context/wiki/meta.ts +221 -0
  356. package/src/domains/context/wiki/plan-store.ts +217 -0
  357. package/src/domains/context/wiki/plan.ts +250 -0
  358. package/src/domains/context/wiki/prompts.ts +270 -0
  359. package/src/domains/context/wiki/staleness.ts +198 -0
  360. package/src/domains/dispatch/active-route-planner.ts +168 -0
  361. package/src/domains/dispatch/admission-queue.ts +150 -0
  362. package/src/domains/dispatch/admission.ts +334 -0
  363. package/src/domains/dispatch/agent-candidates.ts +307 -0
  364. package/src/domains/dispatch/agent-ledger-hub.ts +71 -0
  365. package/src/domains/dispatch/agent-ledger-store.ts +257 -0
  366. package/src/domains/dispatch/agent-ledger.ts +212 -0
  367. package/src/domains/dispatch/agent-plan-adapter.ts +85 -0
  368. package/src/domains/dispatch/assignment-events.ts +132 -0
  369. package/src/domains/dispatch/assignment-reconcile.ts +76 -0
  370. package/src/domains/dispatch/assignment-store.ts +162 -0
  371. package/src/domains/dispatch/assignment.ts +278 -0
  372. package/src/domains/dispatch/backoff.ts +59 -0
  373. package/src/domains/dispatch/batch-store.ts +134 -0
  374. package/src/domains/dispatch/batch-tracker.ts +66 -0
  375. package/src/domains/dispatch/capability-match.ts +155 -0
  376. package/src/domains/dispatch/capacity-lease.ts +413 -0
  377. package/src/domains/dispatch/code-step-store.ts +52 -0
  378. package/src/domains/dispatch/code-step.ts +368 -0
  379. package/src/domains/dispatch/contract.ts +278 -0
  380. package/src/domains/dispatch/dedup.ts +133 -0
  381. package/src/domains/dispatch/event-pump.ts +251 -0
  382. package/src/domains/dispatch/execution-handoff.ts +29 -0
  383. package/src/domains/dispatch/execution-plan.ts +328 -0
  384. package/src/domains/dispatch/execution-role.ts +277 -0
  385. package/src/domains/dispatch/execution-scheduler.ts +583 -0
  386. package/src/domains/dispatch/extension.ts +5869 -0
  387. package/src/domains/dispatch/failure-classification.ts +141 -0
  388. package/src/domains/dispatch/fleet-plan.ts +225 -0
  389. package/src/domains/dispatch/fleet-preflight.ts +394 -0
  390. package/src/domains/dispatch/gate-decisions.ts +1040 -0
  391. package/src/domains/dispatch/gate-role-prompts.ts +58 -0
  392. package/src/domains/dispatch/heartbeat.ts +27 -0
  393. package/src/domains/dispatch/index.ts +137 -0
  394. package/src/domains/dispatch/joint-route-adapter.ts +114 -0
  395. package/src/domains/dispatch/joint-route-resolver.ts +283 -0
  396. package/src/domains/dispatch/manifest.ts +6 -0
  397. package/src/domains/dispatch/orphan-recovery.ts +224 -0
  398. package/src/domains/dispatch/outcome.ts +109 -0
  399. package/src/domains/dispatch/phase-timing.ts +47 -0
  400. package/src/domains/dispatch/placement.ts +202 -0
  401. package/src/domains/dispatch/receipt-findings.ts +255 -0
  402. package/src/domains/dispatch/receipt-integrity.ts +378 -0
  403. package/src/domains/dispatch/recovery-candidates.ts +74 -0
  404. package/src/domains/dispatch/reproducibility.ts +48 -0
  405. package/src/domains/dispatch/reservation-store.ts +501 -0
  406. package/src/domains/dispatch/route-approval.ts +177 -0
  407. package/src/domains/dispatch/route-candidates.ts +57 -0
  408. package/src/domains/dispatch/route-decision.ts +1079 -0
  409. package/src/domains/dispatch/route-facts.ts +187 -0
  410. package/src/domains/dispatch/route-history.ts +238 -0
  411. package/src/domains/dispatch/route-observer.ts +488 -0
  412. package/src/domains/dispatch/route-policy.ts +327 -0
  413. package/src/domains/dispatch/route-quality.ts +256 -0
  414. package/src/domains/dispatch/route-readiness.ts +120 -0
  415. package/src/domains/dispatch/routing-intent.ts +287 -0
  416. package/src/domains/dispatch/run-identity.ts +56 -0
  417. package/src/domains/dispatch/scout-transition.ts +130 -0
  418. package/src/domains/dispatch/state.ts +277 -0
  419. package/src/domains/dispatch/tool-stats.ts +132 -0
  420. package/src/domains/dispatch/transport.ts +209 -0
  421. package/src/domains/dispatch/types.ts +785 -0
  422. package/src/domains/dispatch/validation-grounding.ts +154 -0
  423. package/src/domains/dispatch/validation.ts +721 -0
  424. package/src/domains/dispatch/worker-protocol.ts +275 -0
  425. package/src/domains/dispatch/worker-spawn.ts +566 -0
  426. package/src/domains/dispatch/write-boundary-enforcer.ts +97 -0
  427. package/src/domains/dispatch/write-boundary.ts +426 -0
  428. package/src/domains/eval/artifacts/redact.ts +42 -0
  429. package/src/domains/eval/artifacts/store.ts +173 -0
  430. package/src/domains/eval/compare/compare.ts +33 -0
  431. package/src/domains/eval/compare/gates.ts +66 -0
  432. package/src/domains/eval/compare/thresholds.ts +92 -0
  433. package/src/domains/eval/harness-metrics.ts +62 -0
  434. package/src/domains/eval/index.ts +66 -0
  435. package/src/domains/eval/metrics/chaos-stream.ts +93 -0
  436. package/src/domains/eval/metrics/context.ts +34 -0
  437. package/src/domains/eval/metrics/coverage.ts +21 -0
  438. package/src/domains/eval/metrics/evidence.ts +182 -0
  439. package/src/domains/eval/metrics/fleet-loop-stream.ts +196 -0
  440. package/src/domains/eval/metrics/invariants.ts +736 -0
  441. package/src/domains/eval/metrics/latency.ts +4 -0
  442. package/src/domains/eval/metrics/token-stream.ts +139 -0
  443. package/src/domains/eval/metrics/tokens.ts +51 -0
  444. package/src/domains/eval/metrics/tool-calls.ts +7 -0
  445. package/src/domains/eval/proactive-memory.ts +279 -0
  446. package/src/domains/eval/provenance.ts +35 -0
  447. package/src/domains/eval/report.ts +234 -0
  448. package/src/domains/eval/reports/json.ts +5 -0
  449. package/src/domains/eval/reports/junit.ts +23 -0
  450. package/src/domains/eval/reports/markdown.ts +20 -0
  451. package/src/domains/eval/reports/swe-jsonl.ts +16 -0
  452. package/src/domains/eval/reports/text.ts +25 -0
  453. package/src/domains/eval/run-compare.ts +274 -0
  454. package/src/domains/eval/runner.ts +244 -0
  455. package/src/domains/eval/runners/clio-run.ts +148 -0
  456. package/src/domains/eval/runners/context-index.ts +56 -0
  457. package/src/domains/eval/runners/context-init.ts +203 -0
  458. package/src/domains/eval/runners/external-command.ts +350 -0
  459. package/src/domains/eval/runtime-paths.ts +171 -0
  460. package/src/domains/eval/schema/artifact.ts +75 -0
  461. package/src/domains/eval/schema/suite.ts +235 -0
  462. package/src/domains/eval/schema/validate.ts +339 -0
  463. package/src/domains/eval/store.ts +392 -0
  464. package/src/domains/eval/suites/load.ts +74 -0
  465. package/src/domains/eval/suites/matrix.ts +19 -0
  466. package/src/domains/eval/suites/resolve.ts +44 -0
  467. package/src/domains/eval/suites/run.ts +325 -0
  468. package/src/domains/eval/task-file.ts +186 -0
  469. package/src/domains/eval/types.ts +141 -0
  470. package/src/domains/eval/verifiers/command.ts +27 -0
  471. package/src/domains/eval/verifiers/file-exists.ts +6 -0
  472. package/src/domains/eval/verifiers/patch.ts +22 -0
  473. package/src/domains/eval/workspaces/git.ts +41 -0
  474. package/src/domains/eval/workspaces/local.ts +17 -0
  475. package/src/domains/eval/workspaces/temp-copy.ts +29 -0
  476. package/src/domains/evidence/build.ts +1714 -0
  477. package/src/domains/evidence/eval.ts +605 -0
  478. package/src/domains/evidence/failure-attribution.ts +54 -0
  479. package/src/domains/evidence/finish-contract-map.ts +42 -0
  480. package/src/domains/evidence/index.ts +55 -0
  481. package/src/domains/evidence/provenance.ts +200 -0
  482. package/src/domains/evidence/redact.ts +81 -0
  483. package/src/domains/evidence/store.ts +291 -0
  484. package/src/domains/evidence/types.ts +325 -0
  485. package/src/domains/evolution/SELF_EDIT_GATE.md +91 -0
  486. package/src/domains/evolution/index.ts +26 -0
  487. package/src/domains/evolution/manifest.ts +154 -0
  488. package/src/domains/evolution/validate.ts +304 -0
  489. package/src/domains/extensions/contract.ts +22 -0
  490. package/src/domains/extensions/discovery.ts +193 -0
  491. package/src/domains/extensions/extension.ts +46 -0
  492. package/src/domains/extensions/index.ts +34 -0
  493. package/src/domains/extensions/manager.ts +30 -0
  494. package/src/domains/extensions/manifest.ts +6 -0
  495. package/src/domains/extensions/resources.ts +38 -0
  496. package/src/domains/extensions/state.ts +224 -0
  497. package/src/domains/extensions/types.ts +83 -0
  498. package/src/domains/interop/consent.ts +185 -0
  499. package/src/domains/interop/contract.ts +29 -0
  500. package/src/domains/interop/detect.ts +173 -0
  501. package/src/domains/interop/extension.ts +59 -0
  502. package/src/domains/interop/index.ts +34 -0
  503. package/src/domains/interop/manifest.ts +6 -0
  504. package/src/domains/interop/registry.ts +139 -0
  505. package/src/domains/interop/state.ts +92 -0
  506. package/src/domains/interop/types.ts +109 -0
  507. package/src/domains/lifecycle/contract.ts +11 -0
  508. package/src/domains/lifecycle/doctor.ts +536 -0
  509. package/src/domains/lifecycle/extension.ts +23 -0
  510. package/src/domains/lifecycle/index.ts +21 -0
  511. package/src/domains/lifecycle/install-method.ts +51 -0
  512. package/src/domains/lifecycle/manifest.ts +6 -0
  513. package/src/domains/lifecycle/migrations/index.ts +94 -0
  514. package/src/domains/lifecycle/state.ts +93 -0
  515. package/src/domains/lifecycle/upgrade-notice.ts +35 -0
  516. package/src/domains/lifecycle/version.ts +35 -0
  517. package/src/domains/memory/index.ts +128 -0
  518. package/src/domains/memory/operations.ts +143 -0
  519. package/src/domains/memory/prompt-section.ts +86 -0
  520. package/src/domains/memory/proposal.ts +180 -0
  521. package/src/domains/memory/store.ts +163 -0
  522. package/src/domains/memory/task-bank.ts +229 -0
  523. package/src/domains/memory/task-memory-handoff.ts +222 -0
  524. package/src/domains/memory/task-memory-policy.ts +602 -0
  525. package/src/domains/memory/task-memory-status.ts +58 -0
  526. package/src/domains/memory/task-memory-telemetry.ts +346 -0
  527. package/src/domains/memory/task-memory-trace.ts +89 -0
  528. package/src/domains/memory/types.ts +74 -0
  529. package/src/domains/memory/validate.ts +297 -0
  530. package/src/domains/middleware/budget.ts +216 -0
  531. package/src/domains/middleware/contract.ts +35 -0
  532. package/src/domains/middleware/dispatch-nudge.ts +469 -0
  533. package/src/domains/middleware/extension.ts +129 -0
  534. package/src/domains/middleware/hook-receipts.ts +70 -0
  535. package/src/domains/middleware/hooks-io.ts +174 -0
  536. package/src/domains/middleware/hooks.ts +432 -0
  537. package/src/domains/middleware/index.ts +154 -0
  538. package/src/domains/middleware/manifest.ts +6 -0
  539. package/src/domains/middleware/memory-intervention.ts +701 -0
  540. package/src/domains/middleware/rules.ts +42 -0
  541. package/src/domains/middleware/runtime.ts +333 -0
  542. package/src/domains/middleware/skills-reminder.ts +187 -0
  543. package/src/domains/middleware/snapshot.ts +71 -0
  544. package/src/domains/middleware/stalled-turn.ts +71 -0
  545. package/src/domains/middleware/task-board-reminder.ts +87 -0
  546. package/src/domains/middleware/task-nudge.ts +77 -0
  547. package/src/domains/middleware/tool-choice-control.ts +42 -0
  548. package/src/domains/middleware/types.ts +131 -0
  549. package/src/domains/middleware/validate.ts +329 -0
  550. package/src/domains/observability/accountability.ts +67 -0
  551. package/src/domains/observability/contract.ts +168 -0
  552. package/src/domains/observability/cost.ts +206 -0
  553. package/src/domains/observability/evidence-index.ts +123 -0
  554. package/src/domains/observability/extension.ts +281 -0
  555. package/src/domains/observability/index.ts +78 -0
  556. package/src/domains/observability/manifest.ts +10 -0
  557. package/src/domains/observability/metrics.ts +37 -0
  558. package/src/domains/observability/projection.ts +477 -0
  559. package/src/domains/observability/telemetry.ts +89 -0
  560. package/src/domains/observability/trace-store.ts +1454 -0
  561. package/src/domains/prompts/compiler.ts +556 -0
  562. package/src/domains/prompts/contract.ts +30 -0
  563. package/src/domains/prompts/extension.ts +304 -0
  564. package/src/domains/prompts/fragment-loader.ts +139 -0
  565. package/src/domains/prompts/fragments/identity/clio.md +3 -2
  566. package/src/domains/prompts/fragments/identity/self-awareness.md +63 -0
  567. package/src/domains/prompts/fragments/operating/contract.md +10 -1
  568. package/src/domains/prompts/hash.ts +73 -0
  569. package/src/domains/prompts/index.ts +32 -0
  570. package/src/domains/prompts/manifest.ts +8 -0
  571. package/src/domains/prompts/memory-intervention.ts +57 -0
  572. package/src/domains/prompts/preload.ts +82 -0
  573. package/src/domains/providers/auth/api-key.ts +47 -0
  574. package/src/domains/providers/auth/backend-file.ts +69 -0
  575. package/src/domains/providers/auth/backend-memory.ts +17 -0
  576. package/src/domains/providers/auth/index.ts +37 -0
  577. package/src/domains/providers/auth/oauth.ts +36 -0
  578. package/src/domains/providers/auth/storage.ts +667 -0
  579. package/src/domains/providers/capabilities.ts +50 -0
  580. package/src/domains/providers/catalog.ts +162 -0
  581. package/src/domains/providers/contract.ts +151 -0
  582. package/src/domains/providers/credentials.ts +20 -0
  583. package/src/domains/providers/eligibility.ts +24 -0
  584. package/src/domains/providers/errors.ts +64 -0
  585. package/src/domains/providers/extension.ts +536 -0
  586. package/src/domains/providers/index.ts +142 -0
  587. package/src/domains/providers/knowledge-base-path.ts +102 -0
  588. package/src/domains/providers/manifest.ts +6 -0
  589. package/src/domains/providers/model-capabilities.ts +136 -0
  590. package/src/domains/providers/model-discovery.ts +144 -0
  591. package/src/domains/providers/model-family.ts +32 -0
  592. package/src/domains/providers/model-runtime-capabilities.ts +712 -0
  593. package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +2 -2
  594. package/src/domains/providers/plugins.ts +59 -0
  595. package/src/domains/providers/probe/fingerprint.ts +44 -0
  596. package/src/domains/providers/probe/http.ts +114 -0
  597. package/src/domains/providers/probe/reasoning.ts +111 -0
  598. package/src/domains/providers/registry.ts +166 -0
  599. package/src/domains/providers/resolver.ts +156 -0
  600. package/src/domains/providers/runtime-resolution.ts +720 -0
  601. package/src/domains/providers/runtimes/antigravity/antigravity-code.ts +90 -0
  602. package/src/domains/providers/runtimes/builtins.ts +78 -0
  603. package/src/domains/providers/runtimes/claude/claude-code.ts +38 -0
  604. package/src/domains/providers/runtimes/claude/claude-sdk.ts +38 -0
  605. package/src/domains/providers/runtimes/claude/common.ts +55 -0
  606. package/src/domains/providers/runtimes/cloud/alcf.ts +171 -0
  607. package/src/domains/providers/runtimes/cloud/anthropic-max.ts +71 -0
  608. package/src/domains/providers/runtimes/cloud/anthropic.ts +43 -0
  609. package/src/domains/providers/runtimes/cloud/bedrock.ts +35 -0
  610. package/src/domains/providers/runtimes/cloud/deepseek.ts +50 -0
  611. package/src/domains/providers/runtimes/cloud/google.ts +41 -0
  612. package/src/domains/providers/runtimes/cloud/groq.ts +46 -0
  613. package/src/domains/providers/runtimes/cloud/mistral.ts +46 -0
  614. package/src/domains/providers/runtimes/cloud/openai-codex.ts +49 -0
  615. package/src/domains/providers/runtimes/cloud/openai.ts +46 -0
  616. package/src/domains/providers/runtimes/cloud/openrouter.ts +111 -0
  617. package/src/domains/providers/runtimes/common/lmstudio-logger.ts +32 -0
  618. package/src/domains/providers/runtimes/common/local-synth.ts +165 -0
  619. package/src/domains/providers/runtimes/common/probe-helpers.ts +474 -0
  620. package/src/domains/providers/runtimes/local-native/lemonade-anthropic.ts +27 -0
  621. package/src/domains/providers/runtimes/local-native/lemonade-openai.ts +26 -0
  622. package/src/domains/providers/runtimes/local-native/llamacpp-anthropic.ts +88 -0
  623. package/src/domains/providers/runtimes/local-native/llamacpp-completion.ts +207 -0
  624. package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +180 -0
  625. package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +126 -0
  626. package/src/domains/providers/runtimes/local-native/llamacpp.ts +98 -0
  627. package/src/domains/providers/runtimes/local-native/lmstudio-native.ts +491 -0
  628. package/src/domains/providers/runtimes/local-native/ollama-native.ts +117 -0
  629. package/src/domains/providers/runtimes/local-native/sglang.ts +26 -0
  630. package/src/domains/providers/runtimes/local-native/vllm.ts +27 -0
  631. package/src/domains/providers/runtimes/protocol/anthropic-compat.ts +104 -0
  632. package/src/domains/providers/runtimes/protocol/anthropic-messages.ts +28 -0
  633. package/src/domains/providers/runtimes/protocol/bedrock.ts +26 -0
  634. package/src/domains/providers/runtimes/protocol/google.ts +27 -0
  635. package/src/domains/providers/runtimes/protocol/openai-compat.ts +145 -0
  636. package/src/domains/providers/support.ts +238 -0
  637. package/src/domains/providers/thinking-control-policy.ts +85 -0
  638. package/src/domains/providers/types/capability-flags.ts +114 -0
  639. package/src/domains/providers/types/cost-provenance.ts +7 -0
  640. package/src/domains/providers/types/inference.ts +41 -0
  641. package/src/domains/providers/types/knowledge-base.ts +156 -0
  642. package/src/domains/providers/types/local-model-quirks.ts +218 -0
  643. package/src/domains/providers/types/runtime-descriptor.ts +170 -0
  644. package/src/domains/providers/types/target-descriptor.ts +38 -0
  645. package/src/domains/resources/collision.ts +92 -0
  646. package/src/domains/resources/common-loader.ts +140 -0
  647. package/src/domains/resources/contract.ts +25 -0
  648. package/src/domains/resources/extension.ts +61 -0
  649. package/src/domains/resources/index.ts +74 -0
  650. package/src/domains/resources/loader.ts +86 -0
  651. package/src/domains/resources/manifest.ts +6 -0
  652. package/src/domains/resources/prompts/loader.ts +232 -0
  653. package/src/domains/resources/prompts/substitute.ts +65 -0
  654. package/src/domains/resources/skills/content-hash.ts +105 -0
  655. package/src/domains/resources/skills/evals.ts +175 -0
  656. package/src/domains/resources/skills/install.ts +410 -0
  657. package/src/domains/resources/skills/loader.ts +978 -0
  658. package/src/domains/resources/skills/marketplace.ts +255 -0
  659. package/src/domains/resources/skills/provenance-pin.ts +115 -0
  660. package/src/domains/safety/action-classifier.ts +268 -0
  661. package/src/domains/safety/approval-axis.ts +23 -0
  662. package/src/domains/safety/audit.ts +487 -0
  663. package/src/domains/safety/autonomy.ts +174 -0
  664. package/src/domains/safety/call-target.ts +59 -0
  665. package/src/domains/safety/contract.ts +65 -0
  666. package/src/domains/safety/damage-control.ts +44 -0
  667. package/src/domains/safety/default-path-policy.ts +117 -0
  668. package/src/domains/safety/extension.ts +383 -0
  669. package/src/domains/safety/finish-contract-registration.ts +128 -0
  670. package/src/domains/safety/finish-contract.ts +554 -0
  671. package/src/domains/safety/index.ts +44 -0
  672. package/src/domains/safety/loop-detector.ts +143 -0
  673. package/src/domains/safety/manifest.ts +6 -0
  674. package/src/domains/safety/path-policy.ts +164 -0
  675. package/src/domains/safety/policy-engine.ts +994 -0
  676. package/src/domains/safety/project-policy.ts +391 -0
  677. package/src/domains/safety/protected-artifacts-registration.ts +189 -0
  678. package/src/domains/safety/protected-artifacts.ts +993 -0
  679. package/src/domains/safety/rejection-feedback.ts +102 -0
  680. package/src/domains/safety/rigor.ts +72 -0
  681. package/src/domains/safety/rule-compiler.ts +48 -0
  682. package/src/domains/safety/rule-pack-loader.ts +92 -0
  683. package/src/domains/safety/run-effects.ts +197 -0
  684. package/src/domains/safety/scope.ts +61 -0
  685. package/src/domains/scheduling/budget.ts +35 -0
  686. package/src/domains/scheduling/cluster.ts +175 -0
  687. package/src/domains/scheduling/contract.ts +30 -0
  688. package/src/domains/scheduling/extension.ts +91 -0
  689. package/src/domains/scheduling/index.ts +12 -0
  690. package/src/domains/scheduling/manifest.ts +6 -0
  691. package/src/domains/session/archive-readers.ts +208 -0
  692. package/src/domains/session/checkpoint.ts +38 -0
  693. package/src/domains/session/compaction/auto.ts +89 -0
  694. package/src/domains/session/compaction/branch-summary.ts +186 -0
  695. package/src/domains/session/compaction/compact.ts +493 -0
  696. package/src/domains/session/compaction/cut-point.ts +171 -0
  697. package/src/domains/session/compaction/defaults.ts +34 -0
  698. package/src/domains/session/compaction/mask-observations.ts +265 -0
  699. package/src/domains/session/compaction/session-entries.ts +18 -0
  700. package/src/domains/session/compaction/tokens.ts +147 -0
  701. package/src/domains/session/context-accounting.ts +583 -0
  702. package/src/domains/session/context-ledger.ts +348 -0
  703. package/src/domains/session/contract.ts +144 -0
  704. package/src/domains/session/cwd-fallback.ts +65 -0
  705. package/src/domains/session/entries.ts +509 -0
  706. package/src/domains/session/extension.ts +322 -0
  707. package/src/domains/session/history.ts +172 -0
  708. package/src/domains/session/index.ts +84 -0
  709. package/src/domains/session/manager.ts +128 -0
  710. package/src/domains/session/manifest.ts +6 -0
  711. package/src/domains/session/migrations/index.ts +27 -0
  712. package/src/domains/session/prompt-manifest.ts +173 -0
  713. package/src/domains/session/protected-artifact-journal.ts +241 -0
  714. package/src/domains/session/protected-artifacts.ts +90 -0
  715. package/src/domains/session/retry.ts +238 -0
  716. package/src/domains/session/task-board.ts +375 -0
  717. package/src/domains/session/tree/active-path.ts +98 -0
  718. package/src/domains/session/tree/fork.ts +160 -0
  719. package/src/domains/session/tree/manager.ts +128 -0
  720. package/src/domains/session/tree/navigator.ts +177 -0
  721. package/src/domains/session/tree/preview.ts +259 -0
  722. package/src/domains/session/usage.ts +148 -0
  723. package/src/domains/session/workspace/git-probe.ts +161 -0
  724. package/src/domains/session/workspace/index.ts +4 -0
  725. package/src/domains/session/workspace/project-type.ts +217 -0
  726. package/src/domains/session/workspace/snapshot.ts +74 -0
  727. package/src/domains/share/archive.ts +684 -0
  728. package/src/domains/share/contract.ts +9 -0
  729. package/src/domains/share/extension.ts +26 -0
  730. package/src/domains/share/index.ts +28 -0
  731. package/src/domains/share/manifest.ts +6 -0
  732. package/src/engine/acp/adapter.ts +397 -0
  733. package/src/engine/acp/errors.ts +32 -0
  734. package/src/engine/acp/event-mapper.ts +154 -0
  735. package/src/engine/acp/server.ts +656 -0
  736. package/src/engine/acp/tool-mediator.ts +686 -0
  737. package/src/engine/acp/transport.ts +654 -0
  738. package/src/engine/acp/types.ts +170 -0
  739. package/src/engine/agent.ts +29 -0
  740. package/src/engine/ai.ts +202 -0
  741. package/src/engine/alcf-oauth.ts +198 -0
  742. package/src/engine/antigravity/subprocess-runtime.ts +205 -0
  743. package/src/engine/apis/degraded-inference.ts +95 -0
  744. package/src/engine/apis/index.ts +20 -0
  745. package/src/engine/apis/llamacpp-residency.ts +252 -0
  746. package/src/engine/apis/lmstudio-native.ts +1438 -0
  747. package/src/engine/apis/lmstudio-residency.ts +92 -0
  748. package/src/engine/apis/ollama-native.ts +507 -0
  749. package/src/engine/apis/openai-completions.ts +716 -0
  750. package/src/engine/apis/output-budget.ts +99 -0
  751. package/src/engine/apis/residency-lock.ts +29 -0
  752. package/src/engine/apis/residency.ts +640 -0
  753. package/src/engine/apis/resident-models.ts +42 -0
  754. package/src/engine/apis/sampling-overrides.ts +38 -0
  755. package/src/engine/apis/thinking-replay.ts +11 -0
  756. package/src/engine/claude/sdk-runtime.ts +685 -0
  757. package/src/engine/claude/session-id.ts +5 -0
  758. package/src/engine/claude/subprocess-runtime.ts +316 -0
  759. package/src/engine/claude/tool-safety.ts +400 -0
  760. package/src/engine/external-subprocess.ts +23 -0
  761. package/src/engine/harmony-response.ts +165 -0
  762. package/src/engine/loop-guard.ts +1127 -0
  763. package/src/engine/oauth.ts +192 -0
  764. package/src/engine/pi-mono-names.ts +13 -0
  765. package/src/engine/provider-payload.ts +315 -0
  766. package/src/engine/select-list.ts +53 -0
  767. package/src/engine/session.ts +834 -0
  768. package/src/engine/strip-tokenizer-sentinels.ts +125 -0
  769. package/src/engine/tui.ts +103 -0
  770. package/src/engine/types.ts +66 -0
  771. package/src/engine/worker-events.ts +100 -0
  772. package/src/engine/worker-runtime.ts +1022 -0
  773. package/src/engine/worker-tools.ts +203 -0
  774. package/src/entry/orchestrator.ts +1873 -0
  775. package/src/interactive/application-controller.ts +346 -0
  776. package/src/interactive/bus-notices.ts +265 -0
  777. package/src/interactive/chat-loop-messages.ts +626 -0
  778. package/src/interactive/chat-loop-policy.ts +18 -0
  779. package/src/interactive/chat-loop.ts +865 -0
  780. package/src/interactive/chat-panel.ts +1694 -0
  781. package/src/interactive/chat-renderer.ts +1038 -0
  782. package/src/interactive/clio-editor.ts +166 -0
  783. package/src/interactive/command-fallbacks.ts +23 -0
  784. package/src/interactive/command-output.ts +85 -0
  785. package/src/interactive/context-activity.ts +203 -0
  786. package/src/interactive/context-meter.ts +223 -0
  787. package/src/interactive/context-overlay.ts +220 -0
  788. package/src/interactive/cost-overlay.ts +279 -0
  789. package/src/interactive/dispatch-board.ts +1319 -0
  790. package/src/interactive/dispatch-steering.ts +86 -0
  791. package/src/interactive/editor-bash.ts +46 -0
  792. package/src/interactive/editor-steer.ts +51 -0
  793. package/src/interactive/editor-submit.ts +303 -0
  794. package/src/interactive/external-editor.ts +67 -0
  795. package/src/interactive/follow-up-queue-panel.ts +75 -0
  796. package/src/interactive/footer/dashboard.ts +534 -0
  797. package/src/interactive/footer/notifications.ts +275 -0
  798. package/src/interactive/footer/widgets.ts +1246 -0
  799. package/src/interactive/footer-panel.ts +187 -0
  800. package/src/interactive/format-time.ts +85 -0
  801. package/src/interactive/index.ts +11 -0
  802. package/src/interactive/interactive-application.ts +755 -0
  803. package/src/interactive/interactive-event-projection.ts +380 -0
  804. package/src/interactive/interactive-input-runtime.ts +261 -0
  805. package/src/interactive/interactive-presentation.ts +452 -0
  806. package/src/interactive/interactive-shell.ts +134 -0
  807. package/src/interactive/interactive-slash-runtime.ts +492 -0
  808. package/src/interactive/interactive-subscriptions.ts +111 -0
  809. package/src/interactive/interactive-tickers.ts +152 -0
  810. package/src/interactive/keybinding-manager.ts +496 -0
  811. package/src/interactive/layout.ts +20 -0
  812. package/src/interactive/leader-key.ts +143 -0
  813. package/src/interactive/loop-guard-interrupt.ts +101 -0
  814. package/src/interactive/memory-overlay.ts +280 -0
  815. package/src/interactive/overlay-ask-user-lifecycle.ts +110 -0
  816. package/src/interactive/overlay-auth-lifecycle.ts +308 -0
  817. package/src/interactive/overlay-frame.ts +502 -0
  818. package/src/interactive/overlay-general-openers.ts +217 -0
  819. package/src/interactive/overlay-key-routing.ts +213 -0
  820. package/src/interactive/overlay-lifecycle.ts +413 -0
  821. package/src/interactive/overlay-model-selectors.ts +127 -0
  822. package/src/interactive/overlay-permission-lifecycle.ts +344 -0
  823. package/src/interactive/overlay-resource-openers.ts +112 -0
  824. package/src/interactive/overlay-session-lifecycle.ts +270 -0
  825. package/src/interactive/overlay-transitions.ts +57 -0
  826. package/src/interactive/overlays/agents.ts +69 -0
  827. package/src/interactive/overlays/ask-user.ts +921 -0
  828. package/src/interactive/overlays/auth-dialog.ts +221 -0
  829. package/src/interactive/overlays/context-reset.ts +108 -0
  830. package/src/interactive/overlays/cwd-fallback.ts +141 -0
  831. package/src/interactive/overlays/extensions.ts +54 -0
  832. package/src/interactive/overlays/help-reference.ts +140 -0
  833. package/src/interactive/overlays/interop.ts +139 -0
  834. package/src/interactive/overlays/keybinding-detail.ts +90 -0
  835. package/src/interactive/overlays/list-overlay.ts +606 -0
  836. package/src/interactive/overlays/message-picker.ts +155 -0
  837. package/src/interactive/overlays/model-selector.ts +1091 -0
  838. package/src/interactive/overlays/prompts.ts +72 -0
  839. package/src/interactive/overlays/session-selector-search.ts +31 -0
  840. package/src/interactive/overlays/session-selector.ts +266 -0
  841. package/src/interactive/overlays/settings.ts +3363 -0
  842. package/src/interactive/overlays/skills-hub.ts +237 -0
  843. package/src/interactive/overlays/tree-selector.ts +387 -0
  844. package/src/interactive/permission-overlay.ts +170 -0
  845. package/src/interactive/render-trace.ts +125 -0
  846. package/src/interactive/renderers/branch-summary.ts +86 -0
  847. package/src/interactive/renderers/code-ink.ts +420 -0
  848. package/src/interactive/renderers/compaction-summary.ts +112 -0
  849. package/src/interactive/renderers/diff.ts +126 -0
  850. package/src/interactive/renderers/notice.ts +28 -0
  851. package/src/interactive/renderers/retry-status.ts +31 -0
  852. package/src/interactive/renderers/structured.ts +89 -0
  853. package/src/interactive/renderers/tool-execution.ts +1104 -0
  854. package/src/interactive/renderers/worker-entry.ts +264 -0
  855. package/src/interactive/session-last-turn.ts +186 -0
  856. package/src/interactive/session-transcript.ts +105 -0
  857. package/src/interactive/session-usage-reseed.ts +74 -0
  858. package/src/interactive/slash-autocomplete.ts +364 -0
  859. package/src/interactive/slash-commands.ts +1319 -0
  860. package/src/interactive/slash-spec.ts +453 -0
  861. package/src/interactive/status/controller.ts +256 -0
  862. package/src/interactive/status/index.ts +23 -0
  863. package/src/interactive/status/state-machine.ts +530 -0
  864. package/src/interactive/status/summary.ts +170 -0
  865. package/src/interactive/status/types.ts +121 -0
  866. package/src/interactive/status/verbs.ts +163 -0
  867. package/src/interactive/status/watchdog.ts +24 -0
  868. package/src/interactive/tasks-overlay.ts +186 -0
  869. package/src/interactive/theme/components.ts +55 -0
  870. package/src/interactive/theme/glyphs.ts +70 -0
  871. package/src/interactive/theme/index.ts +15 -0
  872. package/src/interactive/theme/labels.ts +88 -0
  873. package/src/interactive/theme/rules.ts +138 -0
  874. package/src/interactive/theme/segments.ts +88 -0
  875. package/src/interactive/theme/tokens.ts +121 -0
  876. package/src/interactive/thinking-level-policy.ts +6 -0
  877. package/src/interactive/tool-prose-loop.ts +122 -0
  878. package/src/interactive/tool-prose-registration.ts +48 -0
  879. package/src/interactive/turn-context.ts +854 -0
  880. package/src/interactive/turn-middleware.ts +283 -0
  881. package/src/interactive/turn-persistence.ts +441 -0
  882. package/src/interactive/turn-queues.ts +169 -0
  883. package/src/interactive/turn-recovery.ts +306 -0
  884. package/src/interactive/turn-runtime.ts +802 -0
  885. package/src/interactive/turn-state.ts +123 -0
  886. package/src/interactive/view/artifacts.ts +1342 -0
  887. package/src/interactive/view/view-overlay.ts +732 -0
  888. package/src/interactive/welcome-dashboard.ts +536 -0
  889. package/src/interactive/worker-receipts.ts +94 -0
  890. package/src/interactive/worker-replay.ts +111 -0
  891. package/src/interactive/worker-share.ts +100 -0
  892. package/src/interactive/worker-stream.ts +442 -0
  893. package/src/interactive/workspace-facts.ts +141 -0
  894. package/src/tools/agent-tools.ts +382 -0
  895. package/src/tools/artifact.ts +103 -0
  896. package/src/tools/ask-user.ts +656 -0
  897. package/src/tools/bash.ts +176 -0
  898. package/src/tools/bootstrap.ts +474 -0
  899. package/src/tools/codewiki/code-nav.ts +563 -0
  900. package/src/tools/codewiki/shared.ts +115 -0
  901. package/src/tools/compete-worktrees.ts +898 -0
  902. package/src/tools/context/docs-engine.ts +619 -0
  903. package/src/tools/context/index.ts +435 -0
  904. package/src/tools/credential-present.ts +151 -0
  905. package/src/tools/dispatch-arguments.ts +228 -0
  906. package/src/tools/dispatch-plan.ts +741 -0
  907. package/src/tools/dispatch-scout.ts +461 -0
  908. package/src/tools/dispatch.ts +3338 -0
  909. package/src/tools/edit-diff.ts +534 -0
  910. package/src/tools/edit.ts +128 -0
  911. package/src/tools/executables.ts +22 -0
  912. package/src/tools/file-mutation-queue.ts +35 -0
  913. package/src/tools/find.ts +292 -0
  914. package/src/tools/grep.ts +495 -0
  915. package/src/tools/ignore-policy.ts +169 -0
  916. package/src/tools/ledger.ts +206 -0
  917. package/src/tools/ls.ts +110 -0
  918. package/src/tools/monitor.ts +797 -0
  919. package/src/tools/network-policy.ts +29 -0
  920. package/src/tools/observation.ts +421 -0
  921. package/src/tools/observers.ts +99 -0
  922. package/src/tools/path-utils.ts +79 -0
  923. package/src/tools/policy.ts +154 -0
  924. package/src/tools/profiles.ts +108 -0
  925. package/src/tools/read.ts +173 -0
  926. package/src/tools/registry.ts +1157 -0
  927. package/src/tools/result-shaping.ts +204 -0
  928. package/src/tools/safe-exec.ts +128 -0
  929. package/src/tools/spawn-hygiene.ts +182 -0
  930. package/src/tools/steer.ts +88 -0
  931. package/src/tools/string-enum.ts +15 -0
  932. package/src/tools/tasks.ts +168 -0
  933. package/src/tools/truncate-utf8.ts +17 -0
  934. package/src/tools/truncate.ts +202 -0
  935. package/src/tools/verify/frontend.ts +685 -0
  936. package/src/tools/verify/index.ts +66 -0
  937. package/src/tools/verify/scripts.ts +108 -0
  938. package/src/tools/web-fetch.ts +777 -0
  939. package/src/tools/worker-evidence.ts +215 -0
  940. package/src/tools/write.ts +52 -0
  941. package/src/utils/exif-orientation.ts +192 -0
  942. package/src/utils/git.ts +24 -0
  943. package/src/utils/image-resize.ts +148 -0
  944. package/src/utils/photon.ts +103 -0
  945. package/src/worker/control-lane.ts +22 -0
  946. package/src/worker/entry.ts +257 -0
  947. package/src/worker/event-projection.ts +56 -0
  948. package/src/worker/heartbeat.ts +24 -0
  949. package/src/worker/ledger-mirror.ts +95 -0
  950. package/src/worker/ndjson.ts +40 -0
  951. package/src/worker/protocol.ts +529 -0
  952. package/src/worker/resource-facts.ts +79 -0
  953. package/src/worker/runtime-registry.ts +12 -0
  954. package/src/worker/spec-contract.ts +654 -0
  955. package/src/worker/stdin-demux.ts +316 -0
  956. package/dist/acp-UMLFVA3F.js +0 -92
  957. package/dist/chunk-262G75JS.js +0 -35
  958. package/dist/chunk-5LDRNKX2.js +0 -1063
  959. package/dist/chunk-67MTHP2E.js +0 -135
  960. package/dist/chunk-GOTUR54M.js +0 -9
  961. package/dist/chunk-TPOCL34A.js +0 -2876
  962. package/dist/chunk-XV4ZJ6ZM.js +0 -3177
  963. package/dist/clio-KIQ5SNDS.js +0 -53
  964. package/dist/configure-G4E3A2PG.js +0 -27
  965. package/dist/doctor-M5HJJZOL.js +0 -61
  966. package/dist/domains/agents/builtins/architect.md +0 -33
  967. package/dist/domains/agents/builtins/coder.md +0 -31
  968. package/dist/domains/agents/builtins/context-bootstrap.md +0 -38
  969. package/dist/domains/agents/builtins/debugger.md +0 -30
  970. package/dist/domains/agents/builtins/documenter.md +0 -31
  971. package/dist/domains/agents/builtins/git-master.md +0 -30
  972. package/dist/domains/agents/builtins/provenance.md +0 -30
  973. package/dist/domains/agents/builtins/researcher.md +0 -71
  974. package/dist/domains/agents/builtins/scout.md +0 -42
  975. package/dist/domains/agents/builtins/tester.md +0 -31
  976. package/dist/domains/agents/builtins/verifier.md +0 -30
  977. package/dist/domains/agents/builtins/wiki-writer.md +0 -41
  978. package/dist/fleet-preflight-CLIAX7YR.js +0 -21
  979. package/dist/preload-KZVHET2B.js +0 -11
  980. package/dist/version-ROZ6CZKH.js +0 -16
  981. package/skills/git/commit-crafting/SKILL.md +0 -79
  982. package/skills/git/commit-crafting/evals.md +0 -92
  983. package/skills/git/create-pr/SKILL.md +0 -116
  984. package/skills/git/create-pr/evals.md +0 -114
  985. package/skills/git/investigate-issue/SKILL.md +0 -139
  986. package/skills/git/investigate-issue/evals.md +0 -94
  987. package/skills/git/review-changes/SKILL.md +0 -103
  988. package/skills/git/review-changes/evals.md +0 -85
@@ -0,0 +1,1454 @@
1
+ /**
2
+ * Durable, rebuildable SQLite mirror of dispatch activity.
3
+ *
4
+ * Receipts, ledgers, and gate artifacts remain authoritative. This database is
5
+ * deliberately a best-effort operator projection: callers enqueue small
6
+ * writes, failures are reported, and dispatch correctness never depends on it.
7
+ */
8
+
9
+ import { createHash } from "node:crypto";
10
+ import { mkdirSync } from "node:fs";
11
+ import { createRequire } from "node:module";
12
+ import { hostname } from "node:os";
13
+ import { dirname, join } from "node:path";
14
+ import type { DatabaseSync, SQLInputValue } from "node:sqlite";
15
+ import type {
16
+ DispatchCompletedPayload,
17
+ DispatchEnqueuedPayload,
18
+ DispatchFailedPayload,
19
+ DispatchProgressPayload,
20
+ DispatchStartedPayload,
21
+ } from "../../core/bus-events.js";
22
+ import { processAlive, processBirthToken } from "../../core/process-identity.js";
23
+ import { createRedactionTally, redactSecretsText } from "../evidence/redact.js";
24
+
25
+ export const TRACE_SCHEMA_VERSION = 1;
26
+ export const TRACE_DATABASE_FILE = "trace.sqlite";
27
+ export const TRACE_EVENT_POLL_LIMIT = 500;
28
+ export const TRACE_PAYLOAD_LIMIT_BYTES = 16 * 1024;
29
+ export const TRACE_WRITE_QUEUE_LIMIT = 2048;
30
+
31
+ type DatabaseSyncConstructor = typeof import("node:sqlite").DatabaseSync;
32
+ let sqliteConstructor: DatabaseSyncConstructor | null = null;
33
+
34
+ /**
35
+ * Whether the operator asked to see where warnings come from.
36
+ *
37
+ * `--trace-warnings` is a request for more warning detail, not less, so the
38
+ * filter below stands down for it. Dropping a warning the operator explicitly
39
+ * asked to trace would be the one case where the suppression lies.
40
+ */
41
+ function warningTracingRequested(): boolean {
42
+ const flagged = (argument: string): boolean =>
43
+ argument === "--trace-warnings" || argument.startsWith("--trace-warnings=");
44
+ if (process.execArgv.some(flagged)) return true;
45
+ const nodeOptions = process.env.NODE_OPTIONS;
46
+ if (nodeOptions === undefined) return false;
47
+ return nodeOptions.split(/\s+/).some(flagged);
48
+ }
49
+
50
+ /** Exactly the warning Node emits for the sqlite module, and nothing else. */
51
+ function isSqliteExperimentalWarning(args: readonly unknown[]): boolean {
52
+ const [warning, second] = args;
53
+ const type =
54
+ typeof second === "string"
55
+ ? second
56
+ : typeof second === "object" && second !== null && "type" in second
57
+ ? (second as { type?: unknown }).type
58
+ : undefined;
59
+ if (type !== "ExperimentalWarning") return false;
60
+ const text = typeof warning === "string" ? warning : warning instanceof Error ? warning.message : "";
61
+ return text.includes("SQLite is an experimental feature");
62
+ }
63
+
64
+ function requireSqlite(): DatabaseSyncConstructor {
65
+ return (createRequire(import.meta.url)("node:sqlite") as { DatabaseSync: DatabaseSyncConstructor }).DatabaseSync;
66
+ }
67
+
68
+ /**
69
+ * Run one synchronous module load with the SQLite ExperimentalWarning dropped.
70
+ *
71
+ * The warning names a Node internal the operator never chose and it lands on
72
+ * stderr in the middle of `clio-coder trace` output, which is the fresh-install
73
+ * opacity F1 was filed for. Workers are already spawned with
74
+ * `--disable-warning=ExperimentalWarning` (dispatch/worker-spawn.ts), so
75
+ * silencing it here is consistency rather than new policy.
76
+ *
77
+ * The filter is as narrow as the problem: it covers one synchronous call,
78
+ * matches only the ExperimentalWarning naming SQLite, forwards everything else
79
+ * untouched, and restores the original `process.emitWarning` in a `finally` so
80
+ * a load that throws still hands the global back. An operator running with
81
+ * `--trace-warnings` asked for more warning detail, not less, so the filter
82
+ * stands down entirely for them.
83
+ *
84
+ * Exported for the contract test, which drives it with a load that emits both
85
+ * warnings; production has exactly one caller.
86
+ */
87
+ export function loadWithSqliteWarningSuppressed<T>(load: () => T): T {
88
+ if (warningTracingRequested()) return load();
89
+ const emitWarning = process.emitWarning;
90
+ const forward = emitWarning.bind(process) as (...args: unknown[]) => void;
91
+ process.emitWarning = ((...args: unknown[]) => {
92
+ if (isSqliteExperimentalWarning(args)) return;
93
+ forward(...args);
94
+ }) as typeof process.emitWarning;
95
+ try {
96
+ return load();
97
+ } finally {
98
+ process.emitWarning = emitWarning;
99
+ }
100
+ }
101
+
102
+ function databaseSyncConstructor(): DatabaseSyncConstructor {
103
+ // Keep the load lazy so unrelated Clio commands never pay the warning or the
104
+ // module cost; the trace writer/reader is the first real consumer.
105
+ sqliteConstructor ??= loadWithSqliteWarningSuppressed(requireSqlite);
106
+ return sqliteConstructor;
107
+ }
108
+
109
+ export function traceDatabasePath(stateDir: string): string {
110
+ return join(stateDir, TRACE_DATABASE_FILE);
111
+ }
112
+
113
+ export class TraceSchemaVersionError extends Error {
114
+ constructor(readonly found: number | null) {
115
+ super(
116
+ found === null
117
+ ? "trace database has no schema version"
118
+ : `unsupported trace schema version ${found}; this Clio supports ${TRACE_SCHEMA_VERSION}`,
119
+ );
120
+ this.name = "TraceSchemaVersionError";
121
+ }
122
+ }
123
+
124
+ export interface TraceEventInput {
125
+ eventId: string;
126
+ runId: string;
127
+ phaseId: string;
128
+ parentId?: string | null;
129
+ type: string;
130
+ name: string;
131
+ payload?: unknown;
132
+ tokens?: number | null;
133
+ startedAt: string;
134
+ endedAt?: string | null;
135
+ }
136
+
137
+ export interface TraceSpendInput {
138
+ runId: string;
139
+ phaseId: string;
140
+ inputTokens: number;
141
+ outputTokens: number;
142
+ cacheReadTokens: number;
143
+ cacheWriteTokens: number;
144
+ reasoningTokens: number;
145
+ totalTokens: number;
146
+ inputCostUsd?: number | null;
147
+ outputCostUsd?: number | null;
148
+ cacheReadCostUsd?: number | null;
149
+ cacheWriteCostUsd?: number | null;
150
+ totalCostUsd: number;
151
+ contextTokens?: number | null;
152
+ contextWindow?: number | null;
153
+ }
154
+
155
+ /**
156
+ * `runs.assignment_id` for a turn the operator ran themselves.
157
+ *
158
+ * A dispatched run carries its assignment id here; a session turn has no
159
+ * assignment, so the column holds this sentinel instead. That keeps session
160
+ * turns and dispatched runs in one `runs` table, which is what an operator
161
+ * asking "what did this session do" wants, and it avoids a schema bump:
162
+ * TraceSchemaVersionError refuses a version mismatch outright, so every
163
+ * existing trace.sqlite would need migrating for a column the sentinel already
164
+ * expresses.
165
+ *
166
+ * A row bearing it has no receipt and no worker process. Nothing in the trace
167
+ * read paths requires either, but a future reader that does must check this.
168
+ */
169
+ export const SESSION_TRACE_ASSIGNMENT_ID = "session";
170
+
171
+ export interface SessionTurnUsage {
172
+ inputTokens: number;
173
+ outputTokens: number;
174
+ cacheReadTokens: number;
175
+ cacheWriteTokens: number;
176
+ reasoningTokens: number;
177
+ totalTokens: number;
178
+ costUsd?: number | null;
179
+ }
180
+
181
+ /** Opens the runs/phases pair for one operator turn. */
182
+ export interface SessionTurnStart {
183
+ kind: "start";
184
+ runId: string;
185
+ agent: string;
186
+ target: string;
187
+ model: string;
188
+ runtime: string;
189
+ prompt: string | null;
190
+ at: string;
191
+ }
192
+
193
+ /** One row in that turn: the assistant message, a tool call, a tool result. */
194
+ export interface SessionTurnEvent {
195
+ kind: "event";
196
+ runId: string;
197
+ eventId: string;
198
+ type: string;
199
+ name: string;
200
+ payload?: unknown;
201
+ tokens?: number | null;
202
+ startedAt: string;
203
+ endedAt?: string | null;
204
+ }
205
+
206
+ /** Closes the turn. `error` is the terminal failure text, when there was one. */
207
+ export interface SessionTurnFinish {
208
+ kind: "finish";
209
+ runId: string;
210
+ status: "success" | "fail";
211
+ error: string | null;
212
+ usage: SessionTurnUsage | null;
213
+ at: string;
214
+ }
215
+
216
+ export type SessionTurnTrace = SessionTurnStart | SessionTurnEvent | SessionTurnFinish;
217
+
218
+ export interface TraceGateCheck {
219
+ item: string;
220
+ ok: boolean;
221
+ note: string;
222
+ }
223
+
224
+ export interface TraceGateResultInput {
225
+ runId: string;
226
+ phaseId: string;
227
+ attempt: number;
228
+ gate: string;
229
+ passed: boolean;
230
+ checks: ReadonlyArray<TraceGateCheck> | null;
231
+ createdAt: string;
232
+ }
233
+
234
+ export interface TraceEnvelopeInput {
235
+ envelopeId: string;
236
+ runId: string;
237
+ phaseId: string;
238
+ agent: string;
239
+ outputType: string;
240
+ payload: unknown;
241
+ valid: boolean;
242
+ attempt: number;
243
+ createdAt: string;
244
+ }
245
+
246
+ export interface TraceProcessInput {
247
+ runId: string;
248
+ kind: "orchestrator" | "worker";
249
+ name: string;
250
+ pid: number;
251
+ command: string;
252
+ startedAt: string;
253
+ }
254
+
255
+ export interface TraceEventRow {
256
+ rowid: number;
257
+ event_id: string;
258
+ run_id: string;
259
+ phase_id: string;
260
+ parent_id: string | null;
261
+ type: string;
262
+ name: string;
263
+ payload_json: string | null;
264
+ tokens: number | null;
265
+ started_at: string;
266
+ ended_at: string | null;
267
+ }
268
+
269
+ export interface TraceRunRow {
270
+ run_id: string;
271
+ assignment_id: string;
272
+ request: string | null;
273
+ status: string;
274
+ agent: string;
275
+ target: string;
276
+ model: string;
277
+ runtime: string;
278
+ node: string | null;
279
+ started_at: string;
280
+ ended_at: string | null;
281
+ total_tokens: number | null;
282
+ total_cost_usd: number | null;
283
+ }
284
+
285
+ export interface TracePhaseRow {
286
+ phase_id: string;
287
+ run_id: string;
288
+ seq: number;
289
+ name: string;
290
+ kind: string;
291
+ owner: string;
292
+ description: string | null;
293
+ status: string;
294
+ attempt: number;
295
+ retries: number;
296
+ error: string | null;
297
+ started_at: string | null;
298
+ ended_at: string | null;
299
+ input_tokens: number | null;
300
+ output_tokens: number | null;
301
+ cache_read_tokens: number | null;
302
+ cache_write_tokens: number | null;
303
+ reasoning_tokens: number | null;
304
+ total_tokens: number | null;
305
+ input_cost_usd: number | null;
306
+ output_cost_usd: number | null;
307
+ cache_read_cost_usd: number | null;
308
+ cache_write_cost_usd: number | null;
309
+ total_cost_usd: number | null;
310
+ context_tokens: number | null;
311
+ context_window: number | null;
312
+ }
313
+
314
+ export interface TraceProcessRow {
315
+ id: number;
316
+ run_id: string;
317
+ kind: string;
318
+ name: string;
319
+ pid: number;
320
+ command: string;
321
+ command_digest: string;
322
+ started_at: string;
323
+ ended_at: string | null;
324
+ host: string | null;
325
+ birth_token: string | null;
326
+ }
327
+
328
+ function applyConnectionPragmas(db: DatabaseSync): void {
329
+ db.exec("PRAGMA journal_mode=WAL; PRAGMA synchronous=NORMAL; PRAGMA busy_timeout=5000; PRAGMA foreign_keys=ON;");
330
+ }
331
+
332
+ function readVersion(db: DatabaseSync): number | null {
333
+ const hasMeta = db.prepare("SELECT 1 AS found FROM sqlite_master WHERE type='table' AND name='meta'").get() as
334
+ | { found: number }
335
+ | undefined;
336
+ if (!hasMeta) return null;
337
+ const row = db.prepare("SELECT value FROM meta WHERE key='schema_version'").get() as { value: string } | undefined;
338
+ if (!row) return null;
339
+ const parsed = Number.parseInt(row.value, 10);
340
+ return Number.isSafeInteger(parsed) ? parsed : null;
341
+ }
342
+
343
+ function assertSupportedVersion(db: DatabaseSync): void {
344
+ const version = readVersion(db);
345
+ if (version !== TRACE_SCHEMA_VERSION) throw new TraceSchemaVersionError(version);
346
+ }
347
+
348
+ const SCHEMA_SQL = `
349
+ CREATE TABLE meta (key TEXT PRIMARY KEY, value TEXT NOT NULL);
350
+ INSERT INTO meta(key, value) VALUES ('schema_version', '${TRACE_SCHEMA_VERSION}');
351
+
352
+ CREATE TABLE runs (
353
+ run_id TEXT PRIMARY KEY,
354
+ assignment_id TEXT NOT NULL,
355
+ request TEXT,
356
+ status TEXT NOT NULL CHECK(status IN ('queued','running','success','fail')),
357
+ agent TEXT NOT NULL,
358
+ target TEXT NOT NULL,
359
+ model TEXT NOT NULL,
360
+ runtime TEXT NOT NULL,
361
+ node TEXT,
362
+ started_at TEXT NOT NULL,
363
+ ended_at TEXT,
364
+ total_tokens INTEGER,
365
+ total_cost_usd REAL
366
+ );
367
+
368
+ CREATE TABLE phases (
369
+ phase_id TEXT PRIMARY KEY,
370
+ run_id TEXT NOT NULL REFERENCES runs(run_id),
371
+ seq INTEGER NOT NULL,
372
+ name TEXT NOT NULL,
373
+ kind TEXT NOT NULL,
374
+ owner TEXT NOT NULL,
375
+ description TEXT,
376
+ status TEXT NOT NULL DEFAULT 'queued' CHECK(status IN ('queued','running','success','fail')),
377
+ attempt INTEGER NOT NULL DEFAULT 0,
378
+ retries INTEGER NOT NULL DEFAULT 0,
379
+ error TEXT,
380
+ started_at TEXT,
381
+ ended_at TEXT,
382
+ input_tokens INTEGER, output_tokens INTEGER, cache_read_tokens INTEGER, cache_write_tokens INTEGER,
383
+ reasoning_tokens INTEGER, total_tokens INTEGER,
384
+ input_cost_usd REAL, output_cost_usd REAL, cache_read_cost_usd REAL, cache_write_cost_usd REAL,
385
+ total_cost_usd REAL,
386
+ context_tokens INTEGER, context_window INTEGER
387
+ );
388
+ CREATE INDEX phases_run_seq ON phases(run_id, seq);
389
+
390
+ CREATE TABLE events (
391
+ event_id TEXT PRIMARY KEY,
392
+ run_id TEXT NOT NULL REFERENCES runs(run_id),
393
+ phase_id TEXT NOT NULL REFERENCES phases(phase_id),
394
+ parent_id TEXT,
395
+ type TEXT NOT NULL,
396
+ name TEXT NOT NULL,
397
+ payload_json TEXT,
398
+ tokens INTEGER,
399
+ started_at TEXT NOT NULL,
400
+ ended_at TEXT
401
+ );
402
+ CREATE INDEX events_run_rowid ON events(run_id);
403
+ CREATE INDEX events_phase_rowid ON events(phase_id);
404
+
405
+ CREATE TABLE envelopes (
406
+ envelope_id TEXT PRIMARY KEY,
407
+ run_id TEXT NOT NULL REFERENCES runs(run_id),
408
+ phase_id TEXT NOT NULL REFERENCES phases(phase_id),
409
+ agent TEXT NOT NULL,
410
+ output_type TEXT NOT NULL,
411
+ payload_json TEXT NOT NULL,
412
+ valid INTEGER NOT NULL CHECK(valid IN (0,1)),
413
+ attempt INTEGER NOT NULL,
414
+ created_at TEXT NOT NULL
415
+ );
416
+
417
+ CREATE TABLE gate_results (
418
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
419
+ run_id TEXT NOT NULL REFERENCES runs(run_id),
420
+ phase_id TEXT NOT NULL REFERENCES phases(phase_id),
421
+ attempt INTEGER NOT NULL,
422
+ gate TEXT NOT NULL,
423
+ passed INTEGER NOT NULL CHECK(passed IN (0,1)),
424
+ violations_json TEXT NOT NULL,
425
+ checks_json TEXT,
426
+ created_at TEXT NOT NULL
427
+ );
428
+ CREATE INDEX gate_results_phase_attempt ON gate_results(phase_id, attempt);
429
+
430
+ CREATE TABLE agent_sessions (
431
+ run_id TEXT NOT NULL REFERENCES runs(run_id),
432
+ agent TEXT NOT NULL,
433
+ runtime TEXT NOT NULL,
434
+ model TEXT NOT NULL,
435
+ session_id TEXT,
436
+ context_tokens INTEGER,
437
+ context_window INTEGER,
438
+ created_at TEXT NOT NULL,
439
+ last_used_at TEXT NOT NULL,
440
+ PRIMARY KEY (run_id, agent)
441
+ );
442
+
443
+ CREATE TABLE processes (
444
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
445
+ run_id TEXT NOT NULL REFERENCES runs(run_id),
446
+ kind TEXT NOT NULL,
447
+ name TEXT NOT NULL,
448
+ pid INTEGER NOT NULL,
449
+ command TEXT NOT NULL,
450
+ command_digest TEXT NOT NULL,
451
+ started_at TEXT NOT NULL,
452
+ ended_at TEXT,
453
+ host TEXT,
454
+ birth_token TEXT
455
+ );
456
+ CREATE INDEX processes_run_live ON processes(run_id, ended_at);
457
+ `;
458
+
459
+ /** Additive owner-identity columns; older version-1 databases gain them in place. */
460
+ function ensureProcessOwnerColumns(db: DatabaseSync): void {
461
+ const columns = db.prepare("PRAGMA table_info(processes)").all() as { name: string }[];
462
+ if (columns.some((column) => column.name === "host")) return;
463
+ db.exec("ALTER TABLE processes ADD COLUMN host TEXT; ALTER TABLE processes ADD COLUMN birth_token TEXT;");
464
+ }
465
+
466
+ /**
467
+ * Finalize `running` rows whose recorded owner is on this host and provably
468
+ * dead (pid gone, or alive under a different birth token, i.e. reused). Rows
469
+ * with no owner identity, or an owner recorded by another host, are left for
470
+ * that host's own pass. `ended_at` is the last recorded event for the run,
471
+ * never reconciliation time (the honest F18 pattern).
472
+ */
473
+ function reconcileAbandonedRuns(db: DatabaseSync): void {
474
+ const owners = db
475
+ .prepare(`SELECT r.run_id, r.started_at, p.pid, p.host, p.birth_token FROM runs r
476
+ JOIN processes p ON p.id = (SELECT MAX(id) FROM processes WHERE run_id = r.run_id AND host IS NOT NULL)
477
+ WHERE r.status = 'running'`)
478
+ .all() as { run_id: string; started_at: string; pid: number; host: string; birth_token: string | null }[];
479
+ const lastEvent = db.prepare(
480
+ "SELECT COALESCE(ended_at, started_at) AS at FROM events WHERE run_id = ? ORDER BY rowid DESC LIMIT 1",
481
+ );
482
+ for (const owner of owners) {
483
+ if (owner.host !== hostname()) continue;
484
+ if (processAlive(owner.pid) && (owner.birth_token === null || processBirthToken(owner.pid) === owner.birth_token))
485
+ continue;
486
+ const endedAt = (lastEvent.get(owner.run_id) as { at: string } | undefined)?.at ?? owner.started_at;
487
+ db.prepare("UPDATE runs SET status='fail', ended_at=? WHERE run_id=?").run(endedAt, owner.run_id);
488
+ db
489
+ .prepare("UPDATE phases SET status='fail', ended_at=?, error=? WHERE run_id=? AND status='running'")
490
+ .run(endedAt, "abandoned: owner process exited before the run finalized", owner.run_id);
491
+ db.prepare("UPDATE processes SET ended_at=? WHERE run_id=? AND ended_at IS NULL").run(endedAt, owner.run_id);
492
+ }
493
+ }
494
+
495
+ export class TraceStore {
496
+ readonly db: DatabaseSync;
497
+
498
+ constructor(readonly path: string) {
499
+ mkdirSync(dirname(path), { recursive: true });
500
+ this.db = new (databaseSyncConstructor())(path);
501
+ applyConnectionPragmas(this.db);
502
+ const version = readVersion(this.db);
503
+ if (version === null) this.db.exec(`BEGIN IMMEDIATE; ${SCHEMA_SQL} COMMIT;`);
504
+ else if (version !== TRACE_SCHEMA_VERSION) throw new TraceSchemaVersionError(version);
505
+ this.transaction(() => {
506
+ ensureProcessOwnerColumns(this.db);
507
+ reconcileAbandonedRuns(this.db);
508
+ });
509
+ }
510
+
511
+ close(): void {
512
+ this.db.close();
513
+ }
514
+
515
+ transaction(action: () => void): void {
516
+ this.db.exec("BEGIN IMMEDIATE");
517
+ try {
518
+ action();
519
+ this.db.exec("COMMIT");
520
+ } catch (error) {
521
+ this.db.exec("ROLLBACK");
522
+ throw error;
523
+ }
524
+ }
525
+
526
+ upsertRun(input: DispatchEnqueuedPayload, at = new Date().toISOString()): void {
527
+ this.transaction(() => {
528
+ this.db
529
+ .prepare(`INSERT INTO runs
530
+ (run_id, assignment_id, request, status, agent, target, model, runtime, node, started_at)
531
+ VALUES (?, ?, ?, 'queued', ?, ?, ?, ?, ?, ?)
532
+ ON CONFLICT(run_id) DO UPDATE SET request=excluded.request, agent=excluded.agent,
533
+ target=excluded.target, model=excluded.model, runtime=excluded.runtime, node=excluded.node`)
534
+ .run(
535
+ input.runId,
536
+ input.runId,
537
+ input.task === undefined ? null : traceText(input.task, 2000),
538
+ input.agentId,
539
+ input.targetId,
540
+ input.wireModelId,
541
+ input.runtimeId,
542
+ input.node ?? null,
543
+ at,
544
+ );
545
+ this.db
546
+ .prepare(`INSERT INTO phases
547
+ (phase_id, run_id, seq, name, kind, owner, description, status, started_at)
548
+ VALUES (?, ?, 0, ?, 'agent', ?, ?, 'queued', NULL)
549
+ ON CONFLICT(phase_id) DO NOTHING`)
550
+ .run(
551
+ input.runId,
552
+ input.runId,
553
+ traceText(input.agentId, 256),
554
+ traceText(input.agentId, 256),
555
+ input.task === undefined ? null : traceText(input.task, 2000),
556
+ );
557
+ });
558
+ }
559
+
560
+ startRun(input: DispatchStartedPayload, at = new Date().toISOString()): void {
561
+ this.upsertRun(input, at);
562
+ this.transaction(() => {
563
+ this.db.prepare("UPDATE runs SET status='running', started_at=? WHERE run_id=?").run(at, input.runId);
564
+ this.db.prepare("UPDATE phases SET status='running', started_at=? WHERE phase_id=?").run(at, input.runId);
565
+ this.insertEventRaw({
566
+ eventId: `${input.runId}:agent_start`,
567
+ runId: input.runId,
568
+ phaseId: input.runId,
569
+ type: "agent_start",
570
+ name: input.agentId,
571
+ payload: { target: input.targetId, model: input.wireModelId, runtime: input.runtimeId },
572
+ startedAt: at,
573
+ });
574
+ if (input.pid !== null) {
575
+ this.db
576
+ .prepare(`INSERT INTO processes(run_id, kind, name, pid, command, command_digest, started_at, host, birth_token)
577
+ VALUES (?, 'worker', ?, ?, ?, ?, ?, ?, ?)`)
578
+ .run(
579
+ input.runId,
580
+ input.agentId,
581
+ input.pid,
582
+ traceText(input.processCommand ?? "[]", 2000),
583
+ sha256(input.processCommand ?? "[]"),
584
+ at,
585
+ hostname(),
586
+ processBirthToken(input.pid),
587
+ );
588
+ }
589
+ this.db
590
+ .prepare(`INSERT INTO agent_sessions
591
+ (run_id, agent, runtime, model, session_id, context_tokens, context_window, created_at, last_used_at)
592
+ VALUES (?, ?, ?, ?, NULL, NULL, ?, ?, ?)
593
+ ON CONFLICT(run_id, agent) DO UPDATE SET runtime=excluded.runtime, model=excluded.model,
594
+ context_window=excluded.context_window, last_used_at=excluded.last_used_at`)
595
+ .run(
596
+ input.runId,
597
+ traceText(input.agentId, 256),
598
+ traceText(input.runtimeId, 256),
599
+ traceText(input.wireModelId, 256),
600
+ input.contextWindow ?? null,
601
+ at,
602
+ at,
603
+ );
604
+ });
605
+ }
606
+
607
+ insertEvent(input: TraceEventInput): void {
608
+ this.transaction(() => this.insertEventRaw(input));
609
+ }
610
+
611
+ private insertEventRaw(input: TraceEventInput): void {
612
+ this.db
613
+ .prepare(`INSERT INTO events
614
+ (event_id, run_id, phase_id, parent_id, type, name, payload_json, tokens, started_at, ended_at)
615
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
616
+ ON CONFLICT(event_id) DO UPDATE SET name=excluded.name, payload_json=excluded.payload_json,
617
+ tokens=excluded.tokens, started_at=excluded.started_at, ended_at=excluded.ended_at`)
618
+ .run(
619
+ input.eventId,
620
+ input.runId,
621
+ input.phaseId,
622
+ input.parentId ?? null,
623
+ input.type,
624
+ traceText(input.name, 512),
625
+ input.payload === undefined ? null : boundedJson(input.payload),
626
+ input.tokens ?? null,
627
+ input.startedAt,
628
+ input.endedAt ?? null,
629
+ );
630
+ }
631
+
632
+ recordSpend(input: TraceSpendInput): void {
633
+ this.transaction(() => {
634
+ this.db
635
+ .prepare(`UPDATE phases SET input_tokens=?, output_tokens=?, cache_read_tokens=?, cache_write_tokens=?,
636
+ reasoning_tokens=?, total_tokens=?, input_cost_usd=?, output_cost_usd=?, cache_read_cost_usd=?,
637
+ cache_write_cost_usd=?, total_cost_usd=?, context_tokens=?, context_window=? WHERE phase_id=? AND run_id=?`)
638
+ .run(
639
+ input.inputTokens,
640
+ input.outputTokens,
641
+ input.cacheReadTokens,
642
+ input.cacheWriteTokens,
643
+ input.reasoningTokens,
644
+ input.totalTokens,
645
+ input.inputCostUsd ?? null,
646
+ input.outputCostUsd ?? null,
647
+ input.cacheReadCostUsd ?? null,
648
+ input.cacheWriteCostUsd ?? null,
649
+ input.totalCostUsd,
650
+ input.contextTokens ?? null,
651
+ input.contextWindow ?? null,
652
+ input.phaseId,
653
+ input.runId,
654
+ );
655
+ this.db
656
+ .prepare("UPDATE runs SET total_tokens=?, total_cost_usd=? WHERE run_id=?")
657
+ .run(input.totalTokens, input.totalCostUsd, input.runId);
658
+ });
659
+ }
660
+
661
+ recordContext(runId: string, contextTokens: number, contextWindow: number | null, at: string): void {
662
+ this.transaction(() => {
663
+ this.db
664
+ .prepare("UPDATE phases SET context_tokens=?, context_window=COALESCE(?, context_window) WHERE run_id=?")
665
+ .run(contextTokens, contextWindow, runId);
666
+ this.db
667
+ .prepare(`UPDATE agent_sessions SET context_tokens=?, context_window=COALESCE(?, context_window),
668
+ last_used_at=? WHERE run_id=?`)
669
+ .run(contextTokens, contextWindow, at, runId);
670
+ });
671
+ }
672
+
673
+ recordGate(input: TraceGateResultInput): void {
674
+ const violations = input.checks?.filter((check) => !check.ok).map((check) => `${check.item}: ${check.note}`) ?? [];
675
+ this.transaction(() => {
676
+ this.db
677
+ .prepare("DELETE FROM gate_results WHERE run_id=? AND phase_id=? AND attempt=? AND gate=?")
678
+ .run(input.runId, input.phaseId, input.attempt, input.gate);
679
+ this.db
680
+ .prepare(`INSERT INTO gate_results
681
+ (run_id, phase_id, attempt, gate, passed, violations_json, checks_json, created_at)
682
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`)
683
+ .run(
684
+ input.runId,
685
+ input.phaseId,
686
+ input.attempt,
687
+ input.gate,
688
+ input.passed ? 1 : 0,
689
+ JSON.stringify(violations),
690
+ input.checks === null ? null : JSON.stringify(input.checks),
691
+ input.createdAt,
692
+ );
693
+ this.insertEventRaw({
694
+ eventId: `${input.runId}:gate:${input.gate}:${input.attempt}`,
695
+ runId: input.runId,
696
+ phaseId: input.phaseId,
697
+ type: input.passed ? "gate_pass" : "gate_fail",
698
+ name: input.gate,
699
+ payload: { attempt: input.attempt, checks: input.checks, violations },
700
+ startedAt: input.createdAt,
701
+ });
702
+ });
703
+ }
704
+
705
+ recordEnvelope(input: TraceEnvelopeInput): void {
706
+ this.transaction(() => {
707
+ this.db
708
+ .prepare(`INSERT OR REPLACE INTO envelopes
709
+ (envelope_id, run_id, phase_id, agent, output_type, payload_json, valid, attempt, created_at)
710
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
711
+ .run(
712
+ input.envelopeId,
713
+ input.runId,
714
+ input.phaseId,
715
+ input.agent,
716
+ input.outputType,
717
+ boundedJson(input.payload),
718
+ input.valid ? 1 : 0,
719
+ input.attempt,
720
+ input.createdAt,
721
+ );
722
+ });
723
+ }
724
+
725
+ startProcess(input: TraceProcessInput): number {
726
+ let id = 0;
727
+ this.transaction(() => {
728
+ const result = this.db
729
+ .prepare(`INSERT INTO processes(run_id, kind, name, pid, command, command_digest, started_at)
730
+ VALUES (?, ?, ?, ?, ?, ?, ?)`)
731
+ .run(
732
+ input.runId,
733
+ input.kind,
734
+ traceText(input.name, 256),
735
+ input.pid,
736
+ traceText(input.command, 2000),
737
+ sha256(input.command),
738
+ input.startedAt,
739
+ );
740
+ id = Number(result.lastInsertRowid);
741
+ });
742
+ return id;
743
+ }
744
+
745
+ endProcesses(runId: string, endedAt: string): void {
746
+ this.transaction(() => {
747
+ this.db.prepare("UPDATE processes SET ended_at=? WHERE run_id=? AND ended_at IS NULL").run(endedAt, runId);
748
+ });
749
+ }
750
+
751
+ recordRetryDenied(runId: string, agentId: string, detail: string | null, at: string): void {
752
+ this.transaction(() => {
753
+ const phase = this.db.prepare("SELECT phase_id FROM phases WHERE run_id=? ORDER BY seq LIMIT 1").get(runId) as
754
+ | { phase_id: string }
755
+ | undefined;
756
+ if (!phase) return;
757
+ this.insertEventRaw({
758
+ eventId: `${runId}:retry_denied:${at}`,
759
+ runId,
760
+ phaseId: phase.phase_id,
761
+ type: "error",
762
+ name: "retry denied",
763
+ payload: { agent: agentId, detail, reason: "retry_denied" },
764
+ startedAt: at,
765
+ });
766
+ });
767
+ }
768
+
769
+ finishRun(
770
+ input: DispatchCompletedPayload | DispatchFailedPayload,
771
+ success: boolean,
772
+ at = new Date().toISOString(),
773
+ ): void {
774
+ this.transaction(() => {
775
+ const fallbackStartedAt =
776
+ typeof input.durationMs === "number" ? new Date(Math.max(0, Date.parse(at) - input.durationMs)).toISOString() : at;
777
+ this.db
778
+ .prepare(`INSERT INTO runs
779
+ (run_id, assignment_id, request, status, agent, target, model, runtime, node, started_at)
780
+ VALUES (?, ?, ?, 'running', ?, ?, ?, ?, ?, ?)
781
+ ON CONFLICT(run_id) DO NOTHING`)
782
+ .run(
783
+ input.runId,
784
+ input.lineage?.rootRunId ?? input.runId,
785
+ input.task === undefined ? null : traceText(input.task, 2000),
786
+ input.agentId,
787
+ input.targetId,
788
+ input.wireModelId,
789
+ input.runtimeId,
790
+ input.node ?? null,
791
+ fallbackStartedAt,
792
+ );
793
+ this.db
794
+ .prepare(`INSERT INTO phases
795
+ (phase_id, run_id, seq, name, kind, owner, description, status, started_at)
796
+ VALUES (?, ?, 0, ?, 'agent', ?, ?, 'running', ?)
797
+ ON CONFLICT(phase_id) DO NOTHING`)
798
+ .run(
799
+ input.runId,
800
+ input.runId,
801
+ traceText(input.agentId, 256),
802
+ traceText(input.agentId, 256),
803
+ input.task === undefined ? null : traceText(input.task, 2000),
804
+ fallbackStartedAt,
805
+ );
806
+ this.db
807
+ .prepare("UPDATE runs SET assignment_id=?, status=?, ended_at=?, total_tokens=?, total_cost_usd=? WHERE run_id=?")
808
+ .run(
809
+ input.lineage?.rootRunId ?? input.runId,
810
+ success ? "success" : "fail",
811
+ at,
812
+ input.tokenCount ?? null,
813
+ input.costUsd ?? null,
814
+ input.runId,
815
+ );
816
+ this.db
817
+ .prepare(`UPDATE phases SET status=?, attempt=?, retries=?, ended_at=?, error=?, input_tokens=?, output_tokens=?,
818
+ cache_read_tokens=?, cache_write_tokens=?, reasoning_tokens=?, total_tokens=?, total_cost_usd=?
819
+ WHERE phase_id=?`)
820
+ .run(
821
+ success ? "success" : "fail",
822
+ input.lineage?.attempt ?? 0,
823
+ input.lineage?.attempt ?? 0,
824
+ at,
825
+ success ? null : input.outcomeDetail,
826
+ input.inputTokenCount ?? null,
827
+ input.outputTokenCount ?? null,
828
+ input.cacheReadTokenCount ?? null,
829
+ input.cacheWriteTokenCount ?? null,
830
+ input.reasoningTokenCount ?? null,
831
+ input.tokenCount ?? null,
832
+ input.costUsd ?? null,
833
+ input.runId,
834
+ );
835
+ this.db.prepare("UPDATE processes SET ended_at=? WHERE run_id=? AND ended_at IS NULL").run(at, input.runId);
836
+ this.insertEventRaw({
837
+ eventId: `${input.runId}:agent_end`,
838
+ runId: input.runId,
839
+ phaseId: input.runId,
840
+ type: "agent_end",
841
+ name: input.agentId,
842
+ payload: {
843
+ outcome: input.outcome,
844
+ outcomeDetail: input.outcomeDetail,
845
+ usage: terminalUsage(input),
846
+ cost: input.costUsd ?? null,
847
+ contextWindow: input.contextWindow ?? null,
848
+ },
849
+ tokens: input.tokenCount ?? null,
850
+ startedAt: at,
851
+ });
852
+ this.insertEventRaw({
853
+ eventId: `${input.runId}:phase_end`,
854
+ runId: input.runId,
855
+ phaseId: input.runId,
856
+ type: "phase_end",
857
+ name: input.agentId,
858
+ payload: { status: success ? "success" : "fail" },
859
+ startedAt: at,
860
+ });
861
+ });
862
+ }
863
+
864
+ /**
865
+ * Record one fact about a turn the operator ran in the chat loop.
866
+ *
867
+ * The three shapes reuse the dispatch tables exactly: `start` opens the
868
+ * runs/phases pair, `event` appends to the same `events` table a worker's
869
+ * tool calls land in, and `finish` closes both with the turn's usage. The
870
+ * phase id is the run id, as it is for a dispatched run's single phase, so
871
+ * `clio-coder trace phases` and `clio-coder trace tail` need no session-specific path.
872
+ */
873
+ recordSessionTurn(input: SessionTurnTrace): void {
874
+ if (input.kind === "start") {
875
+ this.startSessionTurn(input);
876
+ return;
877
+ }
878
+ if (input.kind === "event") {
879
+ this.transaction(() => {
880
+ this.insertEventRaw({
881
+ eventId: `${input.runId}:${input.eventId}`,
882
+ runId: input.runId,
883
+ phaseId: input.runId,
884
+ parentId: `${input.runId}:turn_start`,
885
+ type: input.type,
886
+ name: input.name,
887
+ ...(input.payload === undefined ? {} : { payload: input.payload }),
888
+ tokens: input.tokens ?? null,
889
+ startedAt: input.startedAt,
890
+ endedAt: input.endedAt ?? null,
891
+ });
892
+ });
893
+ return;
894
+ }
895
+ this.finishSessionTurn(input);
896
+ }
897
+
898
+ private startSessionTurn(input: SessionTurnStart): void {
899
+ this.transaction(() => {
900
+ this.db
901
+ .prepare(`INSERT INTO runs
902
+ (run_id, assignment_id, request, status, agent, target, model, runtime, node, started_at)
903
+ VALUES (?, ?, ?, 'running', ?, ?, ?, ?, NULL, ?)
904
+ ON CONFLICT(run_id) DO NOTHING`)
905
+ .run(
906
+ input.runId,
907
+ SESSION_TRACE_ASSIGNMENT_ID,
908
+ input.prompt === null ? null : traceText(input.prompt, 2000),
909
+ traceText(input.agent, 256),
910
+ traceText(input.target, 256),
911
+ traceText(input.model, 256),
912
+ traceText(input.runtime, 256),
913
+ input.at,
914
+ );
915
+ this.db
916
+ .prepare(`INSERT INTO phases
917
+ (phase_id, run_id, seq, name, kind, owner, description, status, started_at)
918
+ VALUES (?, ?, 0, ?, 'session', ?, ?, 'running', ?)
919
+ ON CONFLICT(phase_id) DO NOTHING`)
920
+ .run(
921
+ input.runId,
922
+ input.runId,
923
+ traceText(input.agent, 256),
924
+ traceText(input.agent, 256),
925
+ input.prompt === null ? null : traceText(input.prompt, 2000),
926
+ input.at,
927
+ );
928
+ this.insertEventRaw({
929
+ eventId: `${input.runId}:turn_start`,
930
+ runId: input.runId,
931
+ phaseId: input.runId,
932
+ type: "agent_start",
933
+ name: input.agent,
934
+ payload: { target: input.target, model: input.model, runtime: input.runtime, session: true },
935
+ startedAt: input.at,
936
+ });
937
+ });
938
+ }
939
+
940
+ private finishSessionTurn(input: SessionTurnFinish): void {
941
+ const usage = input.usage;
942
+ this.transaction(() => {
943
+ this.db
944
+ .prepare("UPDATE runs SET status=?, ended_at=?, total_tokens=?, total_cost_usd=? WHERE run_id=?")
945
+ .run(input.status, input.at, usage?.totalTokens ?? null, usage?.costUsd ?? null, input.runId);
946
+ this.db
947
+ .prepare(`UPDATE phases SET status=?, ended_at=?, error=?, input_tokens=?, output_tokens=?,
948
+ cache_read_tokens=?, cache_write_tokens=?, reasoning_tokens=?, total_tokens=?, total_cost_usd=?
949
+ WHERE phase_id=?`)
950
+ .run(
951
+ input.status,
952
+ input.at,
953
+ input.error,
954
+ usage?.inputTokens ?? null,
955
+ usage?.outputTokens ?? null,
956
+ usage?.cacheReadTokens ?? null,
957
+ usage?.cacheWriteTokens ?? null,
958
+ usage?.reasoningTokens ?? null,
959
+ usage?.totalTokens ?? null,
960
+ usage?.costUsd ?? null,
961
+ input.runId,
962
+ );
963
+ this.insertEventRaw({
964
+ eventId: `${input.runId}:turn_end`,
965
+ runId: input.runId,
966
+ phaseId: input.runId,
967
+ type: "agent_end",
968
+ name: input.status,
969
+ payload: { status: input.status, error: input.error, usage },
970
+ tokens: usage?.totalTokens ?? null,
971
+ startedAt: input.at,
972
+ });
973
+ });
974
+ }
975
+ }
976
+
977
+ export class TraceReader {
978
+ readonly db: DatabaseSync;
979
+
980
+ constructor(readonly path: string) {
981
+ this.db = new (databaseSyncConstructor())(path, { readOnly: true });
982
+ // journal_mode is queried rather than changed: changing it is a write and
983
+ // readonly consumers must remain readonly. The writer creates WAL first.
984
+ this.db.exec("PRAGMA busy_timeout=5000;");
985
+ assertSupportedVersion(this.db);
986
+ const mode = this.db.prepare("PRAGMA journal_mode").get() as { journal_mode: string };
987
+ if (mode.journal_mode.toLowerCase() !== "wal")
988
+ throw new Error(`trace database journal mode is ${mode.journal_mode}, expected WAL`);
989
+ }
990
+
991
+ close(): void {
992
+ this.db.close();
993
+ }
994
+
995
+ runs(limit = 50): TraceRunRow[] {
996
+ return this.db
997
+ .prepare("SELECT * FROM runs ORDER BY started_at DESC LIMIT ?")
998
+ .all(clampInt(limit, 1, 500)) as unknown as TraceRunRow[];
999
+ }
1000
+
1001
+ run(runId: string): TraceRunRow | null {
1002
+ return (
1003
+ (this.db.prepare("SELECT * FROM runs WHERE run_id=?").get(runId) as unknown as TraceRunRow | undefined) ?? null
1004
+ );
1005
+ }
1006
+
1007
+ phases(runId: string): TracePhaseRow[] {
1008
+ return this.db
1009
+ .prepare("SELECT * FROM phases WHERE run_id=? ORDER BY seq, phase_id")
1010
+ .all(runId) as unknown as TracePhaseRow[];
1011
+ }
1012
+
1013
+ events(runId: string, afterRowid = 0, limit = TRACE_EVENT_POLL_LIMIT): TraceEventRow[] {
1014
+ return this.db
1015
+ .prepare(`SELECT rowid, event_id, run_id, phase_id, parent_id, type, name, payload_json,
1016
+ tokens, started_at, ended_at FROM events
1017
+ WHERE run_id = ? AND rowid > ? ORDER BY rowid LIMIT ?`)
1018
+ .all(
1019
+ runId,
1020
+ Math.max(0, Math.trunc(afterRowid)),
1021
+ clampInt(limit, 1, TRACE_EVENT_POLL_LIMIT),
1022
+ ) as unknown as TraceEventRow[];
1023
+ }
1024
+
1025
+ processes(runId: string): TraceProcessRow[] {
1026
+ return this.db
1027
+ .prepare("SELECT * FROM processes WHERE run_id=? ORDER BY ended_at IS NOT NULL, id")
1028
+ .all(runId) as unknown as TraceProcessRow[];
1029
+ }
1030
+
1031
+ gateResults(runId: string): Record<string, SQLInputValue>[] {
1032
+ return this.db
1033
+ .prepare("SELECT * FROM gate_results WHERE run_id=? ORDER BY phase_id, attempt, id")
1034
+ .all(runId) as Record<string, SQLInputValue>[];
1035
+ }
1036
+
1037
+ envelopes(runId: string): Record<string, SQLInputValue>[] {
1038
+ return this.db
1039
+ .prepare("SELECT * FROM envelopes WHERE run_id=? ORDER BY created_at, envelope_id")
1040
+ .all(runId) as Record<string, SQLInputValue>[];
1041
+ }
1042
+
1043
+ select(sql: string): Record<string, SQLInputValue>[] {
1044
+ assertSelectOnly(sql);
1045
+ return this.db.prepare(sql).all() as Record<string, SQLInputValue>[];
1046
+ }
1047
+ }
1048
+
1049
+ export interface DispatchTraceMirror {
1050
+ enqueue(channel: string, payload: unknown): void;
1051
+ /**
1052
+ * Mirror one fact about the operator's own turn. Queued on the same chain as
1053
+ * dispatch events, so a turn's start, events and finish keep their order and
1054
+ * a session row never precedes the run row its events reference.
1055
+ */
1056
+ enqueueSessionTurn(trace: SessionTurnTrace): void;
1057
+ flush(): Promise<void>;
1058
+ close(): Promise<void>;
1059
+ }
1060
+
1061
+ interface ToolStart {
1062
+ toolCallId: string;
1063
+ tool: string;
1064
+ args: unknown;
1065
+ startedAt: string;
1066
+ }
1067
+
1068
+ export function createDispatchTraceMirror(
1069
+ path: string,
1070
+ options: { warn?: (message: string) => void; now?: () => string } = {},
1071
+ ): DispatchTraceMirror {
1072
+ const warn = options.warn ?? ((message: string) => process.stderr.write(`[clio:trace] ${message}\n`));
1073
+ const now = options.now ?? (() => new Date().toISOString());
1074
+ let store: TraceStore | null = null;
1075
+ let chain: Promise<void> = Promise.resolve();
1076
+ let closed = false;
1077
+ let degraded = false;
1078
+ let pendingWrites = 0;
1079
+ let droppedProgress = 0;
1080
+ const starts = new Map<string, ToolStart>();
1081
+ const seen = new Map<string, number>();
1082
+ const contextWindows = new Map<string, number>();
1083
+ const gateRuns = new Map<string, { role: string; cycle: number }>();
1084
+
1085
+ const getStore = (): TraceStore => {
1086
+ store ??= new TraceStore(path);
1087
+ return store;
1088
+ };
1089
+ const schedule = (work: () => void): void => {
1090
+ if (closed || degraded) return;
1091
+ pendingWrites += 1;
1092
+ chain = chain.then(
1093
+ () =>
1094
+ new Promise<void>((resolve) => {
1095
+ setImmediate(() => {
1096
+ try {
1097
+ if (degraded) {
1098
+ pendingWrites -= 1;
1099
+ return resolve();
1100
+ }
1101
+ work();
1102
+ } catch (error) {
1103
+ if (!degraded) warn(error instanceof Error ? error.message : String(error));
1104
+ degraded = true;
1105
+ }
1106
+ pendingWrites -= 1;
1107
+ resolve();
1108
+ });
1109
+ }),
1110
+ );
1111
+ };
1112
+
1113
+ return {
1114
+ enqueue(channel, raw): void {
1115
+ const observedAt = now();
1116
+ if (pendingWrites >= TRACE_WRITE_QUEUE_LIMIT && !isCriticalTraceEvent(channel, raw)) {
1117
+ droppedProgress += 1;
1118
+ return;
1119
+ }
1120
+ schedule(() => {
1121
+ if (!isRecord(raw)) return;
1122
+ if (channel === "dispatch.enqueued") {
1123
+ const payload = raw as unknown as DispatchEnqueuedPayload;
1124
+ getStore().upsertRun(payload, observedAt);
1125
+ if (payload.contextWindow !== undefined) contextWindows.set(payload.runId, payload.contextWindow);
1126
+ if (payload.gate !== undefined) gateRuns.set(payload.runId, payload.gate);
1127
+ } else if (channel === "dispatch.started")
1128
+ getStore().startRun(raw as unknown as DispatchStartedPayload, observedAt);
1129
+ else if (channel === "dispatch.progress")
1130
+ recordProgress(
1131
+ getStore(),
1132
+ raw as unknown as DispatchProgressPayload,
1133
+ starts,
1134
+ seen,
1135
+ contextWindows,
1136
+ gateRuns,
1137
+ observedAt,
1138
+ );
1139
+ else if (channel === "dispatch.completed")
1140
+ getStore().finishRun(raw as unknown as DispatchCompletedPayload, true, observedAt);
1141
+ else if (channel === "dispatch.failed")
1142
+ recordFailure(getStore(), raw as unknown as DispatchFailedPayload, observedAt);
1143
+ });
1144
+ },
1145
+ enqueueSessionTurn(trace): void {
1146
+ // A session turn is low-frequency and every one of its rows is the
1147
+ // record itself rather than display detail, so none of it is eligible
1148
+ // for the progress drop the queue limit applies to dispatch chatter.
1149
+ schedule(() => getStore().recordSessionTurn(trace));
1150
+ },
1151
+ async flush(): Promise<void> {
1152
+ await chain;
1153
+ if (droppedProgress > 0) {
1154
+ warn(`dropped ${droppedProgress} display-only progress events because the trace queue was full`);
1155
+ droppedProgress = 0;
1156
+ }
1157
+ },
1158
+ async close(): Promise<void> {
1159
+ closed = true;
1160
+ await chain;
1161
+ if (droppedProgress > 0)
1162
+ warn(`dropped ${droppedProgress} display-only progress events because the trace queue was full`);
1163
+ store?.close();
1164
+ },
1165
+ };
1166
+ }
1167
+
1168
+ function recordProgress(
1169
+ store: TraceStore,
1170
+ payload: DispatchProgressPayload,
1171
+ starts: Map<string, ToolStart>,
1172
+ seen: Map<string, number>,
1173
+ contextWindows: Map<string, number>,
1174
+ gateRuns: Map<string, { role: string; cycle: number }>,
1175
+ at: string,
1176
+ ): void {
1177
+ if (!isRecord(payload.event)) return;
1178
+ const event = payload.event;
1179
+ const type = typeof event.type === "string" ? event.type : "progress";
1180
+ const toolCallId = stringValue(event.toolCallId) ?? stringValue(event.tool_call_id);
1181
+ if (
1182
+ type === "message_end" &&
1183
+ isRecord(event.message) &&
1184
+ event.message.role === "assistant" &&
1185
+ event.message.stopReason !== "error" &&
1186
+ event.message.stopReason !== "aborted" &&
1187
+ isRecord(event.message.usage)
1188
+ ) {
1189
+ const usage = event.message.usage;
1190
+ const contextTokens =
1191
+ finiteNonNegative(usage.totalTokens) ??
1192
+ finiteNonNegative(usage.total_tokens) ??
1193
+ [usage.input, usage.output, usage.cacheRead, usage.cacheWrite]
1194
+ .map((value) => finiteNonNegative(value) ?? 0)
1195
+ .reduce((sum, value) => sum + value, 0);
1196
+ store.recordContext(payload.runId, contextTokens, contextWindows.get(payload.runId) ?? null, at);
1197
+ }
1198
+ const gate = gateRuns.get(payload.runId);
1199
+ if (type === "message_end" && gate !== undefined && isRecord(event.message) && event.message.role === "assistant") {
1200
+ const result = structuredGateResult(messageText(event.message));
1201
+ if (result !== null) {
1202
+ store.recordGate({
1203
+ runId: payload.runId,
1204
+ phaseId: payload.runId,
1205
+ attempt: gate.cycle,
1206
+ gate: gate.role,
1207
+ passed: result.passed,
1208
+ checks: result.checks,
1209
+ createdAt: at,
1210
+ });
1211
+ }
1212
+ }
1213
+ if ((type === "tool_execution_start" || type === "clio_tool_start") && toolCallId !== null) {
1214
+ starts.set(`${payload.runId}:${toolCallId}`, {
1215
+ toolCallId,
1216
+ tool: stringValue(event.toolName) ?? stringValue(event.tool) ?? "tool",
1217
+ args: event.args ?? null,
1218
+ startedAt: at,
1219
+ });
1220
+ return;
1221
+ }
1222
+ if ((type === "tool_execution_end" || type === "clio_tool_finish") && toolCallId !== null) {
1223
+ const key = `${payload.runId}:${toolCallId}`;
1224
+ const start = starts.get(key);
1225
+ // One clock frame per row. The worker measures `durationMs` on its own
1226
+ // clock while the mirror stamps `at` on the orchestrator's, so storing
1227
+ // both as independent endpoints made `endedAt - startedAt` and
1228
+ // `duration_ms` disagree by transport and queue latency: the viewer read
1229
+ // the first for tick geometry and the second for the duration label.
1230
+ // When the worker reports a span, the mirror's observed start anchors it
1231
+ // and the far endpoint is derived, so the two agree by construction; the
1232
+ // mirror's own read of the end is dropped rather than co-stored. With no
1233
+ // observed start, `at` anchors the end and the start is derived backwards
1234
+ // instead. With no reported span there is only one measurement to begin
1235
+ // with, and both stamps stay as the mirror read them.
1236
+ const duration = finiteNonNegative(event.durationMs);
1237
+ const observedStart = start?.startedAt;
1238
+ const startedAt = observedStart ?? (duration === null ? at : new Date(Date.parse(at) - duration).toISOString());
1239
+ const startedAtMs = Date.parse(startedAt);
1240
+ const endedAt =
1241
+ duration !== null && observedStart !== undefined && Number.isFinite(startedAtMs)
1242
+ ? new Date(startedAtMs + duration).toISOString()
1243
+ : at;
1244
+ const tool = start?.tool ?? stringValue(event.toolName) ?? stringValue(event.tool) ?? "tool";
1245
+ const args = start?.args ?? event.args ?? null;
1246
+ const result = event.result ?? event.resultSnippet ?? null;
1247
+ const ok = event.isError !== true && event.outcome !== "error" && event.outcome !== "blocked";
1248
+ store.insertEvent({
1249
+ eventId: `${payload.runId}:tool:${toolCallId}`,
1250
+ runId: payload.runId,
1251
+ phaseId: payload.runId,
1252
+ parentId: `${payload.runId}:agent_start`,
1253
+ type: "tool_call",
1254
+ name: readableToolName(tool, args),
1255
+ payload: {
1256
+ tool,
1257
+ tool_call_id: toolCallId,
1258
+ args,
1259
+ result_snippet: boundedSnippet(result),
1260
+ ok,
1261
+ duration_ms: duration,
1262
+ agent: payload.agentId,
1263
+ },
1264
+ startedAt,
1265
+ endedAt,
1266
+ });
1267
+ starts.delete(key);
1268
+ return;
1269
+ }
1270
+ const sequence = (seen.get(payload.runId) ?? 0) + 1;
1271
+ seen.set(payload.runId, sequence);
1272
+ store.insertEvent({
1273
+ eventId: `${payload.runId}:event:${sequence}`,
1274
+ runId: payload.runId,
1275
+ phaseId: payload.runId,
1276
+ parentId: `${payload.runId}:agent_start`,
1277
+ type: normalizeEventType(type),
1278
+ name: eventName(event, type),
1279
+ payload: projectProgressPayload(type, event),
1280
+ tokens: eventTokens(event),
1281
+ startedAt: at,
1282
+ });
1283
+ }
1284
+
1285
+ function terminalUsage(input: DispatchCompletedPayload | DispatchFailedPayload): Record<string, number | null> | null {
1286
+ if (input.tokenCount === undefined) return null;
1287
+ return {
1288
+ input: input.inputTokenCount ?? 0,
1289
+ output: input.outputTokenCount ?? 0,
1290
+ cache_read: input.cacheReadTokenCount ?? 0,
1291
+ cache_write: input.cacheWriteTokenCount ?? 0,
1292
+ reasoning_tokens: input.reasoningTokenCount ?? 0,
1293
+ total_tokens: input.tokenCount,
1294
+ };
1295
+ }
1296
+
1297
+ function recordFailure(store: TraceStore, input: DispatchFailedPayload, at: string): void {
1298
+ if (input.reason === "retry_denied") {
1299
+ store.recordRetryDenied(input.runId, input.agentId, input.outcomeDetail, at);
1300
+ return;
1301
+ }
1302
+ store.finishRun(input, false, at);
1303
+ }
1304
+
1305
+ function isCriticalTraceEvent(channel: string, raw: unknown): boolean {
1306
+ if (channel !== "dispatch.progress") return true;
1307
+ if (!isRecord(raw) || !isRecord(raw.event)) return false;
1308
+ const type = raw.event.type;
1309
+ return (
1310
+ type === "tool_execution_start" ||
1311
+ type === "tool_execution_end" ||
1312
+ type === "clio_tool_start" ||
1313
+ type === "clio_tool_finish" ||
1314
+ type === "message_end" ||
1315
+ type === "attempt_start"
1316
+ );
1317
+ }
1318
+
1319
+ function projectProgressPayload(type: string, event: Record<string, unknown>): Record<string, unknown> {
1320
+ if (type === "message_end") {
1321
+ const message = isRecord(event.message) ? event.message : {};
1322
+ return {
1323
+ role: message.role ?? null,
1324
+ stopReason: message.stopReason ?? null,
1325
+ usage: isRecord(message.usage) ? message.usage : null,
1326
+ model: message.model ?? null,
1327
+ };
1328
+ }
1329
+ const projected: Record<string, unknown> = { sourceType: type };
1330
+ for (const key of ["level", "status", "attempt", "reason", "dueAt", "previousRunId", "runId"] as const) {
1331
+ const value = event[key];
1332
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") projected[key] = value;
1333
+ }
1334
+ return projected;
1335
+ }
1336
+
1337
+ function messageText(message: Record<string, unknown>): string {
1338
+ if (typeof message.content === "string") return message.content;
1339
+ if (!Array.isArray(message.content)) return "";
1340
+ return message.content
1341
+ .map((part) => (isRecord(part) && part.type === "text" && typeof part.text === "string" ? part.text : ""))
1342
+ .join("");
1343
+ }
1344
+
1345
+ function structuredGateResult(text: string): { passed: boolean; checks: TraceGateCheck[] } | null {
1346
+ let parsed: unknown;
1347
+ try {
1348
+ parsed = JSON.parse(text) as unknown;
1349
+ } catch {
1350
+ return null;
1351
+ }
1352
+ if (!isRecord(parsed) || !Array.isArray(parsed.checks) || parsed.checks.length === 0) return null;
1353
+ const checks: TraceGateCheck[] = [];
1354
+ for (const raw of parsed.checks) {
1355
+ if (
1356
+ !isRecord(raw) ||
1357
+ typeof raw.name !== "string" ||
1358
+ typeof raw.passed !== "boolean" ||
1359
+ typeof raw.evidence !== "string"
1360
+ ) {
1361
+ return null;
1362
+ }
1363
+ checks.push({ item: raw.name, ok: raw.passed, note: raw.evidence });
1364
+ }
1365
+ if (parsed.verdict !== undefined && parsed.verdict !== "pass" && parsed.verdict !== "fail") return null;
1366
+ if (parsed.winner !== undefined && (!Number.isSafeInteger(parsed.winner) || (parsed.winner as number) < 1))
1367
+ return null;
1368
+ if (parsed.verdict === undefined && parsed.winner === undefined) return null;
1369
+ return { passed: parsed.verdict === "pass" || parsed.winner !== undefined, checks };
1370
+ }
1371
+
1372
+ function normalizeEventType(type: string): string {
1373
+ if (type === "message_end") return "log";
1374
+ if (type === "attempt_start") return "handoff";
1375
+ return type.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64) || "progress";
1376
+ }
1377
+
1378
+ function eventName(event: Record<string, unknown>, fallback: string): string {
1379
+ return stringValue(event.name) ?? stringValue(event.message) ?? fallback;
1380
+ }
1381
+
1382
+ function eventTokens(event: Record<string, unknown>): number | null {
1383
+ if (!isRecord(event.message) || !isRecord(event.message.usage)) return null;
1384
+ return finiteNonNegative(event.message.usage.totalTokens) ?? finiteNonNegative(event.message.usage.total_tokens);
1385
+ }
1386
+
1387
+ function readableToolName(tool: string, args: unknown): string {
1388
+ if (isRecord(args)) {
1389
+ const target = stringValue(args.command) ?? stringValue(args.path) ?? stringValue(args.file_path);
1390
+ if (target !== null) return traceText(`${tool}: ${target.replace(/\s+/g, " ").trim()}`, 160);
1391
+ }
1392
+ return traceText(tool, 160);
1393
+ }
1394
+
1395
+ function boundedSnippet(value: unknown): string | null {
1396
+ if (value === null || value === undefined) return null;
1397
+ const encoded =
1398
+ typeof value === "string"
1399
+ ? value
1400
+ : JSON.stringify(value, (_key, current: unknown) => (typeof current === "bigint" ? current.toString() : current));
1401
+ const text = encoded ?? String(value);
1402
+ return Buffer.byteLength(text) <= 4096 ? text : `${Buffer.from(text).subarray(0, 4093).toString("utf8")}…`;
1403
+ }
1404
+
1405
+ function boundedJson(value: unknown): string {
1406
+ const serialized = JSON.stringify(value, (_key, current: unknown) =>
1407
+ typeof current === "bigint" ? current.toString() : current,
1408
+ );
1409
+ const json = serialized === undefined ? undefined : redactSecretsText(serialized, createRedactionTally());
1410
+ if (json === undefined) return "null";
1411
+ if (Buffer.byteLength(json) <= TRACE_PAYLOAD_LIMIT_BYTES) return json;
1412
+ return JSON.stringify({
1413
+ truncated: true,
1414
+ snippet: Buffer.from(json)
1415
+ .subarray(0, TRACE_PAYLOAD_LIMIT_BYTES - 128)
1416
+ .toString("utf8"),
1417
+ });
1418
+ }
1419
+
1420
+ function traceText(value: string, maxChars: number): string {
1421
+ return redactSecretsText(value, createRedactionTally())
1422
+ .replace(/[\r\n\t]+/g, " ")
1423
+ .slice(0, maxChars);
1424
+ }
1425
+
1426
+ function sha256(value: string): string {
1427
+ return createHash("sha256").update(value, "utf8").digest("hex");
1428
+ }
1429
+
1430
+ function assertSelectOnly(sql: string): void {
1431
+ const trimmed = sql.trim();
1432
+ if (!/^(SELECT|WITH)\b/i.test(trimmed)) throw new Error("trace sql accepts SELECT or read-only WITH queries only");
1433
+ if (trimmed.includes(";")) throw new Error("trace sql accepts exactly one statement");
1434
+ if (/\b(INSERT|UPDATE|DELETE|REPLACE|CREATE|ALTER|DROP|ATTACH|DETACH|VACUUM|PRAGMA)\b/i.test(trimmed)) {
1435
+ throw new Error("trace sql query is not read-only");
1436
+ }
1437
+ }
1438
+
1439
+ function clampInt(value: number, min: number, max: number): number {
1440
+ if (!Number.isFinite(value)) return min;
1441
+ return Math.min(max, Math.max(min, Math.trunc(value)));
1442
+ }
1443
+
1444
+ function isRecord(value: unknown): value is Record<string, unknown> {
1445
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1446
+ }
1447
+
1448
+ function stringValue(value: unknown): string | null {
1449
+ return typeof value === "string" && value.length > 0 ? value : null;
1450
+ }
1451
+
1452
+ function finiteNonNegative(value: unknown): number | null {
1453
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
1454
+ }