@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,1038 @@
1
+ /**
2
+ * Coalescing wrapper around chat events (slice 12.5d).
3
+ *
4
+ * Streaming responses fire `text_delta` / `thinking_delta` events at very
5
+ * high frequency. The TUI's per-event `requestRender()` call rebuilt the
6
+ * entire transcript on every delta, which scaled linearly with response
7
+ * length and made long answers visibly lag. This wrapper applies every
8
+ * event to the panel synchronously (so internal state stays consistent)
9
+ * but defers `requestRender()` for delta events to a single coalesced
10
+ * timer (~16ms = one frame at 60fps). Non-delta events render
11
+ * synchronously so finalizers like `message_end` are never deferred.
12
+ */
13
+
14
+ import type {
15
+ BashExecutionEntry,
16
+ BranchSummaryEntry,
17
+ CompactionSummaryEntry,
18
+ CustomEntry,
19
+ FileEntryEntry,
20
+ MessageEntry,
21
+ ModelChangeEntry,
22
+ ProtectedArtifactEntry,
23
+ SessionEntry,
24
+ SessionInfoEntry,
25
+ ThinkingLevelChangeEntry,
26
+ WorkerRunEntry,
27
+ } from "../domains/session/entries.js";
28
+ import { filterEntriesToActivePath } from "../domains/session/tree/active-path.js";
29
+ import { wrapTextWithAnsi } from "../engine/tui.js";
30
+ import type { AgentMessage } from "../engine/types.js";
31
+ import type { ChatLoopEvent, RetryStatusPayload } from "./chat-loop.js";
32
+ import { isSelfExplainingAbort } from "./chat-loop-messages.js";
33
+ import type { ChatPanel } from "./chat-panel.js";
34
+ import { renderBranchSummaryEntry } from "./renderers/branch-summary.js";
35
+ import { renderCompactionSummaryEntry } from "./renderers/compaction-summary.js";
36
+ import { styleTaggedNotice } from "./renderers/notice.js";
37
+ import { formatRetryStatus } from "./renderers/retry-status.js";
38
+ import { renderToolResultOnly } from "./renderers/tool-execution.js";
39
+ import { readWorkerReceiptFacts } from "./worker-receipts.js";
40
+ import { workerEntriesFromRunEntries } from "./worker-replay.js";
41
+ import type { WorkerReceiptReader } from "./worker-stream.js";
42
+
43
+ const DEFAULT_COALESCE_MS = 16;
44
+ const MAX_REPLAY_TEXT_CHARS = 20_000;
45
+
46
+ /**
47
+ * Event kinds whose render is deferred into a coalesce window. All other
48
+ * `ChatLoopEvent` kinds render synchronously and cancel any pending timer.
49
+ */
50
+ const DELTA_TYPES: ReadonlySet<ChatLoopEvent["type"]> = new Set(["text_delta", "thinking_delta"]);
51
+
52
+ export interface CreateCoalescingChatRendererDeps {
53
+ chatPanel: ChatPanel;
54
+ requestRender: () => void;
55
+ /** Coalesce window in ms. Defaults to 16 (one frame at 60fps). */
56
+ coalesceMs?: number;
57
+ /** Override for tests. Mirrors the setTimeout signature. */
58
+ setTimer?: (cb: () => void, ms: number) => unknown;
59
+ /** Override for tests. Mirrors the clearTimeout signature. */
60
+ clearTimer?: (id: unknown) => void;
61
+ /** Opt-in instrument; counts deltas so a frame row can report how many it absorbed. */
62
+ onDelta?: () => void;
63
+ }
64
+
65
+ export interface CoalescingChatRenderer {
66
+ applyEvent(event: ChatLoopEvent): void;
67
+ /** Cancel the pending coalesce timer (if any) and request one synchronous render. */
68
+ flush(): void;
69
+ }
70
+
71
+ export function createCoalescingChatRenderer(deps: CreateCoalescingChatRendererDeps): CoalescingChatRenderer {
72
+ const setTimer = deps.setTimer ?? ((cb, ms) => setTimeout(cb, ms));
73
+ const clearTimer =
74
+ deps.clearTimer ??
75
+ ((id) => {
76
+ clearTimeout(id as ReturnType<typeof setTimeout>);
77
+ });
78
+ const coalesceMs = deps.coalesceMs ?? DEFAULT_COALESCE_MS;
79
+
80
+ let pendingTimer: unknown = null;
81
+
82
+ const fireCoalesced = (): void => {
83
+ pendingTimer = null;
84
+ deps.requestRender();
85
+ };
86
+
87
+ const cancelPending = (): boolean => {
88
+ if (pendingTimer === null) return false;
89
+ clearTimer(pendingTimer);
90
+ pendingTimer = null;
91
+ return true;
92
+ };
93
+
94
+ return {
95
+ applyEvent(event) {
96
+ deps.chatPanel.applyEvent(event);
97
+ if (DELTA_TYPES.has(event.type)) {
98
+ deps.onDelta?.();
99
+ if (pendingTimer !== null) return;
100
+ pendingTimer = setTimer(fireCoalesced, coalesceMs);
101
+ return;
102
+ }
103
+ cancelPending();
104
+ deps.requestRender();
105
+ },
106
+ flush() {
107
+ const wasPending = cancelPending();
108
+ if (!wasPending) return;
109
+ deps.requestRender();
110
+ },
111
+ };
112
+ }
113
+
114
+ /**
115
+ * Options for the rehydrate helper used by /resume and /fork.
116
+ */
117
+ export interface RehydrateChatPanelOptions {
118
+ /**
119
+ * Select the active branch ancestry without truncating later sidecars.
120
+ * Live compaction replay uses this so a summary appended after the current
121
+ * message leaf remains visible. Unset offline readers retain their
122
+ * file-order fallback.
123
+ */
124
+ activeLeafTurnId?: string;
125
+ /**
126
+ * Pin the active-branch leaf and stop replay after that turn (inclusive).
127
+ * /tree switches and /fork pass the selected turn id so replay follows
128
+ * that turn's ancestry. Unset (default) treats the most recently appended
129
+ * message turn as the leaf.
130
+ */
131
+ uptoTurnId?: string;
132
+ /**
133
+ * Render orphan tool results (results with no matching prior call) in full,
134
+ * without the live view's middle-elision. `/export` sets this so its
135
+ * throwaway panel writes complete tool bodies; the paired-result path reads
136
+ * the same intent from the panel's `unboundedToolBodies` option.
137
+ */
138
+ unboundedToolBodies?: boolean;
139
+ /**
140
+ * Sealed-receipt reader for the worker blocks a `workerRun` entry names.
141
+ * Defaults to `<state>/receipts/<runId>.json`; tests inject their own. This
142
+ * is the one place replay reads outside the entry stream, and it swallows
143
+ * every failure, so a session whose receipts are gone still replays.
144
+ */
145
+ readWorkerReceipt?: WorkerReceiptReader;
146
+ }
147
+
148
+ function extractTurnText(payload: unknown): string {
149
+ if (typeof payload === "string") return payload;
150
+ if (!payload || typeof payload !== "object") return "";
151
+ const p = payload as Record<string, unknown>;
152
+ if (typeof p.text === "string") return p.text;
153
+ if (Array.isArray(p.content)) {
154
+ for (const block of p.content) {
155
+ if (!block || typeof block !== "object") continue;
156
+ const b = block as Record<string, unknown>;
157
+ if (b.type === "text" && typeof b.text === "string") return b.text;
158
+ }
159
+ }
160
+ return "";
161
+ }
162
+
163
+ function stringifyPreview(value: unknown, limit = 600): string {
164
+ if (value === undefined) return "";
165
+ if (typeof value === "string") return value.length <= limit ? value : `${value.slice(0, limit - 3)}...`;
166
+ try {
167
+ const text = JSON.stringify(value);
168
+ if (!text) return "";
169
+ return text.length <= limit ? text : `${text.slice(0, limit - 3)}...`;
170
+ } catch {
171
+ const text = String(value);
172
+ return text.length <= limit ? text : `${text.slice(0, limit - 3)}...`;
173
+ }
174
+ }
175
+
176
+ function truncateReplayText(text: string, limit = MAX_REPLAY_TEXT_CHARS): string {
177
+ if (text.length <= limit) return text;
178
+ const omitted = text.length - limit;
179
+ return `${text.slice(0, limit)}\n\n[... ${omitted} more characters truncated from replay context]`;
180
+ }
181
+
182
+ function timestampMillis(timestamp: string): number {
183
+ const parsed = Date.parse(timestamp);
184
+ return Number.isNaN(parsed) ? 0 : parsed;
185
+ }
186
+
187
+ function makeTextMessage(role: "user" | "assistant", text: string, timestamp: string): AgentMessage {
188
+ const message: Record<string, unknown> = {
189
+ role,
190
+ content: [{ type: "text", text }],
191
+ timestamp: timestampMillis(timestamp),
192
+ };
193
+ if (role === "assistant") message.stopReason = "stop";
194
+ return message as unknown as AgentMessage;
195
+ }
196
+
197
+ function cloneContentBlocks(content: unknown, maxTextChars?: number): unknown[] | null {
198
+ if (!Array.isArray(content)) return null;
199
+ return content
200
+ .filter((block) => !!block && typeof block === "object")
201
+ .map((block) => {
202
+ const cloned: Record<string, unknown> = { ...(block as Record<string, unknown>) };
203
+ if (typeof maxTextChars === "number") {
204
+ if (typeof cloned.text === "string") cloned.text = truncateReplayText(cloned.text, maxTextChars);
205
+ if (typeof cloned.thinking === "string") cloned.thinking = truncateReplayText(cloned.thinking, maxTextChars);
206
+ }
207
+ return cloned;
208
+ });
209
+ }
210
+
211
+ function richMessageFromEntry(entry: MessageEntry, maxTextChars?: number): AgentMessage | null {
212
+ if (entry.role !== "user" && entry.role !== "assistant") return null;
213
+ const obj = payloadObject(entry.payload);
214
+ const content = cloneContentBlocks(obj?.content, maxTextChars);
215
+ const text = truncateReplayText(extractTurnText(entry.payload), maxTextChars);
216
+ const stopReason = typeof obj?.stopReason === "string" ? obj.stopReason : undefined;
217
+ if (!content && text.length === 0 && !messageFailure(entry) && stopReason !== "length") return null;
218
+ const message: Record<string, unknown> = {
219
+ role: entry.role,
220
+ content: content ?? [{ type: "text", text }],
221
+ timestamp: timestampMillis(entry.timestamp),
222
+ };
223
+ if (entry.role === "assistant") {
224
+ const failure = messageFailure(entry);
225
+ message.stopReason = failure?.stopReason ?? stopReason ?? "stop";
226
+ if (failure) message.errorMessage = failure.errorMessage;
227
+ for (const key of [
228
+ "usage",
229
+ "api",
230
+ "provider",
231
+ "model",
232
+ "responseModel",
233
+ "responseId",
234
+ "diagnostics",
235
+ "contextUsageInvalidated",
236
+ ]) {
237
+ if (obj?.[key] !== undefined) message[key] = obj[key];
238
+ }
239
+ }
240
+ return message as unknown as AgentMessage;
241
+ }
242
+
243
+ function recordToolCallsFromMessage(message: AgentMessage, seen: Set<string>): void {
244
+ const content = (message as { content?: unknown }).content;
245
+ if (!Array.isArray(content)) return;
246
+ for (const block of content) {
247
+ if (!block || typeof block !== "object") continue;
248
+ const b = block as Record<string, unknown>;
249
+ if (b.type !== "toolCall") continue;
250
+ if (typeof b.id === "string" && b.id.length > 0) seen.add(b.id);
251
+ }
252
+ }
253
+
254
+ function toolCallMessageFromEntry(entry: MessageEntry): AgentMessage {
255
+ const call = extractToolCall(entry);
256
+ const block: Record<string, unknown> = { type: "toolCall", id: call.id, name: call.name };
257
+ if (call.args !== undefined) block.arguments = call.args;
258
+ return {
259
+ role: "assistant",
260
+ content: [block],
261
+ stopReason: "toolUse",
262
+ timestamp: timestampMillis(entry.timestamp),
263
+ } as unknown as AgentMessage;
264
+ }
265
+
266
+ function toolResultContent(result: unknown): unknown[] {
267
+ const obj = payloadObject(result);
268
+ if (Array.isArray(obj?.content)) {
269
+ return cloneContentBlocks(obj.content, MAX_REPLAY_TEXT_CHARS) ?? [];
270
+ }
271
+ if (isTextResult(result)) return [{ type: "text", text: truncateReplayText(result.text) }];
272
+ if (typeof result === "string") return [{ type: "text", text: truncateReplayText(result) }];
273
+ return [{ type: "text", text: stringifyPreview(result, 10_000) }];
274
+ }
275
+
276
+ function displayReplayToolResult(result: unknown): unknown {
277
+ const content = toolResultContent(result);
278
+ // Preserve the details record (observation envelope, exec records) so the
279
+ // replayed ledger line carries the same outcome facts as the live one.
280
+ const details = payloadObject(result)?.details;
281
+ return details !== null && details !== undefined && typeof details === "object" ? { content, details } : content;
282
+ }
283
+
284
+ function textFromContentBlocks(content: unknown): string {
285
+ if (!Array.isArray(content)) return "";
286
+ const parts: string[] = [];
287
+ for (const block of content) {
288
+ if (!block || typeof block !== "object") continue;
289
+ const b = block as Record<string, unknown>;
290
+ if (b.type === "text" && typeof b.text === "string") parts.push(b.text);
291
+ }
292
+ return parts.join("");
293
+ }
294
+
295
+ function toolResultText(result: unknown): string {
296
+ const obj = payloadObject(result);
297
+ const contentText = textFromContentBlocks(obj?.content);
298
+ if (contentText.length > 0) return contentText;
299
+ if (isTextResult(result)) return result.text;
300
+ if (typeof result === "string") return result;
301
+ return stringifyPreview(result, 10_000);
302
+ }
303
+
304
+ function comparableReplayText(text: string): string {
305
+ return text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").trim();
306
+ }
307
+
308
+ function messagePayloadComparableText(payload: unknown): string {
309
+ const text = extractTurnText(payload);
310
+ if (text.length > 0) return text;
311
+ return textFromContentBlocks(payloadObject(payload)?.content);
312
+ }
313
+
314
+ function isLegacyToolResultAssistantDuplicate(toolResult: MessageEntry, assistant: MessageEntry): boolean {
315
+ const priorText = comparableReplayText(toolResultText(extractToolResult(toolResult).result));
316
+ if (priorText.length === 0) return false;
317
+ const assistantText = comparableReplayText(messagePayloadComparableText(assistant.payload));
318
+ return assistantText.length > 0 && assistantText === priorText;
319
+ }
320
+
321
+ function isTextResult(value: unknown): value is { text: string } {
322
+ return payloadObject(value)?.text !== undefined && typeof (value as { text?: unknown }).text === "string";
323
+ }
324
+
325
+ function toolResultMessageFromEntry(entry: MessageEntry): AgentMessage {
326
+ const result = extractToolResult(entry);
327
+ return {
328
+ role: "toolResult",
329
+ content: toolResultContent(result.result),
330
+ toolCallId: result.id ?? entry.turnId,
331
+ toolName: result.name,
332
+ isError: result.isError,
333
+ timestamp: timestampMillis(entry.timestamp),
334
+ } as AgentMessage;
335
+ }
336
+
337
+ function textBlockFromEntry(entry: MessageEntry): string {
338
+ const text = extractTurnText(entry.payload);
339
+ if (text.length > 0) return text;
340
+ return stringifyPreview(entry.payload);
341
+ }
342
+
343
+ function chatMessageText(entry: MessageEntry): string {
344
+ return extractTurnText(entry.payload);
345
+ }
346
+
347
+ const LEADING_SYSTEM_REMINDER = /^\s*<system-reminder>[\s\S]*?<\/system-reminder>\s*/u;
348
+
349
+ /**
350
+ * What the operator typed for a replayed user turn. The persisted text is the
351
+ * composed prompt (a system-reminder block and any skill preamble ride ahead of
352
+ * the operator's words, as visible text the model receives), and the live
353
+ * transcript only ever showed the typed part. Entries written since the
354
+ * operator text was persisted carry it directly; older entries drop the
355
+ * leading reminder scaffolding so a /fork or /resume redraw does not attribute
356
+ * it to the operator (#81).
357
+ */
358
+ function replayedUserText(entry: MessageEntry): string {
359
+ const obj = payloadObject(entry.payload);
360
+ if (typeof obj?.operatorText === "string") return obj.operatorText;
361
+ let text = extractTurnText(entry.payload);
362
+ for (;;) {
363
+ const stripped = text.replace(LEADING_SYSTEM_REMINDER, "");
364
+ if (stripped === text) return text;
365
+ text = stripped;
366
+ }
367
+ }
368
+
369
+ function messageFailure(entry: MessageEntry): { stopReason: "error" | "aborted"; errorMessage: string } | null {
370
+ const obj = payloadObject(entry.payload);
371
+ if (!obj) return null;
372
+ const stopReason = obj?.stopReason;
373
+ if (stopReason !== "error" && stopReason !== "aborted") return null;
374
+ const raw = obj.errorMessage;
375
+ if (isSelfExplainingAbort({ stopReason, errorMessage: raw, text: extractTurnText(entry.payload) })) return null;
376
+ const errorMessage =
377
+ typeof raw === "string" && raw.length > 0
378
+ ? raw
379
+ : stopReason === "aborted"
380
+ ? "request aborted"
381
+ : "model target returned an error";
382
+ return { stopReason, errorMessage };
383
+ }
384
+
385
+ function payloadObject(payload: unknown): Record<string, unknown> | null {
386
+ return payload && typeof payload === "object" && !Array.isArray(payload) ? (payload as Record<string, unknown>) : null;
387
+ }
388
+
389
+ function parseMaybeJson(value: unknown): unknown {
390
+ if (typeof value !== "string") return value;
391
+ const trimmed = value.trim();
392
+ if (!trimmed) return value;
393
+ try {
394
+ return JSON.parse(trimmed) as unknown;
395
+ } catch {
396
+ return value;
397
+ }
398
+ }
399
+
400
+ function firstContentBlock(payload: unknown, type: string): Record<string, unknown> | null {
401
+ const obj = payloadObject(payload);
402
+ const content = obj?.content;
403
+ if (!Array.isArray(content)) return null;
404
+ for (const block of content) {
405
+ if (!block || typeof block !== "object") continue;
406
+ const b = block as Record<string, unknown>;
407
+ if (b.type === type) return b;
408
+ }
409
+ return null;
410
+ }
411
+
412
+ interface ReplayToolCall {
413
+ id: string;
414
+ name: string;
415
+ args: unknown;
416
+ }
417
+
418
+ function extractToolCall(entry: MessageEntry): ReplayToolCall {
419
+ const payload = entry.payload;
420
+ const obj = payloadObject(payload);
421
+ const block = firstContentBlock(payload, "toolCall");
422
+ const fn = payloadObject(obj?.function);
423
+ const id =
424
+ (typeof obj?.id === "string" && obj.id) ||
425
+ (typeof obj?.toolCallId === "string" && obj.toolCallId) ||
426
+ (typeof obj?.tool_call_id === "string" && obj.tool_call_id) ||
427
+ (typeof block?.id === "string" && block.id) ||
428
+ entry.turnId;
429
+ const name =
430
+ (typeof obj?.name === "string" && obj.name) ||
431
+ (typeof obj?.toolName === "string" && obj.toolName) ||
432
+ (typeof obj?.tool === "string" && obj.tool) ||
433
+ (typeof fn?.name === "string" && fn.name) ||
434
+ (typeof block?.name === "string" && block.name) ||
435
+ "tool";
436
+ const args =
437
+ obj?.arguments ??
438
+ obj?.args ??
439
+ obj?.input ??
440
+ parseMaybeJson(fn?.arguments) ??
441
+ block?.arguments ??
442
+ block?.args ??
443
+ undefined;
444
+ return { id, name, args };
445
+ }
446
+
447
+ interface ReplayToolResult {
448
+ id: string | null;
449
+ name: string;
450
+ result: unknown;
451
+ isError: boolean;
452
+ durationMs?: number;
453
+ resultSummary?: Record<string, unknown>;
454
+ /** Persisted admission verdict; absent on history written before it was recorded. */
455
+ outcome?: string;
456
+ blockReason?: string;
457
+ }
458
+
459
+ function extractToolResult(entry: MessageEntry): ReplayToolResult {
460
+ const payload = entry.payload;
461
+ const obj = payloadObject(payload);
462
+ const contentText = extractTurnText(payload);
463
+ const id =
464
+ (typeof obj?.toolCallId === "string" && obj.toolCallId) ||
465
+ (typeof obj?.tool_call_id === "string" && obj.tool_call_id) ||
466
+ (typeof obj?.id === "string" && obj.id) ||
467
+ null;
468
+ const name =
469
+ (typeof obj?.toolName === "string" && obj.toolName) ||
470
+ (typeof obj?.name === "string" && obj.name) ||
471
+ (typeof obj?.tool === "string" && obj.tool) ||
472
+ "tool";
473
+ const result =
474
+ obj?.result ?? obj?.output ?? obj?.out ?? obj?.content ?? (contentText.length > 0 ? contentText : payload);
475
+ const durationMs = typeof obj?.durationMs === "number" && Number.isFinite(obj.durationMs) ? obj.durationMs : undefined;
476
+ const resultSummary = payloadObject(obj?.resultSummary) ?? undefined;
477
+ const outcome = typeof obj?.outcome === "string" && obj.outcome.length > 0 ? obj.outcome : undefined;
478
+ const blockReason = typeof obj?.blockReason === "string" && obj.blockReason.length > 0 ? obj.blockReason : undefined;
479
+ return {
480
+ id,
481
+ name,
482
+ result,
483
+ isError: obj?.isError === true || obj?.error === true,
484
+ ...(durationMs !== undefined ? { durationMs } : {}),
485
+ ...(resultSummary !== undefined ? { resultSummary } : {}),
486
+ ...(outcome !== undefined ? { outcome } : {}),
487
+ ...(blockReason !== undefined ? { blockReason } : {}),
488
+ };
489
+ }
490
+
491
+ function renderReplayLine(text: string, width: number): string[] {
492
+ // Style a leading bracketed tag (`[skill]`, `[checkpoint]`, ...) dim with a
493
+ // muted body; free-form lines such as `system:` prefixes pass through
494
+ // unchanged so only bracketed notices pick up the treatment.
495
+ return wrapTextWithAnsi(styleTaggedNotice(text), width);
496
+ }
497
+
498
+ function appendReplayLine(chatPanel: ChatPanel, text: string): void {
499
+ chatPanel.appendReplayBlock((width) => renderReplayLine(truncateReplayText(text), width));
500
+ }
501
+
502
+ const BASH_REPLAY_MAX_LINES = 12;
503
+
504
+ export function renderBashExecutionEntry(entry: BashExecutionEntry, width: number): string[] {
505
+ const lines: string[] = [];
506
+ lines.push(...wrapTextWithAnsi(`bash: $ ${entry.command}`, width));
507
+ const output = truncateReplayText(entry.output.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\s+$/g, ""));
508
+ if (output.length > 0) {
509
+ const outputLines = output.split("\n");
510
+ const hidden = Math.max(0, outputLines.length - BASH_REPLAY_MAX_LINES);
511
+ const visible = outputLines.slice(-BASH_REPLAY_MAX_LINES);
512
+ if (hidden > 0) lines.push(...wrapTextWithAnsi(` ... ${hidden} earlier lines`, width));
513
+ for (const line of visible) {
514
+ lines.push(...wrapTextWithAnsi(` ${line}`, width));
515
+ }
516
+ } else {
517
+ lines.push(...wrapTextWithAnsi(" (no output)", width));
518
+ }
519
+ const status: string[] = [];
520
+ if (entry.cancelled) status.push("cancelled");
521
+ if (entry.exitCode !== null && entry.exitCode !== 0) status.push(`exit ${entry.exitCode}`);
522
+ if (entry.truncated) status.push(entry.fullOutputPath ? `truncated: ${entry.fullOutputPath}` : "truncated");
523
+ if (entry.excludeFromContext) status.push("excluded from context");
524
+ if (status.length > 0) lines.push(...wrapTextWithAnsi(` (${status.join(", ")})`, width));
525
+ return lines;
526
+ }
527
+
528
+ function renderRetryStatusEntry(entry: CustomEntry, width: number): string[] {
529
+ const data = payloadObject(entry.data);
530
+ if (!data) return wrapTextWithAnsi(styleTaggedNotice("[retry] status"), width);
531
+ const rawPhase = data.phase;
532
+ if (
533
+ rawPhase !== "scheduled" &&
534
+ rawPhase !== "waiting" &&
535
+ rawPhase !== "retrying" &&
536
+ rawPhase !== "cancelled" &&
537
+ rawPhase !== "exhausted" &&
538
+ rawPhase !== "recovered"
539
+ ) {
540
+ return wrapTextWithAnsi(styleTaggedNotice("[retry] status"), width);
541
+ }
542
+ const attempt = typeof data.attempt === "number" ? data.attempt : null;
543
+ const maxAttempts = typeof data.maxAttempts === "number" ? data.maxAttempts : null;
544
+ if (attempt === null || maxAttempts === null) return wrapTextWithAnsi(styleTaggedNotice("[retry] status"), width);
545
+ const status: RetryStatusPayload = {
546
+ phase: rawPhase,
547
+ attempt,
548
+ maxAttempts,
549
+ ...(typeof data.errorMessage === "string" && data.errorMessage.length > 0 ? { errorMessage: data.errorMessage } : {}),
550
+ ...(typeof data.delayMs === "number" ? { delayMs: data.delayMs } : {}),
551
+ ...(typeof data.seconds === "number" ? { seconds: data.seconds } : {}),
552
+ };
553
+ return wrapTextWithAnsi(formatRetryStatus(status), width);
554
+ }
555
+
556
+ /**
557
+ * Custom entries the replay renders. A custom entry is an extension point: some
558
+ * carry operator-facing text, and the rest are diagnostics the live transcript
559
+ * never shows. `promptRecompiled` is the latter, and replay dumped it as the
560
+ * literal type name plus a JSON blob of hashes in the middle of a resumed
561
+ * conversation, so a fork or resume showed a line the session itself never did.
562
+ * Rendering is opt-in: a known type, or `display: true` from a writer that means
563
+ * the entry to be seen.
564
+ */
565
+ function rendersCustomEntry(entry: CustomEntry): boolean {
566
+ if (entry.display === false) return false;
567
+ if (entry.customType === "retryStatus") return true;
568
+ if (entry.customType === "finishContractAdvisory" || entry.customType === "middlewareReminder") return true;
569
+ return entry.display === true;
570
+ }
571
+
572
+ function renderCustomEntry(entry: CustomEntry, width: number): string[] {
573
+ if (entry.customType === "retryStatus") return renderRetryStatusEntry(entry, width);
574
+ // "finishContractAdvisory" is the pre-middleware name for the same entry
575
+ // shape; older session ledgers still carry it.
576
+ if (entry.customType === "finishContractAdvisory" || entry.customType === "middlewareReminder") {
577
+ return renderReminderMessageEntry(entry, width);
578
+ }
579
+ if (entry.display !== true) return [];
580
+ const body = stringifyPreview(entry.data);
581
+ const suffix = body.length > 0 ? ` ${body}` : "";
582
+ return wrapTextWithAnsi(`custom:${entry.customType}${suffix}`, width);
583
+ }
584
+
585
+ function renderReminderMessageEntry(entry: CustomEntry, width: number): string[] {
586
+ const data = payloadObject(entry.data);
587
+ const message = typeof data?.message === "string" && data.message.length > 0 ? data.message : "middleware reminder";
588
+ return wrapTextWithAnsi(message, width);
589
+ }
590
+
591
+ function renderModelChangeEntry(entry: ModelChangeEntry, width: number): string[] {
592
+ const target = entry.target ? `${entry.target}/` : "";
593
+ return wrapTextWithAnsi(styleTaggedNotice(`[model] ${target}${entry.provider}/${entry.modelId}`), width);
594
+ }
595
+
596
+ function renderThinkingChangeEntry(entry: ThinkingLevelChangeEntry, width: number): string[] {
597
+ return wrapTextWithAnsi(styleTaggedNotice(`[thinking] ${entry.thinkingLevel}`), width);
598
+ }
599
+
600
+ function renderFileEntry(entry: FileEntryEntry, width: number): string[] {
601
+ const bytes = typeof entry.bytes === "number" ? `, ${entry.bytes} bytes` : "";
602
+ return wrapTextWithAnsi(styleTaggedNotice(`[file ${entry.operation}] ${entry.path}${bytes}`), width);
603
+ }
604
+
605
+ function renderProtectedArtifactEntry(entry: ProtectedArtifactEntry, width: number): string[] {
606
+ const validation =
607
+ entry.artifact.validationCommand === undefined
608
+ ? ""
609
+ : ` after ${entry.artifact.validationCommand}${entry.artifact.validationExitCode === undefined ? "" : ` exit ${entry.artifact.validationExitCode}`}`;
610
+ return wrapTextWithAnsi(
611
+ styleTaggedNotice(`[protected] ${entry.artifact.path}${validation}: ${entry.artifact.reason}`),
612
+ width,
613
+ );
614
+ }
615
+
616
+ function renderSessionInfoEntry(entry: SessionInfoEntry, width: number): string[] {
617
+ if (entry.name) return wrapTextWithAnsi(styleTaggedNotice(`[session] ${entry.name}`), width);
618
+ if (entry.label && entry.targetTurnId) {
619
+ return wrapTextWithAnsi(styleTaggedNotice(`[label] ${entry.targetTurnId}: ${entry.label}`), width);
620
+ }
621
+ return [];
622
+ }
623
+
624
+ function truncateAtTurn(entries: ReadonlyArray<SessionEntry>, uptoTurnId?: string): SessionEntry[] {
625
+ if (!uptoTurnId) return [...entries];
626
+ const index = entries.findIndex((entry) => entry.turnId === uptoTurnId);
627
+ if (index < 0) return [...entries];
628
+ return entries.slice(0, index + 1);
629
+ }
630
+
631
+ function latestCompactionIndex(entries: ReadonlyArray<SessionEntry>): number {
632
+ for (let i = entries.length - 1; i >= 0; i--) {
633
+ if (entries[i]?.kind === "compactionSummary") return i;
634
+ }
635
+ return -1;
636
+ }
637
+
638
+ function toolCallIdsInEntry(entry: SessionEntry): string[] {
639
+ if (entry.kind !== "message") return [];
640
+ if (entry.role === "tool_call") return [extractToolCall(entry).id];
641
+ if (entry.role !== "assistant") return [];
642
+ const obj = payloadObject(entry.payload);
643
+ if (!Array.isArray(obj?.content)) return [];
644
+ const ids: string[] = [];
645
+ for (const block of obj.content) {
646
+ if (!block || typeof block !== "object") continue;
647
+ const record = block as Record<string, unknown>;
648
+ if (record.type !== "toolCall") continue;
649
+ if (typeof record.id === "string" && record.id.length > 0) ids.push(record.id);
650
+ }
651
+ return ids;
652
+ }
653
+
654
+ function toolResultIdInEntry(entry: SessionEntry): string | null {
655
+ if (entry.kind !== "message" || entry.role !== "tool_result") return null;
656
+ return extractToolResult(entry).id;
657
+ }
658
+
659
+ function findPriorToolCallEntry(
660
+ entries: ReadonlyArray<SessionEntry>,
661
+ toolCallId: string,
662
+ endExclusive: number,
663
+ ): SessionEntry | null {
664
+ for (let index = Math.min(endExclusive, entries.length) - 1; index >= 0; index -= 1) {
665
+ const entry = entries[index];
666
+ if (!entry) continue;
667
+ if (toolCallIdsInEntry(entry).includes(toolCallId)) return entry;
668
+ }
669
+ return null;
670
+ }
671
+
672
+ function repairToolResultOrphans(
673
+ allEntries: ReadonlyArray<SessionEntry>,
674
+ selected: ReadonlyArray<SessionEntry>,
675
+ compactionIndex: number,
676
+ ): SessionEntry[] {
677
+ const out: SessionEntry[] = [];
678
+ const seenToolCalls = new Set<string>();
679
+ const emittedTurnIds = new Set<string>();
680
+ const remember = (entry: SessionEntry): void => {
681
+ emittedTurnIds.add(entry.turnId);
682
+ for (const id of toolCallIdsInEntry(entry)) seenToolCalls.add(id);
683
+ };
684
+ for (const entry of selected) {
685
+ const resultId = toolResultIdInEntry(entry);
686
+ if (resultId !== null && !seenToolCalls.has(resultId)) {
687
+ const dependency = findPriorToolCallEntry(allEntries, resultId, compactionIndex);
688
+ if (dependency !== null && !emittedTurnIds.has(dependency.turnId)) {
689
+ out.push(dependency);
690
+ remember(dependency);
691
+ }
692
+ }
693
+ out.push(entry);
694
+ remember(entry);
695
+ }
696
+ return out;
697
+ }
698
+
699
+ /**
700
+ * Normalize a heterogeneous session JSONL stream into the entry sequence the
701
+ * replay surfaces should show. The stream is first narrowed to the active
702
+ * branch of the turn tree (activeLeafTurnId selects a live branch;
703
+ * uptoTurnId selects and historically truncates; otherwise the most recent
704
+ * append wins), so abandoned sibling turns from earlier /tree switches never
705
+ * replay. When the remaining slice contains a compaction boundary, render the
706
+ * latest summary first and keep only the retained suffix plus later entries,
707
+ * mirroring pi-coding-agent's buildSessionContext behavior.
708
+ */
709
+ export function selectReplayEntries(
710
+ turns: ReadonlyArray<SessionEntry>,
711
+ options: RehydrateChatPanelOptions = {},
712
+ ): SessionEntry[] {
713
+ const active = filterEntriesToActivePath(turns, options.activeLeafTurnId ?? options.uptoTurnId);
714
+ const entries = truncateAtTurn(active, options.uptoTurnId);
715
+ const compactionIndex = latestCompactionIndex(entries);
716
+ if (compactionIndex < 0) return dropLegacyToolResultAssistantDuplicates(entries);
717
+
718
+ const compaction = entries[compactionIndex] as CompactionSummaryEntry;
719
+ const selected: SessionEntry[] = [compaction];
720
+ const firstKeptIndex = compaction.firstKeptTurnId
721
+ ? entries.findIndex((entry) => entry.turnId === compaction.firstKeptTurnId)
722
+ : -1;
723
+ if (firstKeptIndex >= 0 && firstKeptIndex < compactionIndex) {
724
+ selected.push(...entries.slice(firstKeptIndex, compactionIndex));
725
+ }
726
+ selected.push(...entries.slice(compactionIndex + 1));
727
+ return dropLegacyToolResultAssistantDuplicates(repairToolResultOrphans(entries, selected, compactionIndex));
728
+ }
729
+
730
+ function dropLegacyToolResultAssistantDuplicates(entries: ReadonlyArray<SessionEntry>): SessionEntry[] {
731
+ const out: SessionEntry[] = [];
732
+ for (const entry of entries) {
733
+ const previous = out[out.length - 1];
734
+ if (
735
+ entry.kind === "message" &&
736
+ entry.role === "assistant" &&
737
+ previous?.kind === "message" &&
738
+ previous.role === "tool_result" &&
739
+ isLegacyToolResultAssistantDuplicate(previous, entry)
740
+ ) {
741
+ continue;
742
+ }
743
+ out.push(entry);
744
+ }
745
+ return out;
746
+ }
747
+
748
+ function compactionContextText(entry: CompactionSummaryEntry): string {
749
+ return [
750
+ "The conversation history before this point was compacted into the following summary:",
751
+ "",
752
+ "<summary>",
753
+ entry.summary,
754
+ "</summary>",
755
+ ].join("\n");
756
+ }
757
+
758
+ function branchContextText(entry: BranchSummaryEntry): string {
759
+ return [
760
+ "The following is a summary of a branch that this conversation came back from:",
761
+ "",
762
+ "<summary>",
763
+ entry.summary,
764
+ "</summary>",
765
+ ].join("\n");
766
+ }
767
+
768
+ function bashContextText(entry: BashExecutionEntry): string {
769
+ let text = `Ran \`${entry.command}\`\n`;
770
+ const output = truncateReplayText(entry.output);
771
+ text += output.length > 0 ? `\`\`\`\n${output}\n\`\`\`` : "(no output)";
772
+ if (entry.cancelled) text += "\n\n(command cancelled)";
773
+ else if (entry.exitCode !== null && entry.exitCode !== 0) text += `\n\nCommand exited with code ${entry.exitCode}`;
774
+ if (entry.truncated && entry.fullOutputPath) text += `\n\n[Output truncated. Full output: ${entry.fullOutputPath}]`;
775
+ return text;
776
+ }
777
+
778
+ function appendContextMessage(out: AgentMessage[], role: "user" | "assistant", text: string, timestamp: string): void {
779
+ const trimmed = text.trim();
780
+ if (trimmed.length === 0) return;
781
+ out.push(makeTextMessage(role, truncateReplayText(trimmed), timestamp));
782
+ }
783
+
784
+ function skillActivationContextText(entry: Extract<SessionEntry, { kind: "skillActivation" }>): string {
785
+ const activation = entry.activation;
786
+ const turn = activation.turnId ? ` turn=${activation.turnId}` : "";
787
+ return `Active skill loaded: ${activation.name} source=${activation.source} hash=${activation.hash} path=${activation.filePath} triggeredBy=${activation.triggeredBy}${turn}. Continue honoring this skill unless the user changes direction.`;
788
+ }
789
+
790
+ export function buildReplayAgentMessagesFromTurns(
791
+ turns: ReadonlyArray<SessionEntry>,
792
+ options: RehydrateChatPanelOptions = {},
793
+ ): AgentMessage[] {
794
+ const out: AgentMessage[] = [];
795
+ const seenToolCalls = new Set<string>();
796
+ for (const entry of selectReplayEntries(turns, options)) {
797
+ switch (entry.kind) {
798
+ case "message": {
799
+ const text = textBlockFromEntry(entry);
800
+ if (entry.role === "user" || entry.role === "assistant") {
801
+ if (entry.role === "assistant" && messageFailure(entry)) break;
802
+ const message = richMessageFromEntry(entry, MAX_REPLAY_TEXT_CHARS);
803
+ if (message) {
804
+ out.push(message);
805
+ recordToolCallsFromMessage(message, seenToolCalls);
806
+ }
807
+ } else if (entry.role === "tool_call") {
808
+ const call = extractToolCall(entry);
809
+ if (!seenToolCalls.has(call.id)) {
810
+ const message = toolCallMessageFromEntry(entry);
811
+ out.push(message);
812
+ recordToolCallsFromMessage(message, seenToolCalls);
813
+ }
814
+ } else if (entry.role === "tool_result") {
815
+ out.push(toolResultMessageFromEntry(entry));
816
+ } else if (entry.role === "system") {
817
+ appendContextMessage(out, "user", `System note: ${text}`, entry.timestamp);
818
+ }
819
+ break;
820
+ }
821
+ case "bashExecution":
822
+ if (!entry.excludeFromContext) appendContextMessage(out, "user", bashContextText(entry), entry.timestamp);
823
+ break;
824
+ case "branchSummary":
825
+ appendContextMessage(out, "user", branchContextText(entry), entry.timestamp);
826
+ break;
827
+ case "compactionSummary":
828
+ appendContextMessage(out, "user", compactionContextText(entry), entry.timestamp);
829
+ break;
830
+ case "skillActivation":
831
+ appendContextMessage(out, "user", skillActivationContextText(entry), entry.timestamp);
832
+ break;
833
+ case "custom":
834
+ case "modelChange":
835
+ case "thinkingLevelChange":
836
+ case "fileEntry":
837
+ case "sessionInfo":
838
+ case "label":
839
+ case "protectedArtifact":
840
+ case "taskLedger":
841
+ // A worker's answer is not the operator's words and not the model's.
842
+ // It reaches the model only when an operator shares it, and a share
843
+ // is already a user message by the time it lands in the ledger.
844
+ case "workerRun":
845
+ break;
846
+ }
847
+ }
848
+ return out;
849
+ }
850
+
851
+ /**
852
+ * Rehydrate a chat panel from a persisted session's turn list. The
853
+ * interactive layer calls this after /resume or /fork so the user sees the
854
+ * prior transcript instead of a blank pane; without it, swapping the
855
+ * session contract updated meta but left the visible chat untouched
856
+ * (Row 51 and Row 52 on the Phase 12 ledger).
857
+ *
858
+ * Replays a structured SessionEntry stream. Compaction summaries, branch
859
+ * summaries, bash executions, custom entries, and metadata entries are
860
+ * rendered explicitly. Tool call/result entries are best-effort: when a
861
+ * result can be paired to a prior call id it updates that tool segment,
862
+ * otherwise it falls back to a standalone transcript line.
863
+ *
864
+ * Worker blocks are rebuilt from their `workerRun` entries plus the sealed
865
+ * receipts those entries name, so a resumed session shows the answer a `/run`
866
+ * produced rather than a header with nothing under it. The block is applied
867
+ * through the same panel call the live reducer uses, which is what makes an
868
+ * agent-origin card land under the tool segment that spawned it here too.
869
+ *
870
+ * Callers read turns via `openSession(id).turns()` and pass them in explicitly.
871
+ * The receipt reader is the one thing this touches beyond the panel; it is a
872
+ * parameter with a disk-backed default, and it never throws.
873
+ */
874
+ export function rehydrateChatPanelFromTurns(
875
+ chatPanel: ChatPanel,
876
+ turns: ReadonlyArray<SessionEntry>,
877
+ options: RehydrateChatPanelOptions = {},
878
+ ): void {
879
+ const pendingToolIds: string[] = [];
880
+ const selected = selectReplayEntries(turns, options);
881
+ // One block per assignment, drawn where its first attempt started. Later
882
+ // attempts of the same assignment fold into that block as `↻` rail lines, so
883
+ // a failover replays as the one run it was rather than as two.
884
+ const workerStates = workerEntriesFromRunEntries(
885
+ selected.filter((entry): entry is WorkerRunEntry => entry.kind === "workerRun"),
886
+ options.readWorkerReceipt ?? readWorkerReceiptFacts,
887
+ );
888
+ const placedAssignments = new Set<string>();
889
+ for (const entry of selected) {
890
+ switch (entry.kind) {
891
+ case "message": {
892
+ if (entry.role === "user") {
893
+ const text = truncateReplayText(replayedUserText(entry));
894
+ if (text.length > 0) chatPanel.appendUser(text);
895
+ break;
896
+ }
897
+ if (entry.role === "assistant") {
898
+ const text = chatMessageText(entry);
899
+ const failure = messageFailure(entry);
900
+ const richMessage = richMessageFromEntry(entry, MAX_REPLAY_TEXT_CHARS);
901
+ if (richMessage || text.length > 0 || failure) {
902
+ const message = richMessage ?? makeTextMessage("assistant", truncateReplayText(text), entry.timestamp);
903
+ if (failure) {
904
+ (message as { stopReason?: string; errorMessage?: string }).stopReason = failure.stopReason;
905
+ (message as { stopReason?: string; errorMessage?: string }).errorMessage = failure.errorMessage;
906
+ }
907
+ chatPanel.applyEvent({ type: "message_end", message });
908
+ chatPanel.applyEvent({ type: "agent_end", messages: [message] });
909
+ }
910
+ break;
911
+ }
912
+ if (entry.role === "tool_call") {
913
+ const call = extractToolCall(entry);
914
+ pendingToolIds.push(call.id);
915
+ chatPanel.applyEvent({
916
+ type: "tool_execution_start",
917
+ toolCallId: call.id,
918
+ toolName: call.name,
919
+ args: call.args,
920
+ });
921
+ break;
922
+ }
923
+ if (entry.role === "tool_result") {
924
+ const result = extractToolResult(entry);
925
+ const fallbackId = result.id ?? pendingToolIds.pop() ?? null;
926
+ if (fallbackId) {
927
+ const pendingIndex = pendingToolIds.indexOf(fallbackId);
928
+ if (pendingIndex >= 0) pendingToolIds.splice(pendingIndex, 1);
929
+ chatPanel.applyEvent({
930
+ type: "tool_execution_end",
931
+ toolCallId: fallbackId,
932
+ toolName: result.name,
933
+ result: displayReplayToolResult(result.result),
934
+ isError: result.isError,
935
+ ...(result.durationMs !== undefined ? { durationMs: result.durationMs } : {}),
936
+ ...(result.resultSummary !== undefined ? { resultSummary: result.resultSummary } : {}),
937
+ ...(result.outcome !== undefined ? { outcome: result.outcome } : {}),
938
+ ...(result.blockReason !== undefined ? { blockReason: result.blockReason } : {}),
939
+ } as ChatLoopEvent);
940
+ } else {
941
+ chatPanel.appendReplayBlock((width) =>
942
+ renderToolResultOnly(
943
+ {
944
+ toolCallId: result.id ?? "",
945
+ toolName: result.name,
946
+ result: displayReplayToolResult(result.result),
947
+ isError: result.isError,
948
+ ...(result.durationMs !== undefined ? { durationMs: result.durationMs } : {}),
949
+ ...(result.resultSummary !== undefined ? { resultSummary: result.resultSummary } : {}),
950
+ ...(result.outcome === "blocked" ? { outcome: "blocked" as const } : {}),
951
+ ...(result.blockReason !== undefined ? { blockReason: result.blockReason } : {}),
952
+ },
953
+ width,
954
+ { unbounded: options.unboundedToolBodies === true },
955
+ ),
956
+ );
957
+ }
958
+ break;
959
+ }
960
+ if (entry.role === "system") {
961
+ const text = textBlockFromEntry(entry);
962
+ if (text.length > 0) appendReplayLine(chatPanel, `system: ${text}`);
963
+ break;
964
+ }
965
+ if (entry.role === "checkpoint") {
966
+ const text = textBlockFromEntry(entry);
967
+ appendReplayLine(chatPanel, text.length > 0 ? `[checkpoint] ${text}` : "[checkpoint]");
968
+ break;
969
+ }
970
+ break;
971
+ }
972
+ case "bashExecution":
973
+ chatPanel.appendReplayBlock((width) => renderBashExecutionEntry(entry, width));
974
+ break;
975
+ case "custom":
976
+ if (rendersCustomEntry(entry)) chatPanel.appendReplayBlock((width) => renderCustomEntry(entry, width));
977
+ break;
978
+ case "modelChange":
979
+ chatPanel.appendReplayBlock((width) => renderModelChangeEntry(entry, width));
980
+ break;
981
+ case "thinkingLevelChange":
982
+ chatPanel.appendReplayBlock((width) => renderThinkingChangeEntry(entry, width));
983
+ break;
984
+ case "fileEntry":
985
+ chatPanel.appendReplayBlock((width) => renderFileEntry(entry, width));
986
+ break;
987
+ case "protectedArtifact":
988
+ chatPanel.appendReplayBlock((width) => renderProtectedArtifactEntry(entry, width));
989
+ break;
990
+ case "skillActivation":
991
+ appendReplayLine(chatPanel, `[skill] ${entry.activation.name} ${entry.activation.triggeredBy}`);
992
+ break;
993
+ case "branchSummary":
994
+ if (entry.summary.trim().length > 0) {
995
+ chatPanel.appendReplayBlock((width) =>
996
+ renderBranchSummaryEntry({ ...entry, summary: truncateReplayText(entry.summary) }, width),
997
+ );
998
+ }
999
+ break;
1000
+ case "compactionSummary":
1001
+ if (entry.summary.trim().length > 0) {
1002
+ chatPanel.appendReplayBlock((width) =>
1003
+ renderCompactionSummaryEntry({ ...entry, summary: truncateReplayText(entry.summary) }, width),
1004
+ );
1005
+ }
1006
+ break;
1007
+ case "sessionInfo":
1008
+ if (entry.name || entry.label) chatPanel.appendReplayBlock((width) => renderSessionInfoEntry(entry, width));
1009
+ break;
1010
+ case "workerRun": {
1011
+ if (placedAssignments.has(entry.assignmentId)) break;
1012
+ const state = workerStates.get(entry.assignmentId);
1013
+ if (state === undefined) break;
1014
+ placedAssignments.add(entry.assignmentId);
1015
+ chatPanel.applyWorkerState(state);
1016
+ break;
1017
+ }
1018
+ case "label":
1019
+ case "taskLedger":
1020
+ break;
1021
+ }
1022
+ }
1023
+ for (const pendingId of pendingToolIds) {
1024
+ chatPanel.applyEvent({
1025
+ type: "tool_execution_end",
1026
+ toolCallId: pendingId,
1027
+ toolName: "tool",
1028
+ result: "missing result; session ended before the tool completed",
1029
+ isError: true,
1030
+ });
1031
+ }
1032
+ // Replay reproduces the settled view: tools collapse to their one-line
1033
+ // ledger summary. The live path collapses tools because they fire while the
1034
+ // assistant is streaming (pending), a state replay cannot reconstruct
1035
+ // per-tool, so collapse them explicitly here. /export re-expands afterward
1036
+ // via toggleAllToolsExpanded; /resume and /fork keep the collapsed form.
1037
+ chatPanel.collapseAllTools();
1038
+ }