@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,426 @@
1
+ /**
2
+ * Post-run enforcement of declared write boundaries.
3
+ *
4
+ * This is detect-and-rollback, not sandboxing. Nothing here prevents a write:
5
+ * no container, no seccomp filter, no read-only mount, no interception of the
6
+ * worker's file tools. A step runs with whatever reach its tool permissions
7
+ * give it, and afterwards the orchestrator compares the checkout against the
8
+ * snapshot it took before the step, rolls back what the step was not allowed to
9
+ * change, and fails the step with a typed reason. An operator who needs a step
10
+ * to be *unable* to write outside its allowlist needs OS-level isolation, which
11
+ * this module deliberately does not claim to provide.
12
+ *
13
+ * Enforcement is orchestrator-side because a worker cannot be its own witness:
14
+ * a self-check runs inside the process whose behaviour is in question, so the
15
+ * only authority is the same one that seals result-contract validation.
16
+ *
17
+ * The comparison is git plumbing rather than a tree hash, because this runs
18
+ * after every bounded step and must stay proportionate: one `status` call plus
19
+ * one object-hash call over the dirty set, not a walk of the repository.
20
+ *
21
+ * Everything is pinned to the baseline commit recorded at snapshot time, so a
22
+ * commit step that moves HEAD without touching the working tree reads as "no
23
+ * change" instead of as a wholesale rewrite.
24
+ */
25
+
26
+ import { execFileSync } from "node:child_process";
27
+ import { createHash } from "node:crypto";
28
+ import { existsSync, lstatSync, mkdirSync, readlinkSync, realpathSync, rmSync, writeFileSync } from "node:fs";
29
+ import { dirname, join, relative, resolve, sep } from "node:path";
30
+ import { clioStateDir } from "../../core/xdg.js";
31
+ import { atomicWrite } from "../../engine/session.js";
32
+ import { isGitRepository } from "../../tools/compete-worktrees.js";
33
+ import {
34
+ describeWriteBoundary,
35
+ normalizeWriteBoundary,
36
+ type WriteBoundary,
37
+ writeBoundaryCovers,
38
+ } from "../agents/write-boundary.js";
39
+
40
+ /** Typed step failure an operator can act on: widen the declaration, or don't write there. */
41
+ export const WRITE_BOUNDARY_VIOLATION_REASON = "writes_boundary_violation";
42
+
43
+ /** Content token for a path that does not exist. */
44
+ const ABSENT = "absent";
45
+
46
+ const GIT_TIMEOUT_MS = 30_000;
47
+
48
+ function git(root: string, args: ReadonlyArray<string>, input?: string): string {
49
+ return execFileSync("git", ["-C", root, ...args], {
50
+ encoding: "utf8",
51
+ stdio: ["pipe", "pipe", "pipe"],
52
+ timeout: GIT_TIMEOUT_MS,
53
+ maxBuffer: 64 * 1024 * 1024,
54
+ ...(input === undefined ? {} : { input }),
55
+ });
56
+ }
57
+
58
+ function gitBytes(root: string, args: ReadonlyArray<string>): Buffer {
59
+ return execFileSync("git", ["-C", root, ...args], {
60
+ stdio: ["ignore", "pipe", "pipe"],
61
+ timeout: GIT_TIMEOUT_MS,
62
+ maxBuffer: 256 * 1024 * 1024,
63
+ });
64
+ }
65
+
66
+ /**
67
+ * Every path git currently reports as dirty, tracked or not. `-uall` lists
68
+ * untracked files individually: a collapsed directory entry cannot be compared
69
+ * against a path allowlist. `--no-renames` keeps one path per entry, so a
70
+ * rename reads as the delete and the create it is on disk.
71
+ *
72
+ * Enforcement sees exactly what git sees, so an ignored path is outside it: a
73
+ * repository decides what counts as its own content, and this is not the place
74
+ * to overrule that. The one thing subtracted is Clio's own state directory when
75
+ * an operator has placed it inside the workspace. Receipts, code-step logs, and
76
+ * boundary verdicts are the orchestrator writing its journal while the step
77
+ * runs, and blaming the step for them would make every window a violation.
78
+ */
79
+ function dirtyPaths(root: string): string[] {
80
+ const raw = git(root, ["status", "--porcelain=v1", "-z", "-uall", "--no-renames"]);
81
+ const journal = repoRelative(root, clioStateDir());
82
+ return raw
83
+ .split("\0")
84
+ .filter((entry) => entry.length > 3)
85
+ .map((entry) => entry.slice(3))
86
+ .filter((path) => journal === null || !(path === journal || path.startsWith(`${journal}/`)));
87
+ }
88
+
89
+ /**
90
+ * Content identity of one working-tree path.
91
+ *
92
+ * A blob hash rather than a status letter, because status is a statement about
93
+ * the index and this has to answer "are the bytes the same". A symlink is
94
+ * recorded as its target, so replacing a file with a link out of the repository
95
+ * is a change rather than an unreadable file.
96
+ */
97
+ function contentTokens(root: string, paths: ReadonlyArray<string>): Map<string, string> {
98
+ const tokens = new Map<string, string>();
99
+ const hashable: string[] = [];
100
+ for (const path of paths) {
101
+ const full = join(root, path);
102
+ let stat: ReturnType<typeof lstatSync>;
103
+ try {
104
+ stat = lstatSync(full);
105
+ } catch {
106
+ tokens.set(path, ABSENT);
107
+ continue;
108
+ }
109
+ if (stat.isSymbolicLink()) {
110
+ tokens.set(path, `link:${readlinkSync(full)}`);
111
+ continue;
112
+ }
113
+ if (stat.isDirectory()) {
114
+ tokens.set(path, "dir");
115
+ continue;
116
+ }
117
+ if (!stat.isFile()) {
118
+ tokens.set(path, `special:${stat.mode}`);
119
+ continue;
120
+ }
121
+ // A newline in a path would corrupt the batch protocol, so those paths
122
+ // are hashed one at a time rather than guessed at.
123
+ if (path.includes("\n")) {
124
+ tokens.set(path, `blob:${git(root, ["hash-object", "--", full]).trim()}`);
125
+ continue;
126
+ }
127
+ hashable.push(path);
128
+ }
129
+ if (hashable.length > 0) {
130
+ const hashes = git(root, ["hash-object", "--stdin-paths"], `${hashable.map((path) => join(root, path)).join("\n")}\n`)
131
+ .split("\n")
132
+ .filter((line) => line.length > 0);
133
+ hashable.forEach((path, index) => {
134
+ tokens.set(path, `blob:${hashes[index] ?? "unknown"}`);
135
+ });
136
+ }
137
+ return tokens;
138
+ }
139
+
140
+ /** Content identity of the same paths in the pinned baseline commit. */
141
+ function baselineTokens(root: string, head: string, paths: ReadonlyArray<string>): Map<string, string> {
142
+ const tokens = new Map<string, string>();
143
+ if (paths.length === 0) return tokens;
144
+ const query = paths.map((path) => `${head}:${path}`).join("\n");
145
+ const answered = git(root, ["cat-file", "--batch-check=%(objectname) %(objecttype)"], `${query}\n`)
146
+ .split("\n")
147
+ .filter((line) => line.length > 0);
148
+ paths.forEach((path, index) => {
149
+ const line = answered[index] ?? "";
150
+ const [objectName, objectType] = line.split(" ");
151
+ if (objectType === "blob" && objectName !== undefined) tokens.set(path, `blob:${objectName}`);
152
+ else if (objectType === "tree") tokens.set(path, "dir");
153
+ else tokens.set(path, ABSENT);
154
+ });
155
+ return tokens;
156
+ }
157
+
158
+ /**
159
+ * The workspace as it stood before a step ran: the commit every comparison is
160
+ * pinned to, plus the content identity of everything already dirty. The dirty
161
+ * half matters for rollback rather than for detection: a path this snapshot
162
+ * already found modified has no stored content anywhere, so a later
163
+ * unauthorized change to it cannot be undone without guessing.
164
+ */
165
+ export interface WorkspaceSnapshot {
166
+ root: string;
167
+ head: string;
168
+ /** Dirty path -> content token at capture time. */
169
+ entries: ReadonlyMap<string, string>;
170
+ capturedAt: string;
171
+ }
172
+
173
+ export function captureWorkspaceSnapshot(root: string): WorkspaceSnapshot {
174
+ const absolute = resolve(root);
175
+ if (!isGitRepository(absolute)) {
176
+ throw new Error(
177
+ `write boundary: ${absolute} is not a git repository, so a declared boundary cannot be verified (enforcement fails closed)`,
178
+ );
179
+ }
180
+ const head = git(absolute, ["rev-parse", "HEAD"]).trim();
181
+ const paths = dirtyPaths(absolute);
182
+ return { root: absolute, head, entries: contentTokens(absolute, paths), capturedAt: new Date().toISOString() };
183
+ }
184
+
185
+ export interface WorkspaceChange {
186
+ path: string;
187
+ before: string;
188
+ after: string;
189
+ }
190
+
191
+ /**
192
+ * What changed since the snapshot. Candidates are the paths that were dirty
193
+ * then plus the paths that are dirty now; anything else is identical to the
194
+ * baseline in both readings and cannot have been touched and restored in a way
195
+ * that matters to the repository.
196
+ */
197
+ export function diffWorkspace(snapshot: WorkspaceSnapshot): WorkspaceChange[] {
198
+ const candidates = [...new Set([...snapshot.entries.keys(), ...dirtyPaths(snapshot.root)])].sort();
199
+ if (candidates.length === 0) return [];
200
+ const unknownBefore = candidates.filter((path) => !snapshot.entries.has(path));
201
+ const baseline = baselineTokens(snapshot.root, snapshot.head, unknownBefore);
202
+ const now = contentTokens(snapshot.root, candidates);
203
+ const changes: WorkspaceChange[] = [];
204
+ for (const path of candidates) {
205
+ const before = snapshot.entries.get(path) ?? baseline.get(path) ?? ABSENT;
206
+ const after = now.get(path) ?? ABSENT;
207
+ if (before !== after) changes.push({ path, before, after });
208
+ }
209
+ return changes;
210
+ }
211
+
212
+ export interface WriteBoundaryRollback {
213
+ path: string;
214
+ action: "restored" | "removed";
215
+ /** Where the restored content came from, named so the record is checkable. */
216
+ restoredFrom: string;
217
+ }
218
+
219
+ export interface WriteBoundaryUnrecoverable {
220
+ path: string;
221
+ reason: string;
222
+ }
223
+
224
+ /**
225
+ * `clean` means nothing outside the allowlist changed. `rolled-back` means
226
+ * something did and the repository now looks as it did before. Anything else is
227
+ * `rollback-incomplete`: the working tree is left exactly as the step made it
228
+ * and handed to the operator with the list, because a rollback that guesses at
229
+ * content it never recorded destroys work.
230
+ */
231
+ export type WriteBoundaryStatus = "clean" | "rolled-back" | "rollback-incomplete";
232
+
233
+ export interface WriteBoundaryVerdict {
234
+ version: 1;
235
+ /** Which scheduling window this covers, e.g. `wave-2` or `revalidate-suite.check.1`. */
236
+ window: string;
237
+ /** Every step that ran inside the window. One id means exact attribution. */
238
+ stepIds: ReadonlyArray<string>;
239
+ /** The union the window was permitted to change. */
240
+ allow: ReadonlyArray<string>;
241
+ baselineHead: string;
242
+ capturedAt: string;
243
+ checkedAt: string;
244
+ changedPaths: ReadonlyArray<string>;
245
+ violations: ReadonlyArray<string>;
246
+ rolledBack: ReadonlyArray<WriteBoundaryRollback>;
247
+ unrecoverable: ReadonlyArray<WriteBoundaryUnrecoverable>;
248
+ status: WriteBoundaryStatus;
249
+ /** Typed failure reason, or null when the window stayed inside its boundary. */
250
+ reason: typeof WRITE_BOUNDARY_VIOLATION_REASON | null;
251
+ /** Operator-facing message naming the offending paths and the declaration. */
252
+ detail: string | null;
253
+ digest: string;
254
+ }
255
+
256
+ export interface EnforceWriteBoundaryInput {
257
+ snapshot: WorkspaceSnapshot;
258
+ window: string;
259
+ stepIds: ReadonlyArray<string>;
260
+ allow: WriteBoundary;
261
+ }
262
+
263
+ function canonicalVerdict(verdict: Omit<WriteBoundaryVerdict, "digest">): string {
264
+ return JSON.stringify(verdict);
265
+ }
266
+
267
+ /**
268
+ * Restore one unauthorized path.
269
+ *
270
+ * The only content this can restore is content git already has: the pinned
271
+ * baseline commit. A path that was already dirty when the snapshot was taken
272
+ * has its pre-step bytes nowhere but in the tree the step then overwrote, so it
273
+ * is reported rather than reconstructed.
274
+ */
275
+ function rollbackPath(
276
+ snapshot: WorkspaceSnapshot,
277
+ change: WorkspaceChange,
278
+ ): { rolledBack?: WriteBoundaryRollback; unrecoverable?: WriteBoundaryUnrecoverable } {
279
+ const full = join(snapshot.root, change.path);
280
+ if (snapshot.entries.has(change.path)) {
281
+ return {
282
+ unrecoverable: {
283
+ path: change.path,
284
+ reason: `path was already modified or untracked before the step, so its prior content is not recorded anywhere`,
285
+ },
286
+ };
287
+ }
288
+ if (change.before === ABSENT) {
289
+ try {
290
+ rmSync(full, { force: true, recursive: false });
291
+ } catch (error) {
292
+ return {
293
+ unrecoverable: { path: change.path, reason: `could not remove: ${(error as Error).message}` },
294
+ };
295
+ }
296
+ return { rolledBack: { path: change.path, action: "removed", restoredFrom: "did not exist at baseline" } };
297
+ }
298
+ if (!change.before.startsWith("blob:")) {
299
+ return {
300
+ unrecoverable: {
301
+ path: change.path,
302
+ reason: `baseline state '${change.before}' is not a regular file and is not restorable in place`,
303
+ },
304
+ };
305
+ }
306
+ try {
307
+ const content = gitBytes(snapshot.root, ["cat-file", "blob", `${snapshot.head}:${change.path}`]);
308
+ mkdirSync(dirname(full), { recursive: true });
309
+ // Written directly rather than through `git checkout`, which would also
310
+ // stage the path and quietly rewrite an operator's index.
311
+ writeFileSync(full, content);
312
+ } catch (error) {
313
+ return {
314
+ unrecoverable: { path: change.path, reason: `could not restore from baseline: ${(error as Error).message}` },
315
+ };
316
+ }
317
+ return { rolledBack: { path: change.path, action: "restored", restoredFrom: `${snapshot.head}:${change.path}` } };
318
+ }
319
+
320
+ /**
321
+ * Compare, roll back, and return the verdict. Never throws for a violation: a
322
+ * violation is evidence the caller records and acts on, not an exception that
323
+ * would lose the list of what was restored.
324
+ */
325
+ export function enforceWriteBoundary(input: EnforceWriteBoundaryInput): WriteBoundaryVerdict {
326
+ const allow = normalizeWriteBoundary(input.allow);
327
+ const changes = diffWorkspace(input.snapshot);
328
+ const violations = changes.filter((change) => !writeBoundaryCovers(allow, change.path));
329
+ const rolledBack: WriteBoundaryRollback[] = [];
330
+ const unrecoverable: WriteBoundaryUnrecoverable[] = [];
331
+ for (const change of violations) {
332
+ const outcome = rollbackPath(input.snapshot, change);
333
+ if (outcome.rolledBack !== undefined) rolledBack.push(outcome.rolledBack);
334
+ if (outcome.unrecoverable !== undefined) unrecoverable.push(outcome.unrecoverable);
335
+ }
336
+ const status: WriteBoundaryStatus =
337
+ violations.length === 0 ? "clean" : unrecoverable.length === 0 ? "rolled-back" : "rollback-incomplete";
338
+ const attribution =
339
+ input.stepIds.length === 1
340
+ ? `step '${input.stepIds[0]}'`
341
+ : `steps ${input.stepIds.map((id) => `'${id}'`).join(", ")} ran concurrently in one checkout, so the write cannot be attributed to one of them`;
342
+ const detail =
343
+ violations.length === 0
344
+ ? null
345
+ : [
346
+ `${attribution} wrote outside its declared boundary.`,
347
+ `Unauthorized paths: ${violations.map((change) => change.path).join(", ")}.`,
348
+ `Declared writes: ${describeWriteBoundary(allow)}.`,
349
+ status === "rolled-back"
350
+ ? "Those paths were rolled back to the baseline commit."
351
+ : `Rollback is incomplete; the working tree is left as the step made it. Unrestorable: ${unrecoverable
352
+ .map((entry) => `${entry.path} (${entry.reason})`)
353
+ .join("; ")}.`,
354
+ "If the change was legitimate, widen the step's `writes:` declaration to cover it.",
355
+ ].join(" ");
356
+ const body: Omit<WriteBoundaryVerdict, "digest"> = {
357
+ version: 1,
358
+ window: input.window,
359
+ stepIds: [...input.stepIds],
360
+ allow,
361
+ baselineHead: input.snapshot.head,
362
+ capturedAt: input.snapshot.capturedAt,
363
+ checkedAt: new Date().toISOString(),
364
+ changedPaths: changes.map((change) => change.path),
365
+ violations: violations.map((change) => change.path),
366
+ rolledBack,
367
+ unrecoverable,
368
+ status,
369
+ reason: violations.length === 0 ? null : WRITE_BOUNDARY_VIOLATION_REASON,
370
+ detail,
371
+ };
372
+ return { ...body, digest: createHash("sha256").update(canonicalVerdict(body), "utf8").digest("hex") };
373
+ }
374
+
375
+ /**
376
+ * Refuse a declaration that leaves the repository through a symlink. An entry
377
+ * is matched against git's own repo-relative paths, so a link that points
378
+ * outside can never be *reported* as changed; declaring it would create a
379
+ * boundary that silently permits nothing and hides real writes elsewhere.
380
+ */
381
+ export function assertWriteBoundaryInsideRoot(root: string, allow: WriteBoundary): void {
382
+ const realRoot = realpathSync(resolve(root));
383
+ for (const entry of allow) {
384
+ const relativeEntry = entry.endsWith("/") ? entry.slice(0, -1) : entry;
385
+ let probe = join(realRoot, relativeEntry);
386
+ // Resolve the longest existing prefix: a boundary may legitimately name a
387
+ // path a step is about to create.
388
+ while (probe !== realRoot && !existsSync(probe)) probe = dirname(probe);
389
+ const resolved = realpathSync(probe);
390
+ if (resolved !== realRoot && !resolved.startsWith(realRoot + sep)) {
391
+ throw new Error(`write boundary: entry '${entry}' resolves to ${resolved}, outside the workspace at ${realRoot}`);
392
+ }
393
+ }
394
+ }
395
+
396
+ /** Repo-relative form of an absolute path, or null when it is outside. */
397
+ function repoRelative(root: string, path: string): string | null {
398
+ const rel = relative(resolve(root), resolve(path));
399
+ if (rel.length === 0 || rel.startsWith("..") || rel.startsWith(`..${sep}`)) return null;
400
+ return rel.split(sep).join("/");
401
+ }
402
+
403
+ // ---------------------------------------------------------------------------
404
+ // Durable record
405
+ // ---------------------------------------------------------------------------
406
+
407
+ /**
408
+ * Verdicts are recorded beside the run ledger, in the shape code steps already
409
+ * use: `write-boundaries/<rootId>/<window>.json` under the Clio state
410
+ * directory. A verdict is a fact about the checkout across a scheduling window,
411
+ * not about one model run, so it has no receipt to be sealed inside; it carries
412
+ * its own digest and names the baseline commit it was computed against.
413
+ */
414
+ export function writeBoundaryDir(rootId: string): string {
415
+ return join(clioStateDir(), "write-boundaries", rootId);
416
+ }
417
+
418
+ function writeBoundaryVerdictPath(rootId: string, window: string): string {
419
+ return join(writeBoundaryDir(rootId), `${window.replace(/[^A-Za-z0-9._-]/gu, "_")}.json`);
420
+ }
421
+
422
+ export function writeWriteBoundaryVerdict(rootId: string, verdict: WriteBoundaryVerdict): string {
423
+ const path = writeBoundaryVerdictPath(rootId, verdict.window);
424
+ atomicWrite(path, `${JSON.stringify(verdict, null, 2)}\n`);
425
+ return path;
426
+ }
@@ -0,0 +1,42 @@
1
+ const SENSITIVE_KEY = /(?:^|[_-])(api[_-]?key|authorization|cookie|password|secret|token)(?:$|[_-])/i;
2
+
3
+ const CREDENTIAL_PATTERNS: Array<[RegExp, string]> = [
4
+ [/\b(authorization\s*[:=]\s*)(?:bearer|basic)\s+[A-Za-z0-9._~+/=-]+/gi, "$1[redacted]"],
5
+ [/\b(bearer\s+)[A-Za-z0-9._~+/=-]{12,}/gi, "$1[redacted]"],
6
+ [/\b(sk-[A-Za-z0-9_-]{16,})\b/g, "[redacted]"],
7
+ [/\b(gh[pousr]_[A-Za-z0-9_]{16,})\b/g, "[redacted]"],
8
+ [/\b(AKIA[0-9A-Z]{16})\b/g, "[redacted]"],
9
+ [/\b((?:api[_-]?key|access[_-]?token|refresh[_-]?token|password|secret)\s*[:=]\s*)[^\s"',}]+/gi, "$1[redacted]"],
10
+ ];
11
+
12
+ export function redactArtifactForStorage<T>(value: T, env: NodeJS.ProcessEnv = process.env): T {
13
+ return redactValue(value, env) as T;
14
+ }
15
+
16
+ function redactValue(value: unknown, env: NodeJS.ProcessEnv): unknown {
17
+ if (typeof value === "string") return redactString(value, env);
18
+ if (Array.isArray(value)) return value.map((entry) => redactValue(entry, env));
19
+ if (value !== null && typeof value === "object") {
20
+ const out: Record<string, unknown> = {};
21
+ for (const [key, entry] of Object.entries(value)) {
22
+ out[key] = SENSITIVE_KEY.test(key) ? "[redacted]" : redactValue(entry, env);
23
+ }
24
+ return out;
25
+ }
26
+ return value;
27
+ }
28
+
29
+ function redactString(value: string, env: NodeJS.ProcessEnv): string {
30
+ let out = stripHomePrefix(value, env.HOME);
31
+ for (const [pattern, replacement] of CREDENTIAL_PATTERNS) {
32
+ out = out.replace(pattern, replacement);
33
+ }
34
+ return out;
35
+ }
36
+
37
+ function stripHomePrefix(value: string, home: string | undefined): string {
38
+ if (home === undefined || home.length === 0) return value;
39
+ const normalized = home.replace(/\/+$/g, "");
40
+ if (normalized.length === 0) return value;
41
+ return value.split(normalized).join("$HOME");
42
+ }
@@ -0,0 +1,173 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { assertSafeId } from "../../../core/safe-id.js";
4
+ import { safeResourceWrite } from "../../../core/safe-resource-write.js";
5
+ import type { EvalArtifactV4, EvalTokenAccountingV4 } from "../schema/artifact.js";
6
+ import { evalRoot } from "../store.js";
7
+ import { redactArtifactForStorage } from "./redact.js";
8
+
9
+ function evalArtifactPathV4(dataDir: string, evalId: string): string {
10
+ assertSafeId(evalId, "eval");
11
+ return join(evalRoot(dataDir), `${evalId}.json`);
12
+ }
13
+
14
+ export async function writeEvalArtifactV4(dataDir: string, artifact: EvalArtifactV4, out?: string): Promise<string> {
15
+ const path =
16
+ out === undefined
17
+ ? evalArtifactPathV4(dataDir, artifact.evalId)
18
+ : out.endsWith(".json")
19
+ ? out
20
+ : join(out, `${artifact.evalId}.json`);
21
+ safeResourceWrite(path, `${JSON.stringify(redactArtifactForStorage(artifact), null, 2)}\n`, { encoding: "utf8" });
22
+ return path;
23
+ }
24
+
25
+ /**
26
+ * Read only the current explicit-link artifact format; retired shapes are
27
+ * rejected. An id with no artifact under the store root is named as such: the
28
+ * caller supplied an id, not a path, so the path node:fs would have quoted is
29
+ * not the thing they can correct.
30
+ */
31
+ export async function loadEvalArtifactV4(dataDir: string, evalId: string): Promise<EvalArtifactV4> {
32
+ let raw: string;
33
+ try {
34
+ raw = await readFile(evalArtifactPathV4(dataDir, evalId), "utf8");
35
+ } catch (error) {
36
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") throw new Error(`eval artifact not found: ${evalId}`);
37
+ throw error;
38
+ }
39
+ return parseEvalArtifactV4(JSON.parse(raw) as unknown, evalId);
40
+ }
41
+
42
+ export function parseEvalArtifactV4(value: unknown, source: string): EvalArtifactV4 {
43
+ if (!isRecord(value)) throw new Error(`${source}: expected object`);
44
+ if (value.version !== 4) throw new Error(`${source}.version: expected current version 4`);
45
+ const summary = asRecord(value.summary, `${source}.summary`);
46
+ const matrix = asRecord(value.matrix, `${source}.matrix`);
47
+ const suite = asRecord(value.suite, `${source}.suite`);
48
+ return {
49
+ version: 4,
50
+ evalId: readString(value, source, "evalId"),
51
+ suite: { id: readString(suite, `${source}.suite`, "id"), hash: readString(suite, `${source}.suite`, "hash") },
52
+ clio: {
53
+ version: readString(asRecord(value.clio, `${source}.clio`), `${source}.clio`, "version"),
54
+ commit: readNullableString(asRecord(value.clio, `${source}.clio`), `${source}.clio`, "commit"),
55
+ entry: readString(asRecord(value.clio, `${source}.clio`), `${source}.clio`, "entry"),
56
+ },
57
+ environment: {
58
+ platform: readString(asRecord(value.environment, `${source}.environment`), `${source}.environment`, "platform"),
59
+ node: readString(asRecord(value.environment, `${source}.environment`), `${source}.environment`, "node"),
60
+ },
61
+ matrix: {
62
+ target: readString(matrix, `${source}.matrix`, "target"),
63
+ model: readNullableString(matrix, `${source}.matrix`, "model"),
64
+ thinking: readNullableString(matrix, `${source}.matrix`, "thinking"),
65
+ },
66
+ summary: {
67
+ runs: readNumber(summary, `${source}.summary`, "runs"),
68
+ passed: readNumber(summary, `${source}.summary`, "passed"),
69
+ failed: readNumber(summary, `${source}.summary`, "failed"),
70
+ passRate: readNumber(summary, `${source}.summary`, "passRate"),
71
+ tokens: parseTokenAccounting(summary.tokens, `${source}.summary.tokens`),
72
+ wallTimeMs: readNumber(summary, `${source}.summary`, "wallTimeMs"),
73
+ },
74
+ results: readArray(value, source, "results").map((entry, index) => parseResult(entry, `${source}.results[${index}]`)),
75
+ };
76
+ }
77
+
78
+ /**
79
+ * An unmeasured artifact must carry no counts. Reading counts beside
80
+ * `measured: false` is a contradiction rather than a value to prefer, so it is
81
+ * refused instead of being resolved silently.
82
+ */
83
+ function parseTokenAccounting(value: unknown, source: string): EvalTokenAccountingV4 {
84
+ const record = asRecord(value, source);
85
+ const measured = readBoolean(record, source, "measured");
86
+ const runs = readNumber(record, source, "runs");
87
+ const measuredRuns = readNumber(record, source, "measuredRuns");
88
+ const countFields = ["input", "output", "total", "cacheRead", "cacheWrite"] as const;
89
+ if (!measured) {
90
+ if (measuredRuns !== 0) throw new Error(`${source}.measuredRuns: expected 0 when unmeasured`);
91
+ const present = countFields.filter((field) => field in record);
92
+ if (present.length > 0) throw new Error(`${source}: unmeasured accounting carries no counts (${present.join(", ")})`);
93
+ return { measured: false, runs, measuredRuns: 0 };
94
+ }
95
+ if (measuredRuns <= 0) throw new Error(`${source}.measuredRuns: expected a positive count when measured`);
96
+ return {
97
+ measured: true,
98
+ runs,
99
+ measuredRuns,
100
+ input: readNumber(record, source, "input"),
101
+ output: readNumber(record, source, "output"),
102
+ total: readNumber(record, source, "total"),
103
+ cacheRead: readNumber(record, source, "cacheRead"),
104
+ cacheWrite: readNumber(record, source, "cacheWrite"),
105
+ };
106
+ }
107
+
108
+ function parseResult(value: unknown, source: string): EvalArtifactV4["results"][number] {
109
+ const record = asRecord(value, source);
110
+ const target = asRecord(record.target, `${source}.target`);
111
+ return {
112
+ assignmentId: readNullableString(record, source, "assignmentId"),
113
+ terminalReceiptDigest: readNullableDigest(record, source, "terminalReceiptDigest"),
114
+ taskId: readString(record, source, "taskId"),
115
+ repeatIndex: readNumber(record, source, "repeatIndex"),
116
+ target: {
117
+ id: readString(target, `${source}.target`, "id"),
118
+ model: readNullableString(target, `${source}.target`, "model"),
119
+ thinking: readNullableString(target, `${source}.target`, "thinking"),
120
+ },
121
+ pass: readBoolean(record, source, "pass"),
122
+ failureClass: readNullableString(record, source, "failureClass"),
123
+ metrics: asRecord(record.metrics, `${source}.metrics`) as Record<string, number | string | boolean | null>,
124
+ artifacts: asRecord(record.artifacts, `${source}.artifacts`) as Record<string, string | string[] | null>,
125
+ };
126
+ }
127
+
128
+ function asRecord(value: unknown, source: string): Record<string, unknown> {
129
+ if (isRecord(value)) return value;
130
+ throw new Error(`${source}: expected object`);
131
+ }
132
+
133
+ function isRecord(value: unknown): value is Record<string, unknown> {
134
+ return typeof value === "object" && value !== null && !Array.isArray(value);
135
+ }
136
+
137
+ function readString(record: Record<string, unknown>, source: string, field: string): string {
138
+ const value = record[field];
139
+ if (typeof value !== "string" || value.length === 0) throw new Error(`${source}.${field}: expected string`);
140
+ return value;
141
+ }
142
+
143
+ function readNullableString(record: Record<string, unknown>, source: string, field: string): string | null {
144
+ const value = record[field];
145
+ if (value === null) return null;
146
+ if (typeof value !== "string" || value.length === 0) throw new Error(`${source}.${field}: expected string or null`);
147
+ return value;
148
+ }
149
+
150
+ function readNullableDigest(record: Record<string, unknown>, source: string, field: string): string | null {
151
+ const value = readNullableString(record, source, field);
152
+ if (value !== null && !/^[0-9a-f]{64}$/u.test(value))
153
+ throw new Error(`${source}.${field}: expected sha256 digest or null`);
154
+ return value;
155
+ }
156
+
157
+ function readNumber(record: Record<string, unknown>, source: string, field: string): number {
158
+ const value = record[field];
159
+ if (typeof value !== "number" || !Number.isFinite(value)) throw new Error(`${source}.${field}: expected number`);
160
+ return value;
161
+ }
162
+
163
+ function readBoolean(record: Record<string, unknown>, source: string, field: string): boolean {
164
+ const value = record[field];
165
+ if (typeof value !== "boolean") throw new Error(`${source}.${field}: expected boolean`);
166
+ return value;
167
+ }
168
+
169
+ function readArray(record: Record<string, unknown>, source: string, field: string): unknown[] {
170
+ const value = record[field];
171
+ if (!Array.isArray(value)) throw new Error(`${source}.${field}: expected array`);
172
+ return value;
173
+ }
@@ -0,0 +1,33 @@
1
+ import type { EvalArtifactV4 } from "../schema/artifact.js";
2
+
3
+ export interface EvalCompareV4Summary {
4
+ baselineEvalId: string;
5
+ candidateEvalId: string;
6
+ passRateDelta: number;
7
+ /** Null when either side observed no usage: a delta against an unknown is not zero. */
8
+ tokenDelta: number | null;
9
+ wallTimeDelta: number;
10
+ }
11
+
12
+ export function compareEvalArtifactsV4(baseline: EvalArtifactV4, candidate: EvalArtifactV4): EvalCompareV4Summary {
13
+ const baselineTokens = baseline.summary.tokens;
14
+ const candidateTokens = candidate.summary.tokens;
15
+ return {
16
+ baselineEvalId: baseline.evalId,
17
+ candidateEvalId: candidate.evalId,
18
+ passRateDelta: candidate.summary.passRate - baseline.summary.passRate,
19
+ tokenDelta: baselineTokens.measured && candidateTokens.measured ? candidateTokens.total - baselineTokens.total : null,
20
+ wallTimeDelta: candidate.summary.wallTimeMs - baseline.summary.wallTimeMs,
21
+ };
22
+ }
23
+
24
+ export function renderEvalComparisonV4(summary: EvalCompareV4Summary): string {
25
+ return [
26
+ `baseline eval: ${summary.baselineEvalId}`,
27
+ `candidate eval: ${summary.candidateEvalId}`,
28
+ `pass-rate delta: ${(summary.passRateDelta * 100).toFixed(2)}%`,
29
+ `token delta: ${summary.tokenDelta === null ? "unmeasured" : summary.tokenDelta}`,
30
+ `wall-time delta ms: ${summary.wallTimeDelta}`,
31
+ "",
32
+ ].join("\n");
33
+ }