@iowarp/clio-coder 0.4.3 → 0.4.4

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 (340) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +1 -1
  3. package/dist/{acp-H2NGRPWO.js → acp-WNAYYF4F.js} +4 -5
  4. package/dist/{agents-TL5LLUQP.js → agents-3OKXHLOI.js} +33 -31
  5. package/dist/assets/codewiki.json +1 -1
  6. package/dist/{auth-E5SW4HMS.js → auth-VKNNMGPU.js} +10 -11
  7. package/dist/{builtins-IA7V7FUC.js → builtins-WGALA46I.js} +4 -4
  8. package/dist/{chunk-F5JHEYZM.js → chunk-23L32XTI.js} +10 -7
  9. package/dist/{chunk-DWUOQKRU.js → chunk-25QBEXRS.js} +2 -2
  10. package/dist/{chunk-LLDJM5XK.js → chunk-26QSH3EJ.js} +2 -2
  11. package/dist/{chunk-N2Z7HLVY.js → chunk-2ASED4PZ.js} +10 -10
  12. package/dist/{chunk-MCEPRMZW.js → chunk-2CU2H6KE.js} +2 -2
  13. package/dist/chunk-2DSOYNFC.js +108 -0
  14. package/dist/{chunk-LDJG7DW3.js → chunk-2ZSONWVL.js} +4 -4
  15. package/dist/{chunk-GI7YYQ3F.js → chunk-36CT5VVL.js} +324 -41
  16. package/dist/{chunk-4UVU7BJ5.js → chunk-3GY4F45V.js} +2 -2
  17. package/dist/{chunk-PUVDKJ2Y.js → chunk-3ODX73FK.js} +3 -5
  18. package/dist/{chunk-IUE3Y34X.js → chunk-3UNOLWNZ.js} +2 -2
  19. package/dist/{chunk-6PTFB5VS.js → chunk-3UUXNFEX.js} +8 -4
  20. package/dist/{chunk-2APPQIER.js → chunk-4M6Z5QVF.js} +4 -4
  21. package/dist/{chunk-K6BSR66V.js → chunk-4NSRCOYP.js} +4 -1
  22. package/dist/{chunk-JGRC33J2.js → chunk-54X7T7DK.js} +12 -3
  23. package/dist/{chunk-YQWYVTMC.js → chunk-5636DCO5.js} +4 -4
  24. package/dist/{chunk-7E7I3WLS.js → chunk-57XXR6DR.js} +23 -22
  25. package/dist/{chunk-7ZYNNDKC.js → chunk-5TUB6SLS.js} +2 -2
  26. package/dist/{chunk-VW6DOEDG.js → chunk-6OSVSQL5.js} +11 -2
  27. package/dist/{chunk-L47TF46W.js → chunk-6PAZTBPA.js} +14 -2
  28. package/dist/{chunk-XIVNBFZS.js → chunk-6Q3CYFD3.js} +34 -16
  29. package/dist/{chunk-RSJ25QSL.js → chunk-6QOTUPRG.js} +155 -36
  30. package/dist/{chunk-JKKCYP3C.js → chunk-6UINWWS6.js} +10 -4
  31. package/dist/{chunk-WBKFA554.js → chunk-72YIHOZQ.js} +2 -2
  32. package/dist/{chunk-PAJQJ7BS.js → chunk-75W7L2E2.js} +246 -697
  33. package/dist/{chunk-RRNP2ANY.js → chunk-7UGL4MB5.js} +4 -4
  34. package/dist/{chunk-EKCHAPYA.js → chunk-AUPNRN7C.js} +2 -2
  35. package/dist/{chunk-ZDN3Y73Y.js → chunk-BJVFZO5U.js} +6 -48
  36. package/dist/{chunk-IWT4SF4R.js → chunk-CUSRQKPU.js} +64 -2
  37. package/dist/{chunk-SKHCAU7K.js → chunk-DQOVN6KV.js} +3 -2
  38. package/dist/{chunk-ZWPRK62N.js → chunk-DT3LWJOB.js} +4 -4
  39. package/dist/chunk-DXKJURES.js +671 -0
  40. package/dist/{chunk-BEPZRGGU.js → chunk-EL24TAU4.js} +2 -2
  41. package/dist/{chunk-OML5D5V5.js → chunk-ELWDPP3Y.js} +5 -5
  42. package/dist/{chunk-NDINPTJ4.js → chunk-ELZVTCGV.js} +5 -4
  43. package/dist/chunk-EXLD33WO.js +381 -0
  44. package/dist/{chunk-IJNZMHLA.js → chunk-FEAXX7B6.js} +2 -2
  45. package/dist/{chunk-TM6LQDI3.js → chunk-FFUPXJC4.js} +74 -323
  46. package/dist/chunk-GX5WYQO4.js +59 -0
  47. package/dist/chunk-I2DWJ4GM.js +390 -0
  48. package/dist/{chunk-TXOTCRLG.js → chunk-I5FWO7L5.js} +5 -5
  49. package/dist/chunk-IRXAATOX.js +539 -0
  50. package/dist/chunk-IXIY2H4R.js +44 -0
  51. package/dist/{chunk-KK4JZPBQ.js → chunk-IZXGRF7P.js} +76 -10
  52. package/dist/{chunk-5TSRNF4G.js → chunk-JCI2ROMZ.js} +164 -6
  53. package/dist/{chunk-INY6HTFL.js → chunk-JEIYHLOR.js} +2 -2
  54. package/dist/{chunk-MUW2BDDH.js → chunk-JQLNNIKT.js} +2 -2
  55. package/dist/{chunk-XPWWI35G.js → chunk-JSD46VO2.js} +19 -8
  56. package/dist/{chunk-VA5FNYMT.js → chunk-JT2RFCC5.js} +39 -2
  57. package/dist/{chunk-V2ANDPVT.js → chunk-K6T2ZAMZ.js} +168 -6
  58. package/dist/{chunk-B4OAX3SI.js → chunk-KFV5L5SK.js} +13 -6
  59. package/dist/{chunk-JEQ3XTHC.js → chunk-LLXSDWXS.js} +2 -2
  60. package/dist/{chunk-E3TPLWFX.js → chunk-LTIKRKFL.js} +3 -3
  61. package/dist/{chunk-NIQJ66N4.js → chunk-N56KALIC.js} +17 -17
  62. package/dist/{chunk-JDAY6FIL.js → chunk-NAI6ZFCY.js} +13 -9
  63. package/dist/{chunk-AF4YM7Z4.js → chunk-NRO2BJRH.js} +2490 -2182
  64. package/dist/{chunk-WRBAGUNF.js → chunk-NXIMQY5W.js} +2 -2
  65. package/dist/{chunk-I7ZPNEJM.js → chunk-NXYCB2VD.js} +5 -5
  66. package/dist/chunk-ODGTEFFI.js +50 -0
  67. package/dist/{chunk-2VIKGWFZ.js → chunk-OEJSLEPW.js} +2 -2
  68. package/dist/{chunk-KKOJXO6R.js → chunk-OMQNJVKW.js} +4 -2
  69. package/dist/{chunk-54CBCGIR.js → chunk-Q4WO54TA.js} +132 -77
  70. package/dist/{chunk-B4VEBZKF.js → chunk-QUFRYSWI.js} +12 -6
  71. package/dist/{chunk-42FMPA75.js → chunk-QZWQA4DE.js} +2 -2
  72. package/dist/{chunk-HEQY7ZFI.js → chunk-RAY4OVGZ.js} +2 -2
  73. package/dist/{chunk-G76U63X4.js → chunk-RQCKCSRL.js} +7 -7
  74. package/dist/{chunk-64I3JVYM.js → chunk-RXTN6AKH.js} +2 -2
  75. package/dist/{chunk-UPZU6GE4.js → chunk-RZDWV63N.js} +3 -3
  76. package/dist/{chunk-2UH2KFUP.js → chunk-S6PYF2XF.js} +2 -2
  77. package/dist/{chunk-JSC3U7TI.js → chunk-TOIVGRUX.js} +2 -2
  78. package/dist/{chunk-7DRAWPTZ.js → chunk-TQAHXW6Y.js} +1 -1
  79. package/dist/{chunk-JIEGK6UF.js → chunk-U6TMQNSI.js} +48 -4
  80. package/dist/{chunk-AX2THNSA.js → chunk-UEPWCCTY.js} +4 -4
  81. package/dist/{chunk-QWGDJJYJ.js → chunk-USR47QNF.js} +4 -4
  82. package/dist/{chunk-Y3CBHOR6.js → chunk-V6HJFQZE.js} +2 -2
  83. package/dist/chunk-V76WTFTW.js +318 -0
  84. package/dist/{chunk-NMJXSHBJ.js → chunk-W54I7H25.js} +2 -2
  85. package/dist/{chunk-2UG5F4C5.js → chunk-XULDXHTN.js} +24 -12
  86. package/dist/chunk-XXYSBZIQ.js +283 -0
  87. package/dist/{chunk-MWUZBSAQ.js → chunk-Y55JBDO5.js} +331 -51
  88. package/dist/{chunk-W6RRQCPQ.js → chunk-YD5GIKET.js} +4 -4
  89. package/dist/{chunk-CE5AX47J.js → chunk-YECAMM3D.js} +2 -2
  90. package/dist/{chunk-WCXUNS7U.js → chunk-YNFKXPEC.js} +6 -6
  91. package/dist/cli/index.js +36 -35
  92. package/dist/{clio-CMMK4KRR.js → clio-QLICPCF5.js} +2 -2
  93. package/dist/{code-nav-MDZNQS33.js → code-nav-IJR2DBPR.js} +6 -6
  94. package/dist/{components-UCUQ4QXW.js → components-2TGAI2RC.js} +3 -4
  95. package/dist/{config-SVM5P5YI.js → config-IUA6OYNS.js} +52 -47
  96. package/dist/{configure-LE3IK2TJ.js → configure-VEPX4NMX.js} +14 -15
  97. package/dist/{context-VNCR7KAG.js → context-2DKHWH2T.js} +23 -23
  98. package/dist/{context-2OHRKS42.js → context-4MPR7WKB.js} +48 -42
  99. package/dist/{context-E3VC7RX5.js → context-BOYF5EJM.js} +11 -11
  100. package/dist/{context-clear-BW4O37TG.js → context-clear-S4ZJCQUX.js} +48 -42
  101. package/dist/{context-working-set-VDS25HXZ.js → context-working-set-3I3FYX6Y.js} +8 -8
  102. package/dist/detail-A7JAVSIG.js +98 -0
  103. package/dist/{dispatch-runner-5AHT53RF.js → dispatch-runner-RJ5I2F2O.js} +71 -58
  104. package/dist/{docs-PD3EXDKU.js → docs-SPOV3BAN.js} +3 -5
  105. package/dist/{doctor-WNNVO6FY.js → doctor-DKICC2SN.js} +54 -31
  106. package/dist/{eval-7G7SGAYO.js → eval-OQOQUDHK.js} +47 -56
  107. package/dist/{evidence-VD6736FQ.js → evidence-4DQ25GUQ.js} +53 -150
  108. package/dist/evidence-4F5USFKH.js +208 -0
  109. package/dist/{evolve-AL3NGVRL.js → evolve-GSS52E5J.js} +44 -41
  110. package/dist/{extensions-MOVJ32NM.js → extensions-G7MFLYHT.js} +4 -5
  111. package/dist/{fleet-QZHUMAGI.js → fleet-Q37YHHAQ.js} +74 -68
  112. package/dist/{fleet-commands-BAYT5FJZ.js → fleet-commands-G7E4N7SM.js} +14 -11
  113. package/dist/{fleet-decisions-IREVMRU4.js → fleet-decisions-O7M6QBA2.js} +6 -6
  114. package/dist/{fleet-graph-YCTT3HTI.js → fleet-graph-TOUBW6OW.js} +13 -13
  115. package/dist/{fleet-inspect-QVJTDAVB.js → fleet-inspect-SW33JJNI.js} +43 -39
  116. package/dist/{fleet-preflight-25QAFPK4.js → fleet-preflight-CV2655TW.js} +2 -3
  117. package/dist/{fleet-validate-5O57AAJ7.js → fleet-validate-KESZX2YH.js} +16 -16
  118. package/dist/{fleet-verify-CPH2W2T6.js → fleet-verify-UQPMTVE3.js} +42 -38
  119. package/dist/{fleet-view-SWBR3VGQ.js → fleet-view-MN2VG4MR.js} +43 -39
  120. package/dist/{init-J477LKZH.js → init-PXEXQSBF.js} +60 -54
  121. package/dist/{interop-3FCM6XLG.js → interop-ZG5T62U3.js} +6 -7
  122. package/dist/inventory-C26CFDRR.js +101 -0
  123. package/dist/{library-QUQEIUG6.js → library-B2W4N74O.js} +16 -17
  124. package/dist/{memory-SGGSEP65.js → memory-YCANYS5A.js} +45 -42
  125. package/dist/{models-HEKUAXXK.js → models-GERTU3YI.js} +20 -22
  126. package/dist/{monitor-HKU57TYQ.js → monitor-CPNIUULB.js} +50 -44
  127. package/dist/{orchestrator-VDFAEFAI.js → orchestrator-J4BSH4WQ.js} +491 -1182
  128. package/dist/{panes-DN2SSFOH.js → panes-BOHAEGYC.js} +3 -3
  129. package/dist/{panes-TALGNPZT.js → panes-NXSLDQZ2.js} +5 -6
  130. package/dist/{paths-NBMFAIEZ.js → paths-VSUWNC22.js} +3 -4
  131. package/dist/{reset-EAJFFJVB.js → reset-TNWTB5LU.js} +5 -6
  132. package/dist/{resources-OVKSEFVE.js → resources-4PXNMD5G.js} +14 -14
  133. package/dist/{run-7DP7ZF2J.js → run-D6XJ34CN.js} +79 -83
  134. package/dist/{share-WML67FT3.js → share-2NWMJJEE.js} +14 -15
  135. package/dist/{skills-SG662R2K.js → skills-KR7WON5G.js} +18 -19
  136. package/dist/{skills-eval-VVZEUU46.js → skills-eval-O2ZNOLDS.js} +49 -46
  137. package/dist/{skills-inventory-I2E23GET.js → skills-inventory-ZZOUBK7O.js} +14 -14
  138. package/dist/{slash-commands-S7MBJDQK.js → slash-commands-ZXPJD64J.js} +32 -23
  139. package/dist/{steer-2LQOMCPB.js → steer-XA25PSCS.js} +3 -3
  140. package/dist/{support-CC2UJBJ6.js → support-7EMVWYG2.js} +2 -2
  141. package/dist/{targets-4QC3HIEW.js → targets-OMH2XCSN.js} +25 -27
  142. package/dist/tasks-IPAGMEIX.js +36 -0
  143. package/dist/{terminal-lease-TUHIJ6Y2.js → terminal-lease-C2J3JYRE.js} +4 -4
  144. package/dist/{tools-TFGJICCU.js → tools-EFFEAIDP.js} +5 -6
  145. package/dist/{uninstall-5PEVOE5B.js → uninstall-HALS6BLF.js} +7 -8
  146. package/dist/{upgrade-M4WXY6KN.js → upgrade-MS72RJEP.js} +14 -11
  147. package/dist/{usage-N7ZNVLEM.js → usage-NHG6MCJM.js} +60 -51
  148. package/dist/{verifiers-DJTP4XX6.js → verifiers-7AUNVXDY.js} +150 -17
  149. package/dist/{verify-RWE4PPEK.js → verify-FWYGPKMR.js} +12 -10
  150. package/dist/{web-fetch-MPARV2K7.js → web-fetch-V4FKSDAV.js} +4 -4
  151. package/dist/{wiki-generate-C7IQOXSP.js → wiki-generate-743CIGJW.js} +63 -56
  152. package/dist/{with-panes-4GCGSL7J.js → with-panes-BDQEWBRT.js} +2 -2
  153. package/dist/worker/entry.js +36 -33
  154. package/docs/README.md +3 -2
  155. package/docs/architecture/acp.md +17 -0
  156. package/docs/architecture/artifact-versions.md +1 -1
  157. package/docs/architecture/dispatch-typed-intent.md +1 -1
  158. package/docs/architecture/evidence-and-memory.md +1 -1
  159. package/docs/architecture/observability.md +7 -1
  160. package/docs/architecture/prompt-envelope-and-tools.md +15 -5
  161. package/docs/architecture/safety-model.md +10 -17
  162. package/docs/architecture/tui-design.md +1 -1
  163. package/docs/guide/built-in-agents.md +8 -8
  164. package/docs/guide/commands-and-modes.md +17 -2
  165. package/docs/guide/configuration-and-targets.md +3 -1
  166. package/docs/guide/configuration-reference.md +10 -5
  167. package/docs/guide/environment-variables.md +2 -2
  168. package/docs/guide/tool-usage.md +78 -3
  169. package/docs/history/config-knobs-audit.md +2 -2
  170. package/docs/process/development-pipeline.md +6 -1
  171. package/docs/process/git-commit-provenance.md +15 -0
  172. package/docs/process/release-cut-checklist.md +207 -0
  173. package/docs/process/scientific-validation.md +18 -17
  174. package/evals/behavioral-machinery-support.ts +1 -0
  175. package/evals/behavioral-machinery.yaml +1 -1
  176. package/package.json +1 -1
  177. package/skills/coding/coding-standards/SKILL.md +14 -4
  178. package/skills/context/context-handoff/SKILL.md +3 -3
  179. package/skills/context/context-prime/SKILL.md +3 -3
  180. package/skills/planning/architecture/SKILL.md +5 -5
  181. package/skills/planning/backlog/SKILL.md +4 -4
  182. package/skills/planning/prd/SKILL.md +4 -3
  183. package/skills/planning/product-intent/SKILL.md +8 -8
  184. package/skills/planning/tech-spec/SKILL.md +4 -4
  185. package/skills/registry.yaml +32 -32
  186. package/skills/research/arxiv-literature/SKILL.md +3 -3
  187. package/skills/research/experiment-protocol/SKILL.md +3 -3
  188. package/skills/research/scientific-debugging/SKILL.md +3 -2
  189. package/skills/research/scientific-modernization/SKILL.md +3 -3
  190. package/skills/skill-marketplace.json +16 -16
  191. package/skills/workflow/cut-it/SKILL.md +3 -4
  192. package/skills/workflow/design-council/SKILL.md +5 -10
  193. package/skills/workflow/grill-me/SKILL.md +14 -15
  194. package/skills/workflow/workflow-distiller/SKILL.md +4 -4
  195. package/src/cli/args.ts +0 -8
  196. package/src/cli/configure.ts +2 -1
  197. package/src/cli/doctor-state-size.ts +1 -12
  198. package/src/cli/doctor-validation-contract.ts +28 -0
  199. package/src/cli/doctor.ts +5 -0
  200. package/src/cli/evidence-detail.ts +1 -75
  201. package/src/cli/evidence-inventory.ts +1 -167
  202. package/src/cli/index.ts +2 -0
  203. package/src/cli/run.ts +0 -2
  204. package/src/cli/targets.ts +1 -1
  205. package/src/cli/tasks.ts +84 -0
  206. package/src/cli/upgrade.ts +10 -5
  207. package/src/cli/usage.ts +6 -0
  208. package/src/cli/verifiers.ts +147 -1
  209. package/src/cli/wiki-generate.ts +1 -0
  210. package/src/core/commit-attribution.ts +41 -1
  211. package/src/core/git-commit-attribution.ts +46 -3
  212. package/src/core/run-overrides.ts +0 -5
  213. package/src/core/skill-activation.ts +3 -0
  214. package/src/core/tool-names.ts +5 -2
  215. package/src/domains/agents/builtins/architect.md +1 -1
  216. package/src/domains/agents/builtins/coder.md +1 -1
  217. package/src/domains/agents/builtins/documenter.md +1 -1
  218. package/src/domains/agents/builtins/git-master.md +1 -1
  219. package/src/domains/agents/builtins/provenance.md +7 -7
  220. package/src/domains/agents/builtins/tester.md +1 -1
  221. package/src/domains/agents/builtins/verifier.md +2 -2
  222. package/src/domains/agents/builtins/wiki-writer.md +4 -3
  223. package/src/domains/context/extension.ts +31 -7
  224. package/src/domains/context/refresh.ts +3 -0
  225. package/src/domains/context/wiki/frontmatter.ts +5 -2
  226. package/src/domains/context/wiki/generate.ts +6 -0
  227. package/src/domains/context/wiki/prompts.ts +43 -0
  228. package/src/domains/dispatch/active-route-planner.ts +4 -0
  229. package/src/domains/dispatch/code-step.ts +11 -4
  230. package/src/domains/dispatch/contract.ts +31 -7
  231. package/src/domains/dispatch/execution-scheduler.ts +2 -0
  232. package/src/domains/dispatch/extension.ts +50 -27
  233. package/src/domains/dispatch/fleet-commit-attribution.ts +5 -0
  234. package/src/domains/dispatch/fleet-run.ts +1 -0
  235. package/src/domains/dispatch/host-verification.ts +114 -13
  236. package/src/domains/dispatch/intent.ts +28 -18
  237. package/src/domains/dispatch/orphan-recovery.ts +2 -0
  238. package/src/domains/dispatch/receipt-integrity.ts +4 -0
  239. package/src/domains/dispatch/reservation-store.ts +5 -3
  240. package/src/domains/dispatch/state.ts +15 -2
  241. package/src/domains/dispatch/types.ts +17 -2
  242. package/src/domains/eval/runners/clio-run.ts +12 -9
  243. package/src/domains/eval/runners/context-index.ts +2 -7
  244. package/src/domains/eval/runners/context-init.ts +3 -6
  245. package/src/domains/eval/runners/external-command.ts +29 -11
  246. package/src/domains/evidence/build.ts +102 -15
  247. package/src/domains/evidence/detail.ts +69 -0
  248. package/src/domains/evidence/eval.ts +13 -1
  249. package/src/domains/evidence/finish-contract-map.ts +5 -1
  250. package/src/domains/evidence/inventory.ts +167 -0
  251. package/src/domains/evidence/store.ts +16 -0
  252. package/src/domains/evidence/types.ts +12 -0
  253. package/src/domains/extensions/resources.ts +7 -0
  254. package/src/domains/middleware/marketplace-offer.ts +20 -1
  255. package/src/domains/middleware/runtime.ts +7 -3
  256. package/src/domains/mux/detect.ts +3 -6
  257. package/src/domains/observability/accountability.ts +15 -1
  258. package/src/domains/observability/contract.ts +52 -7
  259. package/src/domains/observability/evidence-index.ts +10 -0
  260. package/src/domains/observability/extension.ts +9 -5
  261. package/src/domains/observability/projection.ts +394 -45
  262. package/src/{interactive → domains/observability}/worker-progress.ts +3 -3
  263. package/src/domains/prompts/fragments/operating/contract.md +2 -0
  264. package/src/domains/prompts/fragments/wiki/page.md +8 -0
  265. package/src/domains/providers/model-discovery.ts +1 -4
  266. package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +16 -14
  267. package/src/domains/providers/runtimes/claude/claude-code.ts +9 -0
  268. package/src/domains/providers/support.ts +1 -1
  269. package/src/domains/providers/types/runtime-descriptor.ts +1 -1
  270. package/src/domains/safety/action-classifier.ts +7 -0
  271. package/src/domains/safety/default-path-policy.ts +2 -0
  272. package/src/domains/safety/finish-contract-registration.ts +29 -14
  273. package/src/domains/safety/finish-contract.ts +252 -40
  274. package/src/domains/safety/index.ts +20 -1
  275. package/src/domains/safety/policy-engine.ts +26 -6
  276. package/src/domains/safety/rigor.ts +53 -39
  277. package/src/domains/safety/validation-contract.ts +388 -0
  278. package/src/domains/session/archive-readers.ts +10 -1
  279. package/src/domains/session/decision-board.ts +101 -2
  280. package/src/domains/session/entries.ts +44 -7
  281. package/src/domains/session/extension.ts +4 -4
  282. package/src/domains/session/handoff.ts +2 -1
  283. package/src/domains/session/manager.ts +2 -3
  284. package/src/domains/session/task-board.ts +14 -1
  285. package/src/domains/session/tree/fork.ts +1 -2
  286. package/src/domains/session/tree/navigator.ts +1 -1
  287. package/src/domains/user-tasks/acceptance.ts +56 -0
  288. package/src/domains/user-tasks/active-acceptance.ts +40 -0
  289. package/src/domains/user-tasks/store.ts +34 -3
  290. package/src/engine/acp/adapter.ts +24 -6
  291. package/src/engine/acp/server.ts +21 -4
  292. package/src/engine/acp/transport.ts +53 -8
  293. package/src/engine/acp/types.ts +4 -0
  294. package/src/engine/apis/ollama-native.ts +15 -0
  295. package/src/engine/claude/subprocess-runtime.ts +107 -60
  296. package/src/engine/external-subprocess.ts +12 -4
  297. package/src/entry/orchestrator.ts +11 -2
  298. package/src/interactive/dispatch-board.ts +46 -717
  299. package/src/interactive/fleet-run-preview.ts +2 -1
  300. package/src/interactive/interactive-application.ts +3 -2
  301. package/src/interactive/interactive-presentation.ts +55 -12
  302. package/src/interactive/interactive-slash-runtime.ts +2 -1
  303. package/src/interactive/oracle.ts +5 -2
  304. package/src/interactive/overlays/fleet-run-approval.ts +3 -2
  305. package/src/interactive/overlays/message-picker.ts +2 -2
  306. package/src/interactive/overlays/settings.ts +2 -2
  307. package/src/interactive/overlays/tree-selector.ts +2 -2
  308. package/src/interactive/renderers/branch-summary.ts +1 -1
  309. package/src/interactive/slash-autocomplete.ts +4 -6
  310. package/src/interactive/slash-commands.ts +25 -39
  311. package/src/interactive/slash-spec.ts +28 -0
  312. package/src/interactive/view/artifacts.ts +2 -0
  313. package/src/interactive/worker-stream.ts +7 -3
  314. package/src/tools/bootstrap.ts +4 -0
  315. package/src/tools/builtin-tool-catalog.ts +31 -0
  316. package/src/tools/compete-worktrees.ts +7 -1
  317. package/src/tools/core-bootstrap.ts +16 -0
  318. package/src/tools/decide.ts +136 -0
  319. package/src/tools/dispatch-admission.ts +21 -0
  320. package/src/tools/dispatch-plan.ts +5 -2
  321. package/src/tools/dispatch-runner.ts +15 -1
  322. package/src/tools/dispatch-types.ts +6 -0
  323. package/src/tools/evidence.ts +96 -0
  324. package/src/tools/limitation.ts +76 -0
  325. package/src/tools/policy.ts +9 -0
  326. package/src/tools/presentation.ts +3 -0
  327. package/src/tools/registry.ts +1 -1
  328. package/src/tools/result-shaping.ts +17 -5
  329. package/src/tools/task-worktree.ts +13 -3
  330. package/src/tools/tasks.ts +10 -1
  331. package/src/tools/verify/authoring.ts +170 -83
  332. package/src/tools/verify/catalog.ts +122 -5
  333. package/src/tools/verify/index.ts +2 -1
  334. package/src/tools/verify/numeric.ts +298 -0
  335. package/src/tools/verify/perf.ts +143 -0
  336. package/src/tools/verify/scripts.ts +229 -2
  337. package/dist/chunk-7DICMOS6.js +0 -313
  338. package/dist/chunk-RVG5JXAL.js +0 -41
  339. package/dist/chunk-T56WDKA5.js +0 -183
  340. package/dist/chunk-VPKWYKEY.js +0 -169
