@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,128 @@
1
+ /**
2
+ * Finish-contract assessor, packaged as a turn_end hook registration.
3
+ *
4
+ * The chat-loop fires `turn_end` with the final assistant text and this
5
+ * registration emits an advisory `inject_reminder` (severity "warn") when the
6
+ * turn mutated workspace state but recorded no validation evidence and no
7
+ * explicit limitation. The trigger is the observed mutation, not the wording of
8
+ * the assistant's text. The chat-loop's generic effect application renders the
9
+ * notice, persists the session entry, and flushes the reminder into the next
10
+ * model request. Every decision is also written to the audit ledger.
11
+ */
12
+
13
+ import { VERIFICATION_SCRIPT_FAMILY_HINT } from "../../core/verification-scripts.js";
14
+ import type { MiddlewareEffect, MiddlewareHookInput, MiddlewareHookRegistration } from "../middleware/index.js";
15
+ import type { CompletionContractAuditInput } from "./audit.js";
16
+ import { assessFinishContract, type FinishContractAssessment } from "./finish-contract.js";
17
+ import type { Rigor } from "./rigor.js";
18
+
19
+ export const FINISH_CONTRACT_REGISTRATION_ID = "assessor.finish-contract";
20
+
21
+ /**
22
+ * High-rigor re-prompt directive. Injected dynamically via effects (never added
23
+ * to the static system prompt) so the prompt prefix stays byte-stable. It tells
24
+ * the model to validate with a verification-family command or to state what
25
+ * could not be verified before claiming done. The command hint mirrors the
26
+ * vocabulary `detectValidationCommand` and `isVerificationScriptName` accept.
27
+ */
28
+ export const HIGH_RIGOR_REVALIDATION_MESSAGE =
29
+ `[Clio Coder] high-rigor finish gate: this completion claim has no validation evidence. ` +
30
+ `Before claiming done, run a verification command (the ${VERIFICATION_SCRIPT_FAMILY_HINT} family, ` +
31
+ `e.g. "npm run test", "npm run lint", "npm run build") or explicitly state what could not be verified ` +
32
+ `and why. Do not end the turn until you have validated or recorded the limitation.`;
33
+
34
+ export interface CreateFinishContractRegistrationOptions {
35
+ /**
36
+ * Current session entries for evidence collection, or null when no session
37
+ * is active. A null return disables assessment for the turn, matching the
38
+ * former chat-loop guard (`!deps.session?.current()`).
39
+ */
40
+ readSessionEntries: () => ReadonlyArray<unknown> | null;
41
+ /**
42
+ * Resolve the effective rigor for the current turn. Optional; defaults to
43
+ * `"normal"` (today's soft advisory) when absent. At `"high"` an
44
+ * unvalidated mutation re-prompts the model to validate or state a
45
+ * limitation instead of merely warning.
46
+ */
47
+ resolveRigor?: () => Rigor;
48
+ /**
49
+ * Record the contract's decision to the audit ledger. Optional; when wired
50
+ * (production passes the safety audit sink), every turn_end decision — each
51
+ * OK reason and each engagement — is written so the outcome is replayable
52
+ * from the JSONL alone. Failures here never affect the returned effects.
53
+ */
54
+ recordDecision?: (input: CompletionContractAuditInput) => void;
55
+ }
56
+
57
+ export function createFinishContractRegistration(
58
+ options: CreateFinishContractRegistrationOptions,
59
+ ): MiddlewareHookRegistration {
60
+ return {
61
+ id: FINISH_CONTRACT_REGISTRATION_ID,
62
+ description: "advise when a turn mutated files without validation evidence or an explicit limitation",
63
+ hooks: ["turn_end"],
64
+ evaluate(input: MiddlewareHookInput, context): ReadonlyArray<MiddlewareEffect> {
65
+ if (input.hook !== "turn_end") return [];
66
+ if (context?.priorEffects.some(isHardBlockEffect) === true) return [];
67
+ // Only settled stop turns make completion claims; aborted and error
68
+ // turns (including tool-prose interruptions) carry no finish contract.
69
+ // An absent stopReason is treated as "stop", mirroring
70
+ // finalAssistantStopMessage.
71
+ const stopReason = input.metadata?.stopReason;
72
+ if (stopReason !== undefined && stopReason !== "stop") return [];
73
+ const assistantText = input.text?.trim() ?? "";
74
+ if (assistantText.length === 0) return [];
75
+ let entries: ReadonlyArray<unknown> | null;
76
+ try {
77
+ entries = options.readSessionEntries();
78
+ } catch {
79
+ return [];
80
+ }
81
+ if (entries === null) return [];
82
+ const assessment = assessFinishContract({
83
+ assistantText,
84
+ sessionEntries: entries,
85
+ assistantTurnId: input.turnId ?? null,
86
+ });
87
+ const rigor = options.resolveRigor?.() ?? "normal";
88
+ recordDecision(options, input.turnId ?? null, assessment, rigor);
89
+ if (assessment.kind !== "engage") return [];
90
+ if (rigor === "high") {
91
+ // Withhold the completion and force a re-prompt: a continuation
92
+ // request carries the turn onward, and the paired reminder gives
93
+ // the directive its own visible system-reminder line.
94
+ return [
95
+ { kind: "request_continuation", message: HIGH_RIGOR_REVALIDATION_MESSAGE },
96
+ { kind: "inject_reminder", message: HIGH_RIGOR_REVALIDATION_MESSAGE, severity: "warn" },
97
+ ];
98
+ }
99
+ return [{ kind: "inject_reminder", message: assessment.message, severity: "warn" }];
100
+ },
101
+ };
102
+ }
103
+
104
+ function isHardBlockEffect(effect: MiddlewareEffect): boolean {
105
+ return effect.kind === "block_tool" || (effect.kind === "inject_reminder" && effect.severity === "hard-block");
106
+ }
107
+
108
+ function recordDecision(
109
+ options: CreateFinishContractRegistrationOptions,
110
+ turnId: string | null,
111
+ assessment: FinishContractAssessment,
112
+ rigor: Rigor,
113
+ ): void {
114
+ if (options.recordDecision === undefined) return;
115
+ const evidenceKinds = Array.from(new Set(assessment.evidence.map((item) => item.kind)));
116
+ try {
117
+ options.recordDecision({
118
+ turnId,
119
+ decision: assessment.kind,
120
+ reason: assessment.reason,
121
+ rigor,
122
+ mutatedPaths: assessment.mutatedPaths,
123
+ evidenceKinds,
124
+ });
125
+ } catch {
126
+ // Audit must never break the hot path; a failed ledger write is silent.
127
+ }
128
+ }
@@ -0,0 +1,554 @@
1
+ import { ToolNames } from "../../core/tool-names.js";
2
+ import { isVerificationScriptName } from "../../core/verification-scripts.js";
3
+ import {
4
+ detectValidationCommand,
5
+ extractCommandDeleteTargets,
6
+ extractCommandWriteTargets,
7
+ toolMutationPaths,
8
+ } from "./protected-artifacts.js";
9
+
10
+ export const FINISH_CONTRACT_ADVISORY_MESSAGE =
11
+ "[Clio Coder] finish-contract advisory: you changed files this turn without recording validation evidence or an explicit limitation. Run a verification command or state what could not be verified.";
12
+
13
+ /**
14
+ * The recent-window cap (entries since the last user message). Exported so a
15
+ * tail-scoped reader can size its read as a multiple of this and stay in lockstep
16
+ * with the window the contract actually inspects.
17
+ */
18
+ export const DEFAULT_RECENT_ENTRY_LIMIT = 80;
19
+
20
+ export type FinishContractEvidenceKind = "validation_command" | "protected_artifact" | "dispatch_receipt";
21
+
22
+ export interface FinishContractEvidence {
23
+ kind: FinishContractEvidenceKind;
24
+ summary: string;
25
+ turnId?: string;
26
+ }
27
+
28
+ /** Why the contract settled. Every branch is auditable from the ledger alone. */
29
+ export type FinishContractReason =
30
+ | "no_mutation"
31
+ | "validation_evidence"
32
+ | "explicit_limitation"
33
+ | "unvalidated_mutation";
34
+
35
+ export type FinishContractAssessment =
36
+ | {
37
+ kind: "ok";
38
+ reason: "no_mutation" | "validation_evidence" | "explicit_limitation";
39
+ evidence: ReadonlyArray<FinishContractEvidence>;
40
+ mutatedPaths: ReadonlyArray<string>;
41
+ }
42
+ | {
43
+ kind: "engage";
44
+ reason: "unvalidated_mutation";
45
+ message: string;
46
+ evidence: ReadonlyArray<FinishContractEvidence>;
47
+ mutatedPaths: ReadonlyArray<string>;
48
+ };
49
+
50
+ export interface FinishContractInput {
51
+ assistantText: string;
52
+ sessionEntries?: ReadonlyArray<unknown>;
53
+ assistantTurnId?: string | null;
54
+ recentEntryLimit?: number;
55
+ }
56
+
57
+ interface ToolCallEvidenceCandidate {
58
+ turnId?: string;
59
+ toolCallId: string;
60
+ command: string;
61
+ }
62
+
63
+ interface MutationCandidate {
64
+ toolCallId: string;
65
+ paths: string[];
66
+ }
67
+
68
+ const LIMITATION_PATTERNS: ReadonlyArray<RegExp> = [
69
+ /\b(?:blocked by|blocker|blockers|unable to|not able to|could not|couldn't|cannot|can't)\b/i,
70
+ /\b(?:did not|didn't|have not|haven't|has not|hasn't|was not able|wasn't able)\b/i,
71
+ /\b(?:not complete|incomplete)\b/i,
72
+ /\b(?:not|un)(?:\s|-)?(?:validated|verified|tested)\b/i,
73
+ /^\s*Tests\s*:\s*(?:not run|not executed|not available|failed|blocked|skipped)\b/im,
74
+ /^\s*Known gaps?\s*:\s*(?!\s*(?:none|no\b|n\/a|not applicable)\b).+/im,
75
+ /\bremaining(?:\s+\w+){0,3}\s+(?:work|issue|issues|gap|gaps|blocker|blockers)\b/i,
76
+ ];
77
+
78
+ /**
79
+ * Action-scoped completion contract. The engine keys off what the turn actually
80
+ * DID, not how the prompt was phrased: it engages only when the recent window
81
+ * mutated workspace state and then settled (turn_end) without recording
82
+ * validation evidence or an explicit limitation. The turn settling is itself
83
+ * the completion signal, so the model never has to type "done" to be gated, and
84
+ * a work request phrased as a question cannot bypass the gate.
85
+ *
86
+ * Decision order (pure function of ledger receipts):
87
+ * 1. no mutating receipt in the window -> ok/no_mutation
88
+ * 2. validation evidence present -> ok/validation_evidence
89
+ * 3. explicit limitation stated in the text -> ok/explicit_limitation
90
+ * 4. otherwise -> engage/unvalidated_mutation
91
+ */
92
+ export function assessFinishContract(input: FinishContractInput): FinishContractAssessment {
93
+ const assistantText = input.assistantText.trim();
94
+ const sessionEntries = input.sessionEntries ?? [];
95
+ const assistantTurnId = input.assistantTurnId ?? null;
96
+ const window = recentEntries(sessionEntries, assistantTurnId, input.recentEntryLimit ?? DEFAULT_RECENT_ENTRY_LIMIT);
97
+
98
+ const mutatedPaths = mutatingReceipts(window);
99
+ if (mutatedPaths.length === 0) {
100
+ return { kind: "ok", reason: "no_mutation", evidence: [], mutatedPaths };
101
+ }
102
+
103
+ const evidence = collectValidationEvidence(window);
104
+ if (evidence.length > 0) {
105
+ return { kind: "ok", reason: "validation_evidence", evidence, mutatedPaths };
106
+ }
107
+
108
+ if (hasExplicitLimitation(assistantText)) {
109
+ return { kind: "ok", reason: "explicit_limitation", evidence: [], mutatedPaths };
110
+ }
111
+
112
+ return {
113
+ kind: "engage",
114
+ reason: "unvalidated_mutation",
115
+ message: FINISH_CONTRACT_ADVISORY_MESSAGE,
116
+ evidence: [],
117
+ mutatedPaths,
118
+ };
119
+ }
120
+
121
+ /**
122
+ * The single retained text escape valve: the assistant explicitly states what
123
+ * it could not verify. Everything else about the contract is receipt-grounded;
124
+ * this is the one place prose still drives the decision. Candidate for a future
125
+ * structured "limitation" signal so the whole gate becomes text-independent.
126
+ */
127
+ function hasExplicitLimitation(text: string): boolean {
128
+ const normalized = text.trim();
129
+ if (normalized.length === 0) return false;
130
+ return LIMITATION_PATTERNS.some((pattern) => pattern.test(normalized));
131
+ }
132
+
133
+ /**
134
+ * Paths the turn actually mutated, drawn only from successful (non-error)
135
+ * receipts inside the window:
136
+ * - write / edit / artifact, via `toolMutationPaths`.
137
+ * - bash whose command carries a workspace write or delete target, via
138
+ * `extractCommandWriteTargets` / `extractCommandDeleteTargets`.
139
+ * Read-only git and pure read/grep/find/ls/exec/web_fetch receipts contribute
140
+ * nothing, so the contract can never fire on a retrieval or execution-only
141
+ * turn. Grounded in the same mutation notion the action classifier records, so
142
+ * the audit ledger and this gate stay consistent about what counts as a change.
143
+ */
144
+ function mutatingReceipts(recent: ReadonlyArray<unknown>): string[] {
145
+ const mutationCalls = new Map<string, MutationCandidate>();
146
+ const paths: string[] = [];
147
+ const seen = new Set<string>();
148
+
149
+ for (const entry of recent) {
150
+ // A user-run `!` bash execution is self-contained: it carries its own
151
+ // success signal, so any mutation targets count without a paired result.
152
+ const bashMutation = bashExecutionMutationPaths(entry);
153
+ if (bashMutation !== null) {
154
+ for (const path of bashMutation) pushPath(paths, seen, path);
155
+ continue;
156
+ }
157
+
158
+ const call = mutatingToolCall(entry);
159
+ if (call !== null) {
160
+ mutationCalls.set(call.toolCallId, call);
161
+ continue;
162
+ }
163
+
164
+ const resultId = successfulToolResultId(entry);
165
+ if (resultId !== null) {
166
+ const candidate = mutationCalls.get(resultId);
167
+ if (candidate !== undefined) {
168
+ for (const path of candidate.paths) pushPath(paths, seen, path);
169
+ }
170
+ }
171
+ }
172
+
173
+ return paths;
174
+ }
175
+
176
+ /** Mutation targets for a tool call, empty for read-only/execute-only tools. */
177
+ function mutationPathsForTool(toolName: string, args: Record<string, unknown> | undefined): string[] {
178
+ if (toolName === ToolNames.Bash) {
179
+ const command = typeof args?.command === "string" ? args.command : null;
180
+ if (command === null) return [];
181
+ return [...extractCommandWriteTargets(command), ...extractCommandDeleteTargets(command)];
182
+ }
183
+ return toolMutationPaths(toolName, args);
184
+ }
185
+
186
+ function mutatingToolCall(entry: unknown): MutationCandidate | null {
187
+ const record = asRecord(entry);
188
+ if (record?.kind !== "message" || record.role !== "tool_call") return null;
189
+ const payload = asRecord(record.payload);
190
+ if (payload === null) return null;
191
+ const toolName = stringFromFirst(payload, ["name", "toolName", "tool"]);
192
+ if (toolName === null) return null;
193
+ const args = asRecord(payload.args ?? payload.arguments ?? payload.input) ?? undefined;
194
+ const paths = mutationPathsForTool(toolName, args);
195
+ if (paths.length === 0) return null;
196
+ const toolCallId = stringFromFirst(payload, ["toolCallId", "tool_call_id", "id"]) ?? turnIdOf(entry);
197
+ if (toolCallId === null) return null;
198
+ return { toolCallId, paths };
199
+ }
200
+
201
+ /**
202
+ * Mutation targets of a settled `!` bash execution entry. Returns null when the
203
+ * entry is not a successful bash execution so the caller falls through to the
204
+ * tool_call/tool_result pairing path; returns `[]` for a successful command
205
+ * with no write/delete target (a read-only `!` command is not a mutation).
206
+ */
207
+ function bashExecutionMutationPaths(entry: unknown): string[] | null {
208
+ const record = asRecord(entry);
209
+ if (record?.kind !== "bashExecution") return null;
210
+ if (typeof record.command !== "string") return null;
211
+ if (record.cancelled === true || record.exitCode !== 0) return null;
212
+ return [...extractCommandWriteTargets(record.command), ...extractCommandDeleteTargets(record.command)];
213
+ }
214
+
215
+ function pushPath(paths: string[], seen: Set<string>, path: string): void {
216
+ if (path.length === 0 || seen.has(path)) return;
217
+ seen.add(path);
218
+ paths.push(path);
219
+ }
220
+
221
+ /**
222
+ * Receipt-based validation evidence over the recent window. Kept verbatim from
223
+ * the pre-redesign engine minus the requested-inspection path: validation
224
+ * commands (`detectValidationCommand`), verify check runs, passed dispatch
225
+ * receipts, and protected-artifact records.
226
+ * Inspection was removed because inspecting the repo is never a mutation, so it
227
+ * can no longer be on the path to engaging the contract.
228
+ */
229
+ function collectValidationEvidence(recent: ReadonlyArray<unknown>): FinishContractEvidence[] {
230
+ const evidence: FinishContractEvidence[] = [];
231
+ const toolCalls = new Map<string, ToolCallEvidenceCandidate>();
232
+ const dispatchCalls = new Map<string, ToolCallEvidenceCandidate>();
233
+ const seen = new Set<string>();
234
+
235
+ for (const entry of recent) {
236
+ const protectedArtifact = protectedArtifactEvidence(entry);
237
+ if (protectedArtifact !== null) {
238
+ pushEvidence(evidence, seen, protectedArtifact);
239
+ continue;
240
+ }
241
+
242
+ const call = bashValidationCall(entry);
243
+ if (call !== null) {
244
+ toolCalls.set(call.toolCallId, call);
245
+ continue;
246
+ }
247
+
248
+ const typedValidationCall = validationToolCall(entry);
249
+ if (typedValidationCall !== null) {
250
+ toolCalls.set(typedValidationCall.toolCallId, typedValidationCall);
251
+ continue;
252
+ }
253
+
254
+ const dispatchCall = dispatchEvidenceCall(entry);
255
+ if (dispatchCall !== null) {
256
+ dispatchCalls.set(dispatchCall.toolCallId, dispatchCall);
257
+ continue;
258
+ }
259
+
260
+ const resultId = successfulToolResultId(entry);
261
+ if (resultId !== null) {
262
+ const dispatchCandidate = dispatchCalls.get(resultId);
263
+ const dispatchReceipt = dispatchReceiptEvidence(entry, dispatchCandidate);
264
+ if (dispatchReceipt !== null) {
265
+ pushEvidence(evidence, seen, dispatchReceipt);
266
+ continue;
267
+ }
268
+ const candidate = toolCalls.get(resultId);
269
+ if (candidate !== undefined) {
270
+ pushEvidence(evidence, seen, validationEvidence(candidate));
271
+ }
272
+ continue;
273
+ }
274
+
275
+ const bashExecution = bashExecutionEvidence(entry);
276
+ if (bashExecution !== null) pushEvidence(evidence, seen, bashExecution);
277
+ }
278
+
279
+ return evidence;
280
+ }
281
+
282
+ function recentEntries(
283
+ entries: ReadonlyArray<unknown>,
284
+ assistantTurnId: string | null,
285
+ recentEntryLimit: number,
286
+ ): ReadonlyArray<unknown> {
287
+ const boundedLimit =
288
+ Number.isFinite(recentEntryLimit) && recentEntryLimit > 0 ? Math.floor(recentEntryLimit) : DEFAULT_RECENT_ENTRY_LIMIT;
289
+ const assistantIndex =
290
+ assistantTurnId === null ? -1 : entries.findIndex((entry) => turnIdOf(entry) === assistantTurnId);
291
+ const endExclusive = assistantIndex >= 0 ? assistantIndex : entries.length;
292
+ let startInclusive = Math.max(0, endExclusive - boundedLimit);
293
+ for (let index = endExclusive - 1; index >= startInclusive; index -= 1) {
294
+ if (isUserMessageEntry(entries[index])) {
295
+ startInclusive = index + 1;
296
+ break;
297
+ }
298
+ }
299
+ return entries.slice(startInclusive, endExclusive);
300
+ }
301
+
302
+ function bashValidationCall(entry: unknown): ToolCallEvidenceCandidate | null {
303
+ const record = asRecord(entry);
304
+ if (record?.kind !== "message" || record.role !== "tool_call") return null;
305
+ const payload = asRecord(record.payload);
306
+ if (payload === null) return null;
307
+ const toolName = stringFromFirst(payload, ["name", "toolName", "tool"]);
308
+ if (toolName !== "bash") return null;
309
+ const args = asRecord(payload.args ?? payload.arguments ?? payload.input);
310
+ const command = typeof args?.command === "string" ? args.command : null;
311
+ if (command === null) return null;
312
+ const detected = detectValidationCommand(command);
313
+ if (detected.kind !== "validation") return null;
314
+ const toolCallId = stringFromFirst(payload, ["toolCallId", "tool_call_id", "id"]) ?? turnIdOf(entry);
315
+ if (toolCallId === null) return null;
316
+ const candidate: ToolCallEvidenceCandidate = {
317
+ toolCallId,
318
+ command: detected.matched,
319
+ };
320
+ const turnId = turnIdOf(entry);
321
+ if (turnId !== null) candidate.turnId = turnId;
322
+ return candidate;
323
+ }
324
+
325
+ function dispatchEvidenceCall(entry: unknown): ToolCallEvidenceCandidate | null {
326
+ const record = asRecord(entry);
327
+ if (record?.kind !== "message" || record.role !== "tool_call") return null;
328
+ const payload = asRecord(record.payload);
329
+ if (payload === null) return null;
330
+ const toolName = stringFromFirst(payload, ["name", "toolName", "tool"]);
331
+ if (toolName !== "dispatch") return null;
332
+ const args = asRecord(payload.args ?? payload.arguments ?? payload.input);
333
+ const { agentId, task } = dispatchCallDescriptor(args);
334
+ const toolCallId = stringFromFirst(payload, ["toolCallId", "tool_call_id", "id"]) ?? turnIdOf(entry);
335
+ if (toolCallId === null) return null;
336
+ const candidate: ToolCallEvidenceCandidate = {
337
+ toolCallId,
338
+ command: `agent=${agentId}${task.length > 0 ? ` task=${task}` : ""}`,
339
+ };
340
+ const turnId = turnIdOf(entry);
341
+ if (turnId !== null) candidate.turnId = turnId;
342
+ return candidate;
343
+ }
344
+
345
+ /**
346
+ * Agent id and lead task text for a dispatch call, tolerant of both the toolkit
347
+ * v2 `tasks` array (task strings or {agent, task} objects, with an optional
348
+ * shared default agent) and the legacy single `task` argument. Only the first
349
+ * task seeds the summary; it feeds the receipt evidence's agent fallback and the
350
+ * audit line, never the gate decision itself.
351
+ */
352
+ function dispatchCallDescriptor(args: Record<string, unknown> | null): { agentId: string; task: string } {
353
+ const defaultAgent = stringFromFirst(args ?? {}, ["agent", "agent_id", "agentId"]);
354
+ const tasks = Array.isArray(args?.tasks) ? args.tasks : null;
355
+ if (tasks !== null && tasks.length > 0) {
356
+ const first = tasks[0];
357
+ if (typeof first === "string") {
358
+ return { agentId: defaultAgent ?? "coder", task: first.trim() };
359
+ }
360
+ const firstRecord = asRecord(first);
361
+ const itemAgent = firstRecord === null ? null : stringFromFirst(firstRecord, ["agent", "agent_id", "agentId"]);
362
+ const itemTask = typeof firstRecord?.task === "string" ? firstRecord.task.trim() : "";
363
+ return { agentId: itemAgent ?? defaultAgent ?? "coder", task: itemTask };
364
+ }
365
+ const singleTask = typeof args?.task === "string" ? args.task.trim() : "";
366
+ return { agentId: defaultAgent ?? "coder", task: singleTask };
367
+ }
368
+
369
+ function validationToolCall(entry: unknown): ToolCallEvidenceCandidate | null {
370
+ const record = asRecord(entry);
371
+ if (record?.kind !== "message" || record.role !== "tool_call") return null;
372
+ const payload = asRecord(record.payload);
373
+ if (payload === null) return null;
374
+ const toolName = stringFromFirst(payload, ["name", "toolName", "tool"]);
375
+ if (toolName === null) return null;
376
+ const summary = typedValidationSummary(toolName, payload);
377
+ if (summary === null) return null;
378
+ const toolCallId = stringFromFirst(payload, ["toolCallId", "tool_call_id", "id"]) ?? turnIdOf(entry);
379
+ if (toolCallId === null) return null;
380
+ const candidate: ToolCallEvidenceCandidate = {
381
+ toolCallId,
382
+ command: summary,
383
+ };
384
+ const turnId = turnIdOf(entry);
385
+ if (turnId !== null) candidate.turnId = turnId;
386
+ return candidate;
387
+ }
388
+
389
+ /**
390
+ * The canonical command a typed validation tool call stands for, or null when
391
+ * the call is not a validation. Exported because run-effects grounds a mutation
392
+ * report's claimed validations against the same notion this gate uses.
393
+ */
394
+ export function typedValidationSummary(toolName: string, payload: Record<string, unknown>): string | null {
395
+ const args = asRecord(payload.args ?? payload.arguments ?? payload.input);
396
+ if (toolName === "verify") {
397
+ const check = typeof args?.check === "string" ? args.check.trim() : "";
398
+ if (check === "frontend") {
399
+ const path = typeof args?.path === "string" && args.path.trim().length > 0 ? args.path.trim() : "artifact";
400
+ return `verify frontend ${path}`;
401
+ }
402
+ if (!isVerificationScriptName(check)) return null;
403
+ return `npm run ${check}`;
404
+ }
405
+ return null;
406
+ }
407
+
408
+ function successfulToolResultId(entry: unknown): string | null {
409
+ const record = asRecord(entry);
410
+ if (record?.kind !== "message" || record.role !== "tool_result") return null;
411
+ const payload = asRecord(record.payload);
412
+ if (payload === null) return null;
413
+ if (payload.isError === true || payload.error === true) return null;
414
+ const result = asRecord(payload.result);
415
+ const details = asRecord(result?.details);
416
+ if (details?.kind === "error") return null;
417
+ return stringFromFirst(payload, ["toolCallId", "tool_call_id", "id"]);
418
+ }
419
+
420
+ function dispatchReceiptEvidence(
421
+ entry: unknown,
422
+ candidate: ToolCallEvidenceCandidate | undefined,
423
+ ): FinishContractEvidence | null {
424
+ const record = asRecord(entry);
425
+ if (record?.kind !== "message" || record.role !== "tool_result") return null;
426
+ const payload = asRecord(record.payload);
427
+ if (payload === null) return null;
428
+ const toolName = stringFromFirst(payload, ["toolName", "name", "tool"]);
429
+ if (toolName !== null && toolName !== "dispatch") return null;
430
+ const result = asRecord(payload.result);
431
+ const details = asRecord(result?.details);
432
+ if (details === null) return null;
433
+ const summary = passedDispatchReceiptSummary(details, candidate);
434
+ if (summary === null) return null;
435
+ const evidence: FinishContractEvidence = {
436
+ kind: "dispatch_receipt",
437
+ summary,
438
+ };
439
+ const turnId = candidate?.turnId ?? turnIdOf(entry);
440
+ if (turnId !== null && turnId !== undefined) evidence.turnId = turnId;
441
+ return evidence;
442
+ }
443
+
444
+ /**
445
+ * Summarizes a dispatch result as passed-receipt evidence, or null when it is
446
+ * not a passing dispatch. Handles the toolkit v2 batch shape
447
+ * (`{mode, runIds, receiptCount, failedCount, runs:[{runId, agentId, exitCode}]}`
448
+ * where exit codes live per-run) as well as the legacy single-run shape
449
+ * (`{exitCode, runId, agentId}`). A batch counts only when it has at least one
450
+ * run and every run exited cleanly, so a partially-failed dispatch never poses
451
+ * as validation evidence.
452
+ */
453
+ function passedDispatchReceiptSummary(
454
+ details: Record<string, unknown>,
455
+ candidate: ToolCallEvidenceCandidate | undefined,
456
+ ): string | null {
457
+ if (Array.isArray(details.runs)) {
458
+ const runs = details.runs.map(asRecord);
459
+ if (runs.length === 0 || runs.some((run) => run === null || run.exitCode !== 0)) return null;
460
+ if (typeof details.failedCount === "number" && details.failedCount !== 0) return null;
461
+ const first = runs[0];
462
+ const runId = typeof first?.runId === "string" && first.runId.length > 0 ? first.runId : "unknown";
463
+ const agentId = dispatchReceiptAgentId(typeof first?.agentId === "string" ? first.agentId : undefined, candidate);
464
+ const extra = runs.length > 1 ? ` (+${runs.length - 1} more)` : "";
465
+ return `dispatch receipt passed: run ${runId} agent ${agentId}${extra}`;
466
+ }
467
+ if (details.exitCode === 0) {
468
+ const runId = typeof details.runId === "string" && details.runId.length > 0 ? details.runId : "unknown";
469
+ const agentId = dispatchReceiptAgentId(typeof details.agentId === "string" ? details.agentId : undefined, candidate);
470
+ return `dispatch receipt passed: run ${runId} agent ${agentId}`;
471
+ }
472
+ return null;
473
+ }
474
+
475
+ /** Prefer the receipt's own agent id, then the dispatch call's, then unknown. */
476
+ function dispatchReceiptAgentId(
477
+ receiptAgentId: string | undefined,
478
+ candidate: ToolCallEvidenceCandidate | undefined,
479
+ ): string {
480
+ if (receiptAgentId !== undefined && receiptAgentId.length > 0) return receiptAgentId;
481
+ return candidate?.command.match(/^agent=([^\s]+)/)?.[1] ?? "unknown";
482
+ }
483
+
484
+ function bashExecutionEvidence(entry: unknown): FinishContractEvidence | null {
485
+ const record = asRecord(entry);
486
+ if (record?.kind !== "bashExecution") return null;
487
+ if (typeof record.command !== "string") return null;
488
+ if (record.cancelled === true) return null;
489
+ if (record.exitCode !== 0) return null;
490
+ const detected = detectValidationCommand(record.command);
491
+ if (detected.kind !== "validation") return null;
492
+ const evidence: FinishContractEvidence = {
493
+ kind: "validation_command",
494
+ summary: `validation command passed: ${detected.matched}`,
495
+ };
496
+ const turnId = turnIdOf(entry);
497
+ if (turnId !== null) evidence.turnId = turnId;
498
+ return evidence;
499
+ }
500
+
501
+ function protectedArtifactEvidence(entry: unknown): FinishContractEvidence | null {
502
+ const record = asRecord(entry);
503
+ if (record?.kind !== "protectedArtifact" || record.action !== "protect") return null;
504
+ const artifact = asRecord(record.artifact);
505
+ const path = typeof artifact?.path === "string" && artifact.path.trim().length > 0 ? artifact.path.trim() : null;
506
+ if (path === null) return null;
507
+ const evidence: FinishContractEvidence = {
508
+ kind: "protected_artifact",
509
+ summary: `protected artifact recorded: ${path}`,
510
+ };
511
+ const turnId = turnIdOf(entry);
512
+ if (turnId !== null) evidence.turnId = turnId;
513
+ return evidence;
514
+ }
515
+
516
+ function validationEvidence(candidate: ToolCallEvidenceCandidate): FinishContractEvidence {
517
+ const evidence: FinishContractEvidence = {
518
+ kind: "validation_command",
519
+ summary: `validation command passed: ${candidate.command}`,
520
+ };
521
+ if (candidate.turnId !== undefined) evidence.turnId = candidate.turnId;
522
+ return evidence;
523
+ }
524
+
525
+ function pushEvidence(evidence: FinishContractEvidence[], seen: Set<string>, item: FinishContractEvidence): void {
526
+ const key = `${item.kind}\0${item.summary}\0${item.turnId ?? ""}`;
527
+ if (seen.has(key)) return;
528
+ seen.add(key);
529
+ evidence.push(item);
530
+ }
531
+
532
+ function isUserMessageEntry(entry: unknown): boolean {
533
+ const record = asRecord(entry);
534
+ if (record?.kind !== "message" || record.role !== "user") return false;
535
+ const payload = asRecord(record.payload);
536
+ return payload?.synthetic !== true;
537
+ }
538
+
539
+ function turnIdOf(entry: unknown): string | null {
540
+ const record = asRecord(entry);
541
+ return typeof record?.turnId === "string" ? record.turnId : null;
542
+ }
543
+
544
+ function stringFromFirst(record: Record<string, unknown>, keys: ReadonlyArray<string>): string | null {
545
+ for (const key of keys) {
546
+ const value = record[key];
547
+ if (typeof value === "string" && value.length > 0) return value;
548
+ }
549
+ return null;
550
+ }
551
+
552
+ function asRecord(value: unknown): Record<string, unknown> | null {
553
+ return value !== null && typeof value === "object" ? (value as Record<string, unknown>) : null;
554
+ }