@@ -35,6 +35,8 @@ export interface WikiPageMetadata {
35
35
  invariants: string[];
36
36
  /** Narrowest non-destructive commands that check this area. */
37
37
  validate: string[];
38
+ /** Stable refs for recorded decisions cited in the body. */
39
+ decisions?: string[];
38
40
  }
39
41
 
40
42
  export interface WikiPageDocument {
@@ -47,7 +49,7 @@ export interface WikiPageDocument {
47
49
 
48
50
  const FRONTMATTER_BLOCK = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/;
49
51
 
50
- const LIST_FIELDS = ["sources", "symbols", "tests", "invariants", "validate"] as const;
52
+ const LIST_FIELDS = ["sources", "symbols", "tests", "invariants", "validate", "decisions"] as const;
51
53
 
52
54
  /** Longest generated summary, so an index line stays one line. */
53
55
  const SUMMARY_MAX_CHARS = 240;
@@ -166,6 +168,7 @@ export function readWikiPage(input: ReadWikiPageInput): WikiPageDocument {
166
168
  tests: [],
167
169
  invariants: stringList(authored.invariants),
168
170
  validate: stringList(authored.validate),
171
+ ...(authored.decisions === undefined ? {} : { decisions: stringList(authored.decisions) }),
169
172
  };
170
173
  const unresolvedPaths: string[] = [];
171
174
  for (const field of ["sources", "tests"] as const) {
@@ -189,7 +192,7 @@ function renderList(name: string, values: ReadonlyArray<string>): string[] {
189
192
  function renderFrontmatter(metadata: WikiPageMetadata): string {
190
193
  const lines = [`title: ${JSON.stringify(metadata.title)}`];
191
194
  if (metadata.summary.length > 0) lines.push(`summary: ${JSON.stringify(metadata.summary)}`);
192
- for (const field of LIST_FIELDS) lines.push(...renderList(field, metadata[field]));
195
+ for (const field of LIST_FIELDS) lines.push(...renderList(field, metadata[field] ?? []));
193
196
  return `---\n${lines.join("\n")}\n---\n`;
194
197
  }
195
198
 
@@ -14,6 +14,7 @@ import {
14
14
  } from "node:fs";
15
15
  import { dirname, join } from "node:path";
16
16
  import type { ContextActivityPayload } from "../../../core/bus-events.js";
17
+ import type { DecisionLedgerEntry } from "../../session/entries.js";
17
18
  import { detectProjectType } from "../../session/workspace/project-type.js";
18
19
  import type { BootstrapProgressSink } from "../bootstrap.js";
19
20
  import { coordinateCodewikiWrite } from "../codewiki/coordinator.js";
@@ -44,6 +45,8 @@ import { changedPathsSince } from "./staleness.js";
44
45
  export type { WikiDepth, WikiGenerateMode };
45
46
 
46
47
  export interface WikiGenerateInput {
48
+ /** The current session board, already scoped to its active branch. */
49
+ decisions?: ReadonlyArray<DecisionLedgerEntry>;
47
50
  cwd: string;
48
51
  mode: WikiGenerateMode;
49
52
  /**
@@ -76,6 +79,8 @@ export interface WikiGenerateInput {
76
79
  export type WikiGenerate = (input: WikiGenerateInput) => void | Promise<void>;
77
80
 
78
81
  export interface RunWikiGenerateInput {
82
+ /** The current session board, already scoped to its active branch. */
83
+ decisions?: ReadonlyArray<DecisionLedgerEntry>;
79
84
  cwd?: string;
80
85
  mode?: WikiGenerateMode;
81
86
  /** Repository-detail policy. Auto scales decomposition from indexed files and lines. */
@@ -473,6 +478,7 @@ export async function runWikiGenerate(
473
478
  plan: resolved.plan,
474
479
  resumed: resolved.resumed,
475
480
  unclaimedAreas: resolved.unclaimedAreas,
481
+ ...(input.decisions ? { decisions: input.decisions } : {}),
476
482
  gitHead: existingMeta?.gitHead ?? null,
477
483
  ...(input.onProgress ? { progress: input.onProgress } : {}),
478
484
  });
@@ -14,6 +14,7 @@ import { execFileSync } from "node:child_process";
14
14
  import { existsSync, realpathSync, statSync } from "node:fs";
15
15
  import { isAbsolute, join, relative } from "node:path";
16
16
  import { loadFragments } from "../../prompts/fragment-loader.js";
17
+ import { type DecisionLedgerEntry, decisionRef } from "../../session/entries.js";
17
18
  import { renderCodewikiDigest } from "../codewiki/digest.js";
18
19
  import type { Codewiki } from "../codewiki/schema.js";
19
20
  import { WIKI_PLAN_FILE } from "./layout.js";
@@ -229,6 +230,8 @@ function scopedSymbols(codewiki: Codewiki, sources: ReadonlyArray<string>, limit
229
230
  }
230
231
 
231
232
  export interface BuildWikiPagePromptInput {
233
+ /** The current session board, already scoped to its active branch. */
234
+ decisions?: ReadonlyArray<DecisionLedgerEntry>;
232
235
  cwd: string;
233
236
  mode: WikiGenerateMode;
234
237
  codewiki: Codewiki;
@@ -272,6 +275,8 @@ export function buildWikiPagePrompt(input: BuildWikiPagePromptInput): string {
272
275
  "## Repository guidance",
273
276
  repositoryGuidance(input.cwd),
274
277
  ];
278
+ const decisions = recordedDecisions(input);
279
+ if (decisions.length > 0) sections.push("# Recorded decisions", "```json", JSON.stringify(decisions, null, 2), "```");
275
280
  if (input.seeded) {
276
281
  sections.push(
277
282
  "## Revision",
@@ -281,3 +286,41 @@ export function buildWikiPagePrompt(input: BuildWikiPagePromptInput): string {
281
286
  }
282
287
  return `${sections.join("\n\n")}\n`;
283
288
  }
289
+
290
+ /** Match a source itself or a descendant, without accepting similarly named siblings. */
291
+ function underSource(path: string, source: string): boolean {
292
+ const root = source.replace(/^\.\//, "").replace(/\/$/, "");
293
+ const candidate = path.replace(/^\.\//, "");
294
+ return candidate === root || candidate.startsWith(`${root}/`);
295
+ }
296
+
297
+ function recordedDecisions(input: BuildWikiPagePromptInput) {
298
+ const files = new Set(
299
+ input.codewiki.files
300
+ .filter((file) => input.page.sources.some((source) => underSource(file.path, source)))
301
+ .map((file) => file.id),
302
+ );
303
+ const symbols = new Set(
304
+ input.codewiki.symbols.filter((symbol) => files.has(symbol.fileId)).map((symbol) => symbol.name),
305
+ );
306
+ return (input.decisions ?? [])
307
+ .flatMap((entry) =>
308
+ entry.decisions
309
+ .filter((record) => {
310
+ if (record.status !== "active") return false;
311
+ if (symbols.has(record.key)) return true;
312
+ const paths = [record.rationale ?? "", ...(record.alternatives ?? [])].join(" ").match(/[\w@./-]+/g) ?? [];
313
+ return paths.some((path) => input.page.sources.some((source) => underSource(path.replace(/\.$/, ""), source)));
314
+ })
315
+ .map((record) => ({
316
+ ref: decisionRef(entry.interviewId, record.key),
317
+ key: record.key,
318
+ value: record.value,
319
+ alternatives: record.alternatives ?? [],
320
+ rationale: record.rationale ?? record.source_question ?? "",
321
+ decidedAt: record.decidedAt,
322
+ source: record.source ?? (entry.origin === "agent" ? "agent" : "operator"),
323
+ })),
324
+ )
325
+ .slice(0, 12);
326
+ }
@@ -37,6 +37,9 @@ export function routeValidationProjection(
37
37
  // Presentation-only parentage stamped by the calling tool, on the same
38
38
  // terms: a model must not be able to author it.
39
39
  parentToolCallId,
40
+ // Sealed from the parent decision board by the dispatch tool; a model
41
+ // must not be able to author which decisions a receipt claims.
42
+ decisionRefs,
40
43
  resolvedVerification,
41
44
  resultContractOverride,
42
45
  fleetGateReceipt,
@@ -60,6 +63,7 @@ export function routeValidationProjection(
60
63
  ...(assignmentDeadlineAt !== undefined ? { assignmentDeadlineAt } : {}),
61
64
  ...(ledger !== undefined ? { ledger } : {}),
62
65
  ...(parentToolCallId !== undefined ? { parentToolCallId } : {}),
66
+ ...(decisionRefs !== undefined ? { decisionRefs } : {}),
63
67
  ...(resolvedVerification !== undefined
64
68
  ? { resolvedVerification: resolvedVerification.map((check) => ({ ...check, argv: [...check.argv] })) }
65
69
  : {}),
@@ -107,6 +107,8 @@ export interface CodeStepRecord {
107
107
  export interface CodeStepOutcome {
108
108
  report: CodeReportResult;
109
109
  record: CodeStepRecord;
110
+ /** Stdout retained within the shared capture cap, for structured command judgments. */
111
+ stdout: string;
110
112
  /** Canonical JSON of the report; this is the text that crosses plan edges. */
111
113
  output: string;
112
114
  }
@@ -210,6 +212,7 @@ interface SpawnOutcome {
210
212
  signal: string | null;
211
213
  timedOut: boolean;
212
214
  captured: Buffer;
215
+ stdout: Buffer;
213
216
  outputBytes: number;
214
217
  spawnError: string | null;
215
218
  }
@@ -226,6 +229,7 @@ async function spawnCommand(input: CodeStepRunInput, cwd: string, argv: Readonly
226
229
  });
227
230
  reportCommitAttributionDiagnostic(attribution.diagnostic);
228
231
  const chunks: Buffer[] = [];
232
+ const stdoutChunks: Buffer[] = [];
229
233
  let outputBytes = 0;
230
234
  let captured = 0;
231
235
  let settled = false;
@@ -239,16 +243,17 @@ async function spawnCommand(input: CodeStepRunInput, cwd: string, argv: Readonly
239
243
  // whole tree rather than orphaning a test runner's children.
240
244
  detached: process.platform !== "win32",
241
245
  });
242
- const collect = (chunk: Buffer): void => {
246
+ const collect = (chunk: Buffer, stdout: boolean): void => {
243
247
  outputBytes += chunk.length;
244
248
  if (captured >= CODE_STEP_CAPTURE_MAX_BYTES) return;
245
249
  const room = CODE_STEP_CAPTURE_MAX_BYTES - captured;
246
250
  const slice = chunk.length <= room ? chunk : chunk.subarray(0, room);
247
251
  chunks.push(slice);
252
+ if (stdout) stdoutChunks.push(slice);
248
253
  captured += slice.length;
249
254
  };
250
- child.stdout?.on("data", collect);
251
- child.stderr?.on("data", collect);
255
+ child.stdout?.on("data", (chunk: Buffer) => collect(chunk, true));
256
+ child.stderr?.on("data", (chunk: Buffer) => collect(chunk, false));
252
257
  const kill = (): void => {
253
258
  if (child.pid === undefined) return;
254
259
  try {
@@ -276,6 +281,7 @@ async function spawnCommand(input: CodeStepRunInput, cwd: string, argv: Readonly
276
281
  signal,
277
282
  timedOut,
278
283
  captured: Buffer.concat(chunks),
284
+ stdout: Buffer.concat(stdoutChunks),
279
285
  outputBytes,
280
286
  spawnError,
281
287
  });
@@ -317,6 +323,7 @@ export async function runCodeStep(input: CodeStepRunInput): Promise<CodeStepOutc
317
323
  signal: null,
318
324
  timedOut: false,
319
325
  captured: Buffer.from(`${CODE_STEP_EMPTY_DIFF_MESSAGE}\n`, "utf8"),
326
+ stdout: Buffer.alloc(0),
320
327
  outputBytes: 0,
321
328
  spawnError: null,
322
329
  }
@@ -383,5 +390,5 @@ export async function runCodeStep(input: CodeStepRunInput): Promise<CodeStepOutc
383
390
  artifactPaths,
384
391
  reportDigest: codeReportDigest(report),
385
392
  };
386
- return { report, record, output: canonicalCodeReport(report) };
393
+ return { report, record, stdout: spawned.stdout.toString("utf8"), output: canonicalCodeReport(report) };
387
394
  }
@@ -1,4 +1,7 @@
1
1
  import type { SafeEventBus } from "../../core/event-bus.js";
2
+ import type { DeclaredCheckKind } from "../../tools/verify/catalog.js";
3
+ import type { NumericTolerance } from "../../tools/verify/numeric.js";
4
+ import type { PerfBudgetSpec } from "../../tools/verify/perf.js";
2
5
  import type { ResultContract } from "../agents/result-contract.js";
3
6
  import type { AgentAutomationAuthority, AgentSpec } from "../agents/spec.js";
4
7
  import type { CostProvenance } from "../providers/index.js";
@@ -15,6 +18,19 @@ import type { RunEnvelope, RunLineage, RunNodeIdentity, RunPhaseDurations, RunRe
15
18
  import type { DispatchFailoverCandidate, JobSpec } from "./validation.js";
16
19
  import type { WriteBoundaryAttribution } from "./write-boundary.js";
17
20
 
21
+ export interface ResolvedVerificationCheck {
22
+ check: string;
23
+ argv: ReadonlyArray<string>;
24
+ cwd: string;
25
+ timeoutMs: number;
26
+ /** Absent means `command`, the exit-code check every receipt carried before kinds existed. */
27
+ kind?: DeclaredCheckKind;
28
+ /** Sealed at admission with the reference as an absolute path. */
29
+ numeric?: { reference: string; tolerance: NumericTolerance };
30
+ /** Sealed at admission with the baseline as an absolute path. */
31
+ perf?: { budget?: PerfBudgetSpec; baseline?: string; tolerance?: { relative?: number } };
32
+ }
33
+
18
34
  export interface DispatchRequest extends JobSpec {
19
35
  /** Coordinator-owned result contract override for a fleet plan step. */
20
36
  resultContractOverride?: ResultContract;
@@ -33,13 +49,13 @@ export interface DispatchRequest extends JobSpec {
33
49
  runIdHint?: string;
34
50
  /** Parent checkout frozen by plan approval for task worktree application. */
35
51
  taskWorktreeDestination?: string;
36
- /** Admission-resolved commands. Model text never enters these argv vectors. */
37
- resolvedVerification?: ReadonlyArray<{
38
- check: string;
39
- argv: ReadonlyArray<string>;
40
- cwd: string;
41
- timeoutMs: number;
42
- }>;
52
+ /**
53
+ * Admission-resolved commands. Model text never enters these argv vectors.
54
+ * A numeric-compare or perf-budget check also seals its kind and the
55
+ * absolute reference or baseline path it will judge against, so host
56
+ * verification runs exactly the check the catalog declared at admission.
57
+ */
58
+ resolvedVerification?: ReadonlyArray<ResolvedVerificationCheck>;
43
59
  /**
44
60
  * Semantic role this request's first attempt runs under. Derived once by
45
61
  * `execution-role.ts` at request construction, never authored by a model, and
@@ -79,6 +95,14 @@ export interface DispatchRequest extends JobSpec {
79
95
  * validation projection strips it like the reservation and ledger refs.
80
96
  */
81
97
  parentToolCallId?: string;
98
+ /**
99
+ * Decision refs (`<interviewId>/<key>`) active on the parent session's
100
+ * decision board when this request was built. Sealed by the orchestrator
101
+ * from the board snapshot, never by model arguments: the validation
102
+ * projection strips it like `reservation` and `ledger`. Copied onto the run
103
+ * envelope and receipt so a receipt names the decisions it worked under.
104
+ */
105
+ decisionRefs?: ReadonlyArray<string>;
82
106
  }
83
107
 
84
108
  /** Internal, non-serializable admission hook for transactional resource owners. */
@@ -13,6 +13,8 @@ import {
13
13
  export interface ExecutionStepResult extends ExecutionHandoff {
14
14
  succeeded: boolean;
15
15
  integrityValid: boolean;
16
+ /** Decision refs the step's sealed receipt was made under; absent for code steps and decision-free runs. */
17
+ decisionRefs?: ReadonlyArray<string>;
16
18
  /**
17
19
  * The step changed the workspace outside its declared boundary. Sealed by
18
20
  * the orchestrator after the fact, never by the step: a run that reports on
@@ -844,14 +844,19 @@ function renderBoundSkillBlock(recipe: AgentRecipe): string {
844
844
  ].join("\n");
845
845
  }
846
846
 
847
- function workerPersonaBody(
848
- req: DispatchRequest,
849
- recipe: AgentRecipe | null,
850
- allowedTools: ReadonlyArray<ToolName>,
851
- ): string {
847
+ /**
848
+ * Whether Clio's canonical `context` tool is attached to this worker. A
849
+ * subprocess runtime runs its own tool loop and never receives Clio's tool
850
+ * surface, so the recipe's `context` entry does not make the tool available
851
+ * there, and bound skills must not be promised through it.
852
+ */
853
+ function canonicalContextAttached(runtime: Pick<RuntimeDescriptor, "kind">, tools: ReadonlyArray<ToolName>): boolean {
854
+ return runtime.kind !== "subprocess" && tools.includes(ToolNames.Context);
855
+ }
856
+
857
+ function workerPersonaBody(req: DispatchRequest, recipe: AgentRecipe | null, contextAttached: boolean): string {
852
858
  const base = req.systemPrompt && req.systemPrompt.length > 0 ? req.systemPrompt : (recipe?.body ?? "");
853
- const skillBlock =
854
- recipe && req.noSkills !== true && allowedTools.includes(ToolNames.Context) ? renderBoundSkillBlock(recipe) : "";
859
+ const skillBlock = recipe && req.noSkills !== true && contextAttached ? renderBoundSkillBlock(recipe) : "";
855
860
  return [base, skillBlock].filter((part) => part.trim().length > 0).join("\n\n");
856
861
  }
857
862
 
@@ -1350,6 +1355,8 @@ interface DispatchLifecycleStage {
1350
1355
  pipeline: RunPipelineProvenance | null;
1351
1356
  briefing: RunBriefingProvenance | null;
1352
1357
  personaOverride: RunPersonaOverride | null;
1358
+ /** Decision refs sealed on the request by the dispatch tool; null when the parent board was empty. */
1359
+ decisionRefs: ReadonlyArray<string> | null;
1353
1360
  projectContext: RunProjectContextProvenance;
1354
1361
  /** Rule ids the worker prompt compiler selected into this run's system prompt; [] when none matched. */
1355
1362
  rulesApplied: string[];
@@ -1382,6 +1389,8 @@ interface AcpDelegationLifecycleStage {
1382
1389
  pipeline: RunPipelineProvenance | null;
1383
1390
  briefing: RunBriefingProvenance | null;
1384
1391
  personaOverride: RunPersonaOverride | null;
1392
+ /** Decision refs sealed on the request by the dispatch tool; null when the parent board was empty. */
1393
+ decisionRefs: ReadonlyArray<string> | null;
1385
1394
  projectContext: RunProjectContextProvenance;
1386
1395
  /** ACP delegation bypasses the worker prompt compiler entirely, so this is always []. */
1387
1396
  rulesApplied: string[];
@@ -1954,7 +1963,7 @@ function buildDispatchWorkerSpec(input: DispatchWorkerSpecInput, config?: Config
1954
1963
  if (
1955
1964
  input.req.noSkills !== true &&
1956
1965
  recipeSkills.length > 0 &&
1957
- input.admission.allowedTools.includes(ToolNames.Context)
1966
+ canonicalContextAttached(input.target.runtime, input.admission.allowedTools)
1958
1967
  ) {
1959
1968
  spec.agentSkills = [...new Set(recipeSkills)];
1960
1969
  }
@@ -2750,13 +2759,13 @@ export function createDispatchBundle(
2750
2759
  }
2751
2760
 
2752
2761
  /** Retries only: the first attempt's member was consumed with the planned bound. */
2753
- function rebindReservationSlot(
2762
+ async function rebindReservationSlot(
2754
2763
  req: DispatchRequest,
2755
2764
  nodeId: string,
2756
2765
  endpoint: EndpointCapacity | null,
2757
2766
  costUsd: number,
2758
2767
  settings: EffectiveSettings,
2759
- ): void {
2768
+ ): Promise<void> {
2760
2769
  if (req.reservation === undefined || req.lineage === undefined) return;
2761
2770
  const capacity = reservationCapacitySnapshot(settings);
2762
2771
  const rebind = {
@@ -2767,7 +2776,7 @@ export function createDispatchBundle(
2767
2776
  capacity,
2768
2777
  nowMs: now(),
2769
2778
  };
2770
- rebindDispatchReservationMember(rebind);
2779
+ await rebindDispatchReservationMember(rebind);
2771
2780
  }
2772
2781
 
2773
2782
  /** Process-local retry queue keyed by finished run; backoff is keyed by assignment root. */
@@ -3553,8 +3562,8 @@ export function createDispatchBundle(
3553
3562
  ...admission,
3554
3563
  allowedTools: effectiveTools,
3555
3564
  };
3556
- const personaBody = workerPersonaBody(req, recipe, effectiveTools);
3557
- const hasCanonicalContext = effectiveTools.includes(ToolNames.Context);
3565
+ const hasCanonicalContext = canonicalContextAttached(target.runtime, effectiveTools);
3566
+ const personaBody = workerPersonaBody(req, recipe, hasCanonicalContext);
3558
3567
  const hasBoundSkills =
3559
3568
  hasCanonicalContext && recipe.skills !== undefined && recipe.skills.length > 0 && req.noSkills !== true;
3560
3569
  const compiledWorkerPrompt = await prompts.compileWorkerPrompt({
@@ -3639,6 +3648,7 @@ export function createDispatchBundle(
3639
3648
  pipeline: pipelineProvenanceFor(req),
3640
3649
  briefing: briefingProvenanceFor(req),
3641
3650
  personaOverride,
3651
+ decisionRefs: req.decisionRefs ?? null,
3642
3652
  projectContext: projectContextProvenance,
3643
3653
  rulesApplied: compiledWorkerPrompt.rulesApplied ?? [],
3644
3654
  operatorProfileApplied: compiledWorkerPrompt.operatorProfileApplied ?? false,
@@ -3686,7 +3696,7 @@ export function createDispatchBundle(
3686
3696
  }
3687
3697
  const cwd = req.cwd ?? process.cwd();
3688
3698
  const pathScope = resolveDispatchPathScope(req);
3689
- const personaBody = workerPersonaBody(req, null, []);
3699
+ const personaBody = workerPersonaBody(req, null, false);
3690
3700
  // ACP owns an unknown external tool inventory, so it receives the raw
3691
3701
  // bounded persona rather than a native Clio schema-harness claim.
3692
3702
  const systemPrompt = personaBody;
@@ -3728,6 +3738,7 @@ export function createDispatchBundle(
3728
3738
  pipeline: pipelineProvenanceFor(req),
3729
3739
  briefing: briefingProvenanceFor(req),
3730
3740
  personaOverride,
3741
+ decisionRefs: req.decisionRefs ?? null,
3731
3742
  projectContext: projectContextProvenance,
3732
3743
  rulesApplied: [],
3733
3744
  operatorProfileApplied: false,
@@ -4009,6 +4020,7 @@ export function createDispatchBundle(
4009
4020
  ...(req.council !== undefined ? { council: req.council } : {}),
4010
4021
  ...(req.plan !== undefined ? { plan: req.plan } : {}),
4011
4022
  ...(lifecycle.personaOverride ? { personaOverride: lifecycle.personaOverride } : {}),
4023
+ ...(lifecycle.decisionRefs ? { decisionRefs: lifecycle.decisionRefs } : {}),
4012
4024
  });
4013
4025
  observer?.onAdmitted({
4014
4026
  runId: envelope.id,
@@ -4081,6 +4093,12 @@ export function createDispatchBundle(
4081
4093
  });
4082
4094
 
4083
4095
  const startedAt = envelope.startedAt;
4096
+ let resolveFinal!: (receipt: RunReceipt) => void;
4097
+ let rejectFinal!: (error: unknown) => void;
4098
+ const finalPromise = new Promise<RunReceipt>((res, rej) => {
4099
+ resolveFinal = res;
4100
+ rejectFinal = rej;
4101
+ });
4084
4102
  const activeRun: ActiveRun = {
4085
4103
  runId: envelope.id,
4086
4104
  req,
@@ -4112,7 +4130,7 @@ export function createDispatchBundle(
4112
4130
  meter: tokenMeter,
4113
4131
  pricing: null,
4114
4132
  costProvenance: "unknown",
4115
- finalPromise: undefined as unknown as Promise<RunReceipt>,
4133
+ finalPromise,
4116
4134
  };
4117
4135
 
4118
4136
  const buildReceiptDraft = (
@@ -4170,6 +4188,7 @@ export function createDispatchBundle(
4170
4188
  ...(req.council !== undefined ? { council: req.council } : {}),
4171
4189
  ...(req.plan !== undefined ? { plan: req.plan } : {}),
4172
4190
  ...(lifecycle.personaOverride ? { personaOverride: lifecycle.personaOverride } : {}),
4191
+ ...(lifecycle.decisionRefs ? { decisionRefs: lifecycle.decisionRefs } : {}),
4173
4192
  projectContext: lifecycle.projectContext,
4174
4193
  rulesApplied: lifecycle.rulesApplied,
4175
4194
  operatorProfileApplied: lifecycle.operatorProfileApplied,
@@ -4295,7 +4314,6 @@ export function createDispatchBundle(
4295
4314
  const assessDispatchFinishContract = (): DispatchFinishContractSnapshot | null => {
4296
4315
  if (finishContractAssistantText.trim().length === 0) return null;
4297
4316
  const assessment = assessFinishContract({
4298
- assistantText: finishContractAssistantText,
4299
4317
  sessionEntries: finishContractEntries,
4300
4318
  assistantTurnId: finishContractAssistantTurnId,
4301
4319
  });
@@ -4316,7 +4334,7 @@ export function createDispatchBundle(
4316
4334
  return { assessment, rigor };
4317
4335
  };
4318
4336
 
4319
- const finalPromise = (async (): Promise<RunReceipt> => {
4337
+ (async (): Promise<RunReceipt> => {
4320
4338
  try {
4321
4339
  const result = await acp.promise;
4322
4340
  // The receipt reads meters the domain pump fills. Finalization
@@ -4452,9 +4470,7 @@ export function createDispatchBundle(
4452
4470
  } finally {
4453
4471
  leaseSlot.release();
4454
4472
  }
4455
- })();
4456
-
4457
- activeRun.finalPromise = finalPromise;
4473
+ })().then(resolveFinal, rejectFinal);
4458
4474
  active.set(envelope.id, activeRun);
4459
4475
 
4460
4476
  return {
@@ -4562,7 +4578,7 @@ export function createDispatchBundle(
4562
4578
  "dispatch: writeRoots cannot be enforced on an ACP delegation target; the external agent runs its own tool surface. Dispatch to a native or claude-sdk worker.",
4563
4579
  );
4564
4580
  }
4565
- rebindReservationSlot(req, "local", null, UNKNOWN_PRICING_ADMISSION_ESTIMATE_USD, settings);
4581
+ await rebindReservationSlot(req, "local", null, UNKNOWN_PRICING_ADMISSION_ESTIMATE_USD, settings);
4566
4582
  routeObservation = observeShadowRoute(req, undefined, settings);
4567
4583
  const delegated = await dispatchAcpDelegation(req, settings, timing, routeObservation.decision, observer);
4568
4584
  // An ACP member never runs host verification, so it can only ever leave
@@ -4603,7 +4619,7 @@ export function createDispatchBundle(
4603
4619
  };
4604
4620
  const endpoint = endpointCapacityForTarget(lifecycle.target.target.id);
4605
4621
  assertRouteWithinApprovedEnvelope(req, effectiveRoute);
4606
- rebindReservationSlot(
4622
+ await rebindReservationSlot(
4607
4623
  req,
4608
4624
  effectiveRoute.node,
4609
4625
  endpoint,
@@ -5110,6 +5126,7 @@ export function createDispatchBundle(
5110
5126
  ...(req.council !== undefined ? { council: req.council } : {}),
5111
5127
  ...(req.plan !== undefined ? { plan: req.plan } : {}),
5112
5128
  ...(lifecycle.personaOverride ? { personaOverride: lifecycle.personaOverride } : {}),
5129
+ ...(lifecycle.decisionRefs ? { decisionRefs: lifecycle.decisionRefs } : {}),
5113
5130
  ...(heartbeatAt ? { heartbeatAt: heartbeatIso(heartbeatAt) } : {}),
5114
5131
  });
5115
5132
  observer?.onAdmitted({
@@ -5213,6 +5230,13 @@ export function createDispatchBundle(
5213
5230
 
5214
5231
  const startedAt = envelope.startedAt;
5215
5232
 
5233
+ let resolveFinal!: (receipt: RunReceipt) => void;
5234
+ let rejectFinal!: (error: unknown) => void;
5235
+ const finalPromise = new Promise<RunReceipt>((res, rej) => {
5236
+ resolveFinal = res;
5237
+ rejectFinal = rej;
5238
+ });
5239
+
5216
5240
  const activeRun: ActiveRun = {
5217
5241
  runId: envelope.id,
5218
5242
  req,
@@ -5248,7 +5272,7 @@ export function createDispatchBundle(
5248
5272
  meter: tokenMeter,
5249
5273
  pricing: lifecycle.target.effectivePricing.rates,
5250
5274
  costProvenance: lifecycle.target.effectivePricing.provenance,
5251
- finalPromise: undefined as unknown as Promise<RunReceipt>,
5275
+ finalPromise,
5252
5276
  };
5253
5277
 
5254
5278
  const buildReceiptDraft = (
@@ -5343,6 +5367,7 @@ export function createDispatchBundle(
5343
5367
  ...(req.plan !== undefined ? { plan: req.plan } : {}),
5344
5368
  ...(fleetGate !== null ? { fleetGate } : {}),
5345
5369
  ...(lifecycle.personaOverride ? { personaOverride: lifecycle.personaOverride } : {}),
5370
+ ...(lifecycle.decisionRefs ? { decisionRefs: lifecycle.decisionRefs } : {}),
5346
5371
  projectContext: lifecycle.projectContext,
5347
5372
  rulesApplied: lifecycle.rulesApplied,
5348
5373
  operatorProfileApplied: lifecycle.operatorProfileApplied,
@@ -5486,7 +5511,6 @@ export function createDispatchBundle(
5486
5511
  const assessDispatchFinishContract = (): DispatchFinishContractSnapshot | null => {
5487
5512
  if (finishContractAssistantText.trim().length === 0) return null;
5488
5513
  const assessment = assessFinishContract({
5489
- assistantText: finishContractAssistantText,
5490
5514
  sessionEntries: finishContractEntries,
5491
5515
  assistantTurnId: finishContractAssistantTurnId,
5492
5516
  });
@@ -5515,7 +5539,7 @@ export function createDispatchBundle(
5515
5539
  // finalPromise settles.
5516
5540
  settlement?.live(envelope.id);
5517
5541
 
5518
- const finalPromise = (async (): Promise<RunReceipt> => {
5542
+ (async (): Promise<RunReceipt> => {
5519
5543
  try {
5520
5544
  const result = await workerDone;
5521
5545
  // The receipt reads meters the domain pump fills. Finalization
@@ -5832,9 +5856,8 @@ export function createDispatchBundle(
5832
5856
  unsubscribeAgentLedger?.();
5833
5857
  leaseSlot.release();
5834
5858
  }
5835
- })();
5859
+ })().then(resolveFinal, rejectFinal);
5836
5860
 
5837
- activeRun.finalPromise = finalPromise;
5838
5861
  active.set(envelope.id, activeRun);
5839
5862
 
5840
5863
  return attachRouteObservation({
@@ -6,6 +6,8 @@ export interface FleetCommitPriorResult {
6
6
  succeeded: boolean;
7
7
  integrityValid: boolean;
8
8
  receiptDigest: string;
9
+ /** Decision refs from the step's sealed receipt; they become `Clio-Decision:` trailers. */
10
+ decisionRefs?: ReadonlyArray<string>;
9
11
  }
10
12
 
11
13
  /**
@@ -23,6 +25,7 @@ export function deriveFleetCommitAttribution(input: {
23
25
  const byId = new Map(input.plan.steps.map((step) => [step.id, step] as const));
24
26
  let materiallyAuthored = false;
25
27
  let receipt: CommitAttributionEvidence["receipt"];
28
+ let decisions: CommitAttributionEvidence["decisions"];
26
29
  for (const candidate of input.step.commitFrom ?? []) {
27
30
  const source = byId.get(candidate);
28
31
  const result = input.priorResults.get(candidate);
@@ -35,6 +38,7 @@ export function deriveFleetCommitAttribution(input: {
35
38
  continue;
36
39
  }
37
40
  materiallyAuthored = true;
41
+ if (result.decisionRefs !== undefined && result.decisionRefs.length > 0) decisions = [...result.decisionRefs];
38
42
  if (/^[0-9a-f]{64}$/u.test(result.receiptDigest)) {
39
43
  receipt = {
40
44
  version: RUN_RECEIPT_INTEGRITY_VERSION,
@@ -52,5 +56,6 @@ export function deriveFleetCommitAttribution(input: {
52
56
  validationSucceeded: input.validationFresh,
53
57
  independentReviewPassed: input.independentReviewFresh,
54
58
  ...(receipt === undefined ? {} : { receipt }),
59
+ ...(decisions === undefined ? {} : { decisions }),
55
60
  };
56
61
  }
@@ -657,6 +657,7 @@ export async function executeFleetRun(input: ExecuteFleetRunInput): Promise<Flee
657
657
  output: receipt.output?.state === "final" ? receipt.output.text : "",
658
658
  succeeded: stepSucceeded,
659
659
  integrityValid,
660
+ ...(receipt.decisionRefs !== undefined ? { decisionRefs: receipt.decisionRefs } : {}),
660
661
  ...(failureReason !== undefined ? { failureReason } : {}),
661
662
  ...(gatePathHash !== undefined ? { gatePathHash } : {}),
662
663
  ...(delegationPlanHash !== undefined ? { delegationPlanHash } : {}),