@iowarp/clio-coder 0.4.2 → 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 (523) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/CONTRIBUTING.md +86 -19
  3. package/README.md +35 -6
  4. package/dist/{acp-TMDQZDIG.js → acp-WNAYYF4F.js} +12 -13
  5. package/dist/{agents-5N5NG3XG.js → agents-3OKXHLOI.js} +60 -57
  6. package/dist/assets/codewiki.json +1 -1
  7. package/dist/{auth-Z5CCBXKQ.js → auth-VKNNMGPU.js} +21 -19
  8. package/dist/{builtins-K6TNDT24.js → builtins-WGALA46I.js} +9 -4
  9. package/dist/{chunk-XE3PCIXH.js → chunk-23L32XTI.js} +12 -9
  10. package/dist/{chunk-I64IFBLB.js → chunk-25QBEXRS.js} +18 -11
  11. package/dist/{chunk-CDNVLKUX.js → chunk-26QSH3EJ.js} +13 -7
  12. package/dist/{chunk-QQLGQY2A.js → chunk-2ASED4PZ.js} +22 -22
  13. package/dist/{chunk-MCEPRMZW.js → chunk-2CU2H6KE.js} +2 -2
  14. package/dist/chunk-2DSOYNFC.js +108 -0
  15. package/dist/{chunk-72GZI5EV.js → chunk-2JH2WHGE.js} +2 -2
  16. package/dist/{chunk-I66EAJFY.js → chunk-2WZ546HR.js} +267 -232
  17. package/dist/{chunk-O3YUNJZ2.js → chunk-2ZSONWVL.js} +82 -25
  18. package/dist/{chunk-2NHR3NAY.js → chunk-36CT5VVL.js} +331 -42
  19. package/dist/{chunk-2X4RYJTJ.js → chunk-3GY4F45V.js} +3 -3
  20. package/dist/{chunk-ZW55JB7N.js → chunk-3ODX73FK.js} +4 -6
  21. package/dist/{chunk-PBP4B7XR.js → chunk-3UNOLWNZ.js} +3 -3
  22. package/dist/{chunk-4JDLP6ZS.js → chunk-3UUXNFEX.js} +14 -10
  23. package/dist/{chunk-RKSR6VSF.js → chunk-4IUZQIJ3.js} +29 -1
  24. package/dist/{chunk-ZW4HH5JJ.js → chunk-4M6Z5QVF.js} +6 -6
  25. package/dist/{chunk-K6BSR66V.js → chunk-4NSRCOYP.js} +4 -1
  26. package/dist/{chunk-M2DAX4F6.js → chunk-4WR7VSYB.js} +2 -2
  27. package/dist/{chunk-FSP7CMNU.js → chunk-54X7T7DK.js} +61 -6
  28. package/dist/{chunk-54ODD65L.js → chunk-5636DCO5.js} +4 -4
  29. package/dist/chunk-57XXR6DR.js +3763 -0
  30. package/dist/{chunk-3KIPBMUA.js → chunk-5ICU3EUH.js} +2 -2
  31. package/dist/{chunk-77QIVUZB.js → chunk-5MEZN6CB.js} +4 -4
  32. package/dist/{chunk-O42A54GG.js → chunk-5OIVVPHF.js} +2 -2
  33. package/dist/{chunk-YJISEZKC.js → chunk-5TUB6SLS.js} +6 -6
  34. package/dist/{chunk-IMXMHHMQ.js → chunk-6OSVSQL5.js} +341 -57
  35. package/dist/{chunk-Q4XWMHX6.js → chunk-6PAZTBPA.js} +14 -2
  36. package/dist/{chunk-FVDGR2ZL.js → chunk-6Q3CYFD3.js} +112 -39
  37. package/dist/{chunk-IDNA72AH.js → chunk-6QOTUPRG.js} +155 -36
  38. package/dist/{chunk-X7IARSHT.js → chunk-6UINWWS6.js} +16 -10
  39. package/dist/{chunk-CYZW7JHJ.js → chunk-72YIHOZQ.js} +9 -9
  40. package/dist/{chunk-IKSLQ4XV.js → chunk-75W7L2E2.js} +752 -861
  41. package/dist/{chunk-CRFOIAX3.js → chunk-7UGL4MB5.js} +6 -6
  42. package/dist/{chunk-HIICAHCJ.js → chunk-AUPNRN7C.js} +2 -2
  43. package/dist/{chunk-7BHIY2MW.js → chunk-BJVFZO5U.js} +8 -50
  44. package/dist/{chunk-B74PXLU7.js → chunk-CUSRQKPU.js} +65 -3
  45. package/dist/chunk-DQOVN6KV.js +386 -0
  46. package/dist/{chunk-E7GT7O5N.js → chunk-DT3LWJOB.js} +7 -4
  47. package/dist/chunk-DXKJURES.js +671 -0
  48. package/dist/{chunk-JBCS7CRR.js → chunk-EL24TAU4.js} +10 -10
  49. package/dist/{chunk-TPEQIQIE.js → chunk-ELWDPP3Y.js} +8 -8
  50. package/dist/{chunk-NDINPTJ4.js → chunk-ELZVTCGV.js} +5 -4
  51. package/dist/chunk-EXLD33WO.js +381 -0
  52. package/dist/chunk-FEAXX7B6.js +101 -0
  53. package/dist/{chunk-RLYRBIYQ.js → chunk-FFUPXJC4.js} +90 -331
  54. package/dist/{chunk-5PFYMY2V.js → chunk-FTMGRKEF.js} +2 -2
  55. package/dist/{chunk-34BHNEE3.js → chunk-GHS5EBTQ.js} +58 -7
  56. package/dist/{chunk-DYHAXKHD.js → chunk-GWZNEVM2.js} +12 -8
  57. package/dist/chunk-GX5WYQO4.js +59 -0
  58. package/dist/chunk-GYV6VZOC.js +26 -0
  59. package/dist/{chunk-MQXIVJ35.js → chunk-HAXOFFRH.js} +5 -5
  60. package/dist/chunk-I2DWJ4GM.js +390 -0
  61. package/dist/{chunk-TXOTCRLG.js → chunk-I5FWO7L5.js} +5 -5
  62. package/dist/{chunk-WNP7O5WZ.js → chunk-ID64D7PE.js} +4 -4
  63. package/dist/{chunk-XQRY4DTA.js → chunk-IGLP3ODT.js} +10 -10
  64. package/dist/chunk-IRXAATOX.js +539 -0
  65. package/dist/chunk-IXIY2H4R.js +44 -0
  66. package/dist/{chunk-SSEYRH53.js → chunk-IZXGRF7P.js} +92 -147
  67. package/dist/{chunk-5TSRNF4G.js → chunk-JCI2ROMZ.js} +164 -6
  68. package/dist/{chunk-JWJGP5DQ.js → chunk-JEIYHLOR.js} +7 -7
  69. package/dist/{chunk-F2I26BDK.js → chunk-JQLNNIKT.js} +4 -4
  70. package/dist/{chunk-BYMNWQ7O.js → chunk-JSD46VO2.js} +315 -63
  71. package/dist/{chunk-AK5XEFVZ.js → chunk-JT2RFCC5.js} +64 -14
  72. package/dist/{chunk-MCMZMDAC.js → chunk-K6T2ZAMZ.js} +168 -6
  73. package/dist/{chunk-PGF63K6I.js → chunk-KFV5L5SK.js} +73 -4
  74. package/dist/{chunk-IHXBNWMM.js → chunk-KXDSS5WJ.js} +7 -3
  75. package/dist/{chunk-PJX3WQUQ.js → chunk-LLXSDWXS.js} +3 -3
  76. package/dist/{chunk-DZAW46HP.js → chunk-LTIKRKFL.js} +3 -3
  77. package/dist/{chunk-DZEK6CJN.js → chunk-N56KALIC.js} +21 -21
  78. package/dist/{chunk-B7HM5Z7T.js → chunk-NAI6ZFCY.js} +9 -5
  79. package/dist/{chunk-I66ZTYNP.js → chunk-NRO2BJRH.js} +2656 -2213
  80. package/dist/{chunk-ZGNYYXQ6.js → chunk-NXIMQY5W.js} +3 -3
  81. package/dist/{chunk-IKOZFYBN.js → chunk-NXYCB2VD.js} +149 -106
  82. package/dist/{chunk-CWVRRIEI.js → chunk-NZMNUPZZ.js} +2 -2
  83. package/dist/{chunk-462T4EGZ.js → chunk-O5CVSAG5.js} +2 -2
  84. package/dist/chunk-ODGTEFFI.js +50 -0
  85. package/dist/{chunk-3F7VUY77.js → chunk-OEJSLEPW.js} +2 -2
  86. package/dist/{chunk-KKOJXO6R.js → chunk-OMQNJVKW.js} +4 -2
  87. package/dist/{chunk-5KW52TEP.js → chunk-Q4WO54TA.js} +132 -77
  88. package/dist/{chunk-W6NIE6OW.js → chunk-QUFRYSWI.js} +13 -7
  89. package/dist/{chunk-42FMPA75.js → chunk-QZWQA4DE.js} +2 -2
  90. package/dist/chunk-R6Q67RJH.js +134 -0
  91. package/dist/{chunk-W4YEMFBX.js → chunk-RAY4OVGZ.js} +3 -3
  92. package/dist/{chunk-ZNT2M6TG.js → chunk-RQCKCSRL.js} +17 -17
  93. package/dist/{chunk-LJID3DYZ.js → chunk-RXTN6AKH.js} +3 -3
  94. package/dist/{chunk-P75RZCJW.js → chunk-RZDWV63N.js} +3 -3
  95. package/dist/{chunk-UH632ZYL.js → chunk-S6PYF2XF.js} +2 -2
  96. package/dist/{chunk-HJWWJ6IL.js → chunk-TOIVGRUX.js} +17 -5
  97. package/dist/{chunk-HLAFFSEK.js → chunk-TQAHXW6Y.js} +2 -2
  98. package/dist/{chunk-JIEGK6UF.js → chunk-U6TMQNSI.js} +48 -4
  99. package/dist/{chunk-2HFQNRV3.js → chunk-UEPWCCTY.js} +12 -12
  100. package/dist/chunk-UOIZ7DA4.js +41 -0
  101. package/dist/{chunk-UH347SHR.js → chunk-USR47QNF.js} +11 -11
  102. package/dist/{chunk-AZ4WMN4W.js → chunk-V6HJFQZE.js} +2 -2
  103. package/dist/chunk-V76WTFTW.js +318 -0
  104. package/dist/{chunk-NMJXSHBJ.js → chunk-W54I7H25.js} +2 -2
  105. package/dist/{chunk-KPXDY6QF.js → chunk-XRZT5WY5.js} +2 -2
  106. package/dist/{chunk-UBRFI4HS.js → chunk-XULDXHTN.js} +142 -50
  107. package/dist/chunk-XXYSBZIQ.js +283 -0
  108. package/dist/{chunk-HKMD33FO.js → chunk-Y55JBDO5.js} +405 -122
  109. package/dist/{chunk-XOXV5GKE.js → chunk-YD5GIKET.js} +17 -8
  110. package/dist/{chunk-XGDPUNND.js → chunk-YECAMM3D.js} +2 -2
  111. package/dist/{chunk-BO7Y52RY.js → chunk-YNFKXPEC.js} +7 -7
  112. package/dist/{chunk-VXMFAE2W.js → chunk-YPC6ZR5L.js} +19 -6
  113. package/dist/{chunk-M2WXEHER.js → chunk-ZA4VCIGV.js} +2 -2
  114. package/dist/cli/index.js +42 -40
  115. package/dist/{clio-7VB377CC.js → clio-QLICPCF5.js} +7 -7
  116. package/dist/{code-nav-YVLCYA7V.js → code-nav-IJR2DBPR.js} +9 -9
  117. package/dist/{components-UBWCQSRW.js → components-2TGAI2RC.js} +5 -6
  118. package/dist/{config-4HVOS65E.js → config-IUA6OYNS.js} +88 -81
  119. package/dist/{configure-PIWO7B24.js → configure-VEPX4NMX.js} +26 -25
  120. package/dist/{context-KQYIWPWT.js → context-2DKHWH2T.js} +60 -45
  121. package/dist/{context-IYEHL3WQ.js → context-4MPR7WKB.js} +78 -69
  122. package/dist/{context-N6ZE3LGJ.js → context-BOYF5EJM.js} +15 -11
  123. package/dist/{context-clear-G4OGZJDS.js → context-clear-S4ZJCQUX.js} +73 -65
  124. package/dist/context-map-COB37XXN.js +505 -0
  125. package/dist/{context-working-set-BWLF6LJP.js → context-working-set-3I3FYX6Y.js} +18 -17
  126. package/dist/detail-A7JAVSIG.js +98 -0
  127. package/dist/{dispatch-runner-2QQAITS3.js → dispatch-runner-RJ5I2F2O.js} +99 -75
  128. package/dist/{docs-PD3EXDKU.js → docs-SPOV3BAN.js} +3 -5
  129. package/dist/{doctor-LHBD36VU.js → doctor-DKICC2SN.js} +71 -48
  130. package/dist/{eval-C45FYRJ6.js → eval-OQOQUDHK.js} +308 -146
  131. package/dist/{eval-inventory-6DEJPLBF.js → eval-inventory-Y6QRFOH5.js} +4 -4
  132. package/dist/{evidence-6SHONYAF.js → evidence-4DQ25GUQ.js} +79 -175
  133. package/dist/evidence-4F5USFKH.js +208 -0
  134. package/dist/{evolve-KRKMV72X.js → evolve-GSS52E5J.js} +71 -67
  135. package/dist/{extensions-KPZ2UHBB.js → extensions-G7MFLYHT.js} +8 -9
  136. package/dist/{fleet-IVTCKDHT.js → fleet-Q37YHHAQ.js} +126 -118
  137. package/dist/{fleet-commands-EDWL3IT7.js → fleet-commands-G7E4N7SM.js} +16 -13
  138. package/dist/{fleet-decisions-YP3YEFGK.js → fleet-decisions-O7M6QBA2.js} +9 -8
  139. package/dist/{fleet-graph-ZFWKHY2M.js → fleet-graph-TOUBW6OW.js} +21 -20
  140. package/dist/{fleet-inspect-FVUNCBML.js → fleet-inspect-SW33JJNI.js} +65 -60
  141. package/dist/{fleet-preflight-UN5XED4R.js → fleet-preflight-CV2655TW.js} +4 -5
  142. package/dist/{fleet-validate-XOWC4HSX.js → fleet-validate-KESZX2YH.js} +25 -24
  143. package/dist/{fleet-verify-UN3SODEL.js → fleet-verify-UQPMTVE3.js} +66 -61
  144. package/dist/{fleet-view-TWHJKCN6.js → fleet-view-MN2VG4MR.js} +65 -60
  145. package/dist/{init-T2QORQ3Y.js → init-PXEXQSBF.js} +90 -82
  146. package/dist/{interop-IN5I2A66.js → interop-ZG5T62U3.js} +12 -13
  147. package/dist/inventory-C26CFDRR.js +101 -0
  148. package/dist/{library-LSCATDLZ.js → library-B2W4N74O.js} +29 -29
  149. package/dist/{memory-HYOKAGGJ.js → memory-YCANYS5A.js} +73 -69
  150. package/dist/{models-2GPMFYCM.js → models-GERTU3YI.js} +51 -47
  151. package/dist/{monitor-E4ASVUJH.js → monitor-CPNIUULB.js} +74 -67
  152. package/dist/{orchestrator-DDMPR3PY.js → orchestrator-J4BSH4WQ.js} +1288 -1606
  153. package/dist/{panes-E3RUXOW5.js → panes-BOHAEGYC.js} +4 -4
  154. package/dist/{panes-IXKLOKA2.js → panes-NXSLDQZ2.js} +10 -11
  155. package/dist/{paths-L7LGY6RN.js → paths-VSUWNC22.js} +6 -7
  156. package/dist/reset-TNWTB5LU.js +343 -0
  157. package/dist/{resources-OTRSN34L.js → resources-4PXNMD5G.js} +29 -22
  158. package/dist/{run-5DEYH5QK.js → run-D6XJ34CN.js} +132 -132
  159. package/dist/{share-IHWTLO3M.js → share-2NWMJJEE.js} +27 -27
  160. package/dist/{skills-IYMXMKW4.js → skills-KR7WON5G.js} +40 -33
  161. package/dist/{skills-eval-DROHSJAR.js → skills-eval-O2ZNOLDS.js} +81 -77
  162. package/dist/{skills-inventory-D7X4L4ZX.js → skills-inventory-ZZOUBK7O.js} +23 -22
  163. package/dist/{slash-commands-QBM7UZ3B.js → slash-commands-ZXPJD64J.js} +47 -37
  164. package/dist/{steer-Z5DO23FJ.js → steer-XA25PSCS.js} +4 -4
  165. package/dist/{support-U7QOWY26.js → support-7EMVWYG2.js} +6 -6
  166. package/dist/{targets-P2FUC4IL.js → targets-OMH2XCSN.js} +50 -49
  167. package/dist/tasks-IPAGMEIX.js +36 -0
  168. package/dist/{terminal-lease-YREJ3JX2.js → terminal-lease-C2J3JYRE.js} +4 -4
  169. package/dist/{tools-5B7RO6MV.js → tools-EFFEAIDP.js} +8 -9
  170. package/dist/{trace-YMGMUM6A.js → trace-FXMXUZUF.js} +7 -7
  171. package/dist/uninstall-HALS6BLF.js +407 -0
  172. package/dist/upgrade-MS72RJEP.js +306 -0
  173. package/dist/{usage-ME5MPXGX.js → usage-NHG6MCJM.js} +162 -108
  174. package/dist/{verifiers-BVZ7IWOO.js → verifiers-7AUNVXDY.js} +155 -22
  175. package/dist/{verify-5K7ZKQFC.js → verify-FWYGPKMR.js} +14 -12
  176. package/dist/{web-fetch-MPARV2K7.js → web-fetch-V4FKSDAV.js} +4 -4
  177. package/dist/{wiki-generate-F5W5QTYY.js → wiki-generate-743CIGJW.js} +99 -90
  178. package/dist/{with-panes-BYOJCLAM.js → with-panes-BDQEWBRT.js} +10 -10
  179. package/dist/worker/entry.js +72 -68
  180. package/docs/README.md +3 -2
  181. package/docs/architecture/acp.md +17 -0
  182. package/docs/architecture/artifact-placement.md +1 -0
  183. package/docs/architecture/artifact-versions.md +2 -2
  184. package/docs/architecture/context-engine.md +4 -0
  185. package/docs/architecture/dispatch-typed-intent.md +1 -1
  186. package/docs/architecture/evidence-and-memory.md +1 -1
  187. package/docs/architecture/middleware-and-components.md +1 -1
  188. package/docs/architecture/model-catalog.md +21 -10
  189. package/docs/architecture/observability.md +19 -2
  190. package/docs/architecture/prompt-envelope-and-tools.md +17 -5
  191. package/docs/architecture/provider-adapter-cookbook.md +63 -0
  192. package/docs/architecture/safety-model.md +25 -22
  193. package/docs/architecture/tui-design.md +1 -1
  194. package/docs/guide/built-in-agents.md +25 -11
  195. package/docs/guide/commands-and-modes.md +18 -3
  196. package/docs/guide/configuration-and-targets.md +100 -10
  197. package/docs/guide/configuration-reference.md +17 -7
  198. package/docs/guide/environment-variables.md +4 -2
  199. package/docs/guide/installation-and-lifecycle.md +37 -4
  200. package/docs/guide/proactive-memory.md +66 -55
  201. package/docs/guide/skills-marketplace.md +18 -0
  202. package/docs/guide/tool-usage.md +78 -3
  203. package/docs/history/config-knobs-audit.md +2 -2
  204. package/docs/process/development-pipeline.md +40 -2
  205. package/docs/process/eval-runner.md +67 -3
  206. package/docs/process/git-commit-provenance.md +15 -0
  207. package/docs/process/release-cut-checklist.md +207 -0
  208. package/docs/process/scientific-validation.md +18 -17
  209. package/evals/behavioral-machinery-support.ts +1 -0
  210. package/evals/behavioral-machinery.yaml +1 -1
  211. package/evals/behavioral-model.yaml +3 -2
  212. package/package.json +2 -2
  213. package/skills/README.md +7 -5
  214. package/skills/coding/ast-grep/SKILL.md +101 -30
  215. package/skills/coding/ast-grep/evals.md +26 -0
  216. package/skills/coding/coding-standards/SKILL.md +47 -2
  217. package/skills/coding/coding-standards/evals.md +23 -0
  218. package/skills/coding/prototype/SKILL.md +87 -28
  219. package/skills/coding/prototype/evals.md +19 -0
  220. package/skills/coding/tdd/SKILL.md +80 -53
  221. package/skills/coding/tdd/evals.md +20 -0
  222. package/skills/context/context-handoff/SKILL.md +43 -2
  223. package/skills/context/context-handoff/evals.md +44 -0
  224. package/skills/context/context-prime/SKILL.md +45 -15
  225. package/skills/context/context-prime/evals.md +45 -0
  226. package/skills/git/branch-closeout/SKILL.md +132 -0
  227. package/skills/git/branch-closeout/evals.md +133 -0
  228. package/skills/git/branch-closeout/references/closeout-checklist.md +81 -0
  229. package/skills/git/file-ticket/SKILL.md +77 -63
  230. package/skills/git/file-ticket/assets/issue-template.md +22 -0
  231. package/skills/git/file-ticket/evals.md +31 -26
  232. package/skills/git/file-ticket/references/issue-discovery.md +49 -0
  233. package/skills/git/fix-issue/SKILL.md +87 -64
  234. package/skills/git/fix-issue/evals.md +35 -31
  235. package/skills/git/fix-issue/references/diagnosis-and-rca.md +46 -0
  236. package/skills/git/resolve-merge-conflicts/SKILL.md +100 -51
  237. package/skills/git/resolve-merge-conflicts/evals.md +52 -25
  238. package/skills/git/resolve-merge-conflicts/references/conflict-matrix.md +126 -0
  239. package/skills/git/ship/SKILL.md +103 -67
  240. package/skills/git/ship/assets/pr-template.md +21 -0
  241. package/skills/git/ship/evals.md +44 -28
  242. package/skills/git/ship/references/remote-and-branch-policy.md +62 -0
  243. package/skills/git/worktree-create/SKILL.md +80 -50
  244. package/skills/git/worktree-create/evals.md +40 -33
  245. package/skills/git/worktree-create/references/worktree-setup.md +62 -66
  246. package/skills/git/worktree-merge/SKILL.md +112 -65
  247. package/skills/git/worktree-merge/evals.md +42 -34
  248. package/skills/git/worktree-merge/references/merge-strategies.md +52 -0
  249. package/skills/planning/archify/SKILL.md +196 -0
  250. package/skills/planning/archify/evals.md +65 -0
  251. package/skills/planning/architecture/SKILL.md +61 -12
  252. package/skills/planning/architecture/evals.md +65 -0
  253. package/skills/planning/backlog/SKILL.md +130 -14
  254. package/skills/planning/backlog/evals.md +142 -0
  255. package/skills/planning/prd/SKILL.md +47 -6
  256. package/skills/planning/prd/evals.md +54 -0
  257. package/skills/planning/product-intent/SKILL.md +57 -2
  258. package/skills/planning/product-intent/evals.md +70 -0
  259. package/skills/planning/tech-spec/SKILL.md +53 -2
  260. package/skills/planning/tech-spec/evals.md +73 -0
  261. package/skills/registry.yaml +58 -50
  262. package/skills/remote.yaml +13 -0
  263. package/skills/research/arxiv-literature/SKILL.md +76 -18
  264. package/skills/research/arxiv-literature/evals.md +50 -0
  265. package/skills/research/experiment-protocol/SKILL.md +20 -1
  266. package/skills/research/experiment-protocol/evals.md +23 -0
  267. package/skills/research/scientific-debugging/SKILL.md +24 -1
  268. package/skills/research/scientific-debugging/evals.md +18 -0
  269. package/skills/research/scientific-modernization/SKILL.md +26 -1
  270. package/skills/research/scientific-modernization/evals.md +27 -0
  271. package/skills/skill-marketplace.json +63 -28
  272. package/skills/workflow/cut-it/SKILL.md +64 -5
  273. package/skills/workflow/cut-it/evals.md +101 -0
  274. package/skills/workflow/design-council/SKILL.md +112 -27
  275. package/skills/workflow/design-council/evals.md +161 -0
  276. package/skills/workflow/grill-me/SKILL.md +85 -10
  277. package/skills/workflow/grill-me/evals.md +153 -0
  278. package/skills/workflow/workflow-distiller/SKILL.md +76 -17
  279. package/skills/workflow/workflow-distiller/evals.md +118 -0
  280. package/src/cli/args.ts +0 -8
  281. package/src/cli/configure-interop.ts +105 -13
  282. package/src/cli/configure-oauth.ts +57 -0
  283. package/src/cli/configure-onboarding.ts +980 -0
  284. package/src/cli/configure-target.ts +594 -0
  285. package/src/cli/configure.ts +1084 -529
  286. package/src/cli/context-map.ts +114 -0
  287. package/src/cli/context.ts +4 -0
  288. package/src/cli/doctor-state-size.ts +1 -12
  289. package/src/cli/doctor-validation-contract.ts +28 -0
  290. package/src/cli/doctor.ts +5 -0
  291. package/src/cli/evidence-detail.ts +1 -75
  292. package/src/cli/evidence-inventory.ts +1 -167
  293. package/src/cli/index.ts +3 -0
  294. package/src/cli/lifecycle-presenter.ts +436 -0
  295. package/src/cli/models.ts +10 -2
  296. package/src/cli/modes/print.ts +5 -1
  297. package/src/cli/reset.ts +228 -106
  298. package/src/cli/run.ts +7 -4
  299. package/src/cli/select.ts +664 -0
  300. package/src/cli/skills.ts +9 -2
  301. package/src/cli/targets.ts +3 -0
  302. package/src/cli/tasks.ts +84 -0
  303. package/src/cli/uninstall.ts +233 -165
  304. package/src/cli/upgrade.ts +210 -150
  305. package/src/cli/usage.ts +92 -27
  306. package/src/cli/validate-model.ts +3 -3
  307. package/src/cli/verifiers.ts +147 -1
  308. package/src/cli/wiki-generate.ts +1 -0
  309. package/src/core/commit-attribution.ts +41 -1
  310. package/src/core/config.ts +56 -0
  311. package/src/core/external-diagnostic.ts +44 -0
  312. package/src/core/gateway-routing.ts +157 -0
  313. package/src/core/git-commit-attribution.ts +46 -3
  314. package/src/core/run-overrides.ts +0 -5
  315. package/src/core/safe-exec.ts +17 -2
  316. package/src/core/skill-activation.ts +92 -2
  317. package/src/core/tool-names.ts +5 -2
  318. package/src/domains/agents/builtins/architect.md +1 -1
  319. package/src/domains/agents/builtins/coder.md +1 -1
  320. package/src/domains/agents/builtins/documenter.md +1 -1
  321. package/src/domains/agents/builtins/git-master.md +1 -1
  322. package/src/domains/agents/builtins/provenance.md +7 -7
  323. package/src/domains/agents/builtins/tester.md +1 -1
  324. package/src/domains/agents/builtins/verifier.md +2 -2
  325. package/src/domains/agents/builtins/wiki-writer.md +4 -3
  326. package/src/domains/agents/builtins/world-knowledge.md +31 -0
  327. package/src/domains/agents/catalog.ts +1 -1
  328. package/src/domains/agents/result-contract.ts +70 -0
  329. package/src/domains/context/extension.ts +31 -7
  330. package/src/domains/context/refresh.ts +3 -0
  331. package/src/domains/context/wiki/frontmatter.ts +5 -2
  332. package/src/domains/context/wiki/generate.ts +6 -0
  333. package/src/domains/context/wiki/map-seed.ts +589 -0
  334. package/src/domains/context/wiki/plan.ts +2 -2
  335. package/src/domains/context/wiki/prompts.ts +43 -0
  336. package/src/domains/dispatch/active-route-planner.ts +4 -0
  337. package/src/domains/dispatch/admission.ts +29 -0
  338. package/src/domains/dispatch/agent-candidates.ts +10 -0
  339. package/src/domains/dispatch/budget-envelope.ts +86 -1
  340. package/src/domains/dispatch/capability-match.ts +1 -0
  341. package/src/domains/dispatch/capacity-lease.ts +17 -0
  342. package/src/domains/dispatch/code-step.ts +11 -4
  343. package/src/domains/dispatch/contract.ts +42 -8
  344. package/src/domains/dispatch/execution-scheduler.ts +2 -0
  345. package/src/domains/dispatch/extension.ts +184 -56
  346. package/src/domains/dispatch/fleet-commit-attribution.ts +5 -0
  347. package/src/domains/dispatch/fleet-run.ts +1 -0
  348. package/src/domains/dispatch/host-verification.ts +114 -13
  349. package/src/domains/dispatch/intent.ts +28 -18
  350. package/src/domains/dispatch/orphan-recovery.ts +2 -0
  351. package/src/domains/dispatch/receipt-integrity.ts +4 -0
  352. package/src/domains/dispatch/reservation-store.ts +5 -3
  353. package/src/domains/dispatch/state.ts +15 -2
  354. package/src/domains/dispatch/types.ts +20 -2
  355. package/src/domains/dispatch/worker-model-metadata.ts +38 -0
  356. package/src/domains/eval/metrics/call-ledger-stream.ts +34 -11
  357. package/src/domains/eval/metrics/token-stream.ts +201 -31
  358. package/src/domains/eval/metrics/tracked.ts +40 -4
  359. package/src/domains/eval/runners/clio-run.ts +17 -11
  360. package/src/domains/eval/runners/context-index.ts +2 -7
  361. package/src/domains/eval/runners/context-init.ts +3 -6
  362. package/src/domains/eval/runners/external-command.ts +29 -11
  363. package/src/domains/eval/schema/suite.ts +28 -0
  364. package/src/domains/eval/schema/verdict.ts +2 -2
  365. package/src/domains/eval/suites/resolve.ts +13 -1
  366. package/src/domains/eval/suites/run.ts +24 -3
  367. package/src/domains/evidence/build.ts +102 -15
  368. package/src/domains/evidence/detail.ts +69 -0
  369. package/src/domains/evidence/eval.ts +13 -1
  370. package/src/domains/evidence/finish-contract-map.ts +5 -1
  371. package/src/domains/evidence/inventory.ts +167 -0
  372. package/src/domains/evidence/store.ts +16 -0
  373. package/src/domains/evidence/types.ts +12 -0
  374. package/src/domains/extensions/resources.ts +7 -0
  375. package/src/domains/interop/registry.ts +6 -2
  376. package/src/domains/interop/types.ts +4 -0
  377. package/src/domains/lifecycle/migrations/index.ts +4 -0
  378. package/src/domains/memory/task-memory-policy.ts +70 -26
  379. package/src/domains/memory/task-memory-telemetry.ts +1 -0
  380. package/src/domains/middleware/index.ts +0 -1
  381. package/src/domains/middleware/marketplace-offer.ts +22 -35
  382. package/src/domains/middleware/memory-intervention.ts +127 -32
  383. package/src/domains/middleware/memory-step-endpoint.ts +3 -2
  384. package/src/domains/middleware/runtime.ts +7 -3
  385. package/src/domains/middleware/skills-reminder.ts +31 -2
  386. package/src/domains/mux/detect.ts +3 -6
  387. package/src/domains/observability/accountability.ts +15 -1
  388. package/src/domains/observability/compaction-usage.ts +118 -0
  389. package/src/domains/observability/contract.ts +52 -7
  390. package/src/domains/observability/cost.ts +1 -1
  391. package/src/domains/observability/evidence-index.ts +10 -0
  392. package/src/domains/observability/extension.ts +15 -6
  393. package/src/domains/observability/out-of-turn-usage.ts +52 -21
  394. package/src/domains/observability/projection.ts +394 -45
  395. package/src/{interactive → domains/observability}/worker-progress.ts +3 -3
  396. package/src/domains/prompts/fragments/operating/contract.md +2 -0
  397. package/src/domains/prompts/fragments/wiki/page.md +8 -0
  398. package/src/domains/providers/contract.ts +4 -1
  399. package/src/domains/providers/extension.ts +40 -9
  400. package/src/domains/providers/model-capabilities.ts +9 -0
  401. package/src/domains/providers/model-discovery.ts +3 -4
  402. package/src/domains/providers/model-runtime-capabilities.ts +15 -5
  403. package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +48 -26
  404. package/src/domains/providers/runtimes/antigravity/antigravity-code.ts +225 -45
  405. package/src/domains/providers/runtimes/claude/claude-code.ts +9 -0
  406. package/src/domains/providers/runtimes/common/lmstudio-http.ts +6 -2
  407. package/src/domains/providers/runtimes/common/local-synth.ts +2 -0
  408. package/src/domains/providers/runtimes/protocol/litellm.ts +119 -29
  409. package/src/domains/providers/support.ts +11 -5
  410. package/src/domains/providers/target-model-cache.ts +25 -2
  411. package/src/domains/providers/types/capability-flags.ts +2 -0
  412. package/src/domains/providers/types/runtime-descriptor.ts +20 -1
  413. package/src/domains/providers/types/target-descriptor.ts +19 -0
  414. package/src/domains/resources/index.ts +3 -0
  415. package/src/domains/resources/skills/install.ts +72 -7
  416. package/src/domains/resources/skills/loader.ts +7 -0
  417. package/src/domains/resources/skills/marketplace.ts +63 -11
  418. package/src/domains/safety/action-classifier.ts +7 -0
  419. package/src/domains/safety/autonomy.ts +15 -0
  420. package/src/domains/safety/default-path-policy.ts +2 -0
  421. package/src/domains/safety/finish-contract-registration.ts +29 -14
  422. package/src/domains/safety/finish-contract.ts +252 -40
  423. package/src/domains/safety/index.ts +21 -1
  424. package/src/domains/safety/path-policy.ts +1 -1
  425. package/src/domains/safety/policy-engine.ts +60 -17
  426. package/src/domains/safety/protected-artifacts.ts +191 -88
  427. package/src/domains/safety/rigor.ts +53 -39
  428. package/src/domains/safety/run-effects.ts +2 -22
  429. package/src/domains/safety/skill-authority.ts +55 -0
  430. package/src/domains/safety/validation-contract.ts +388 -0
  431. package/src/domains/session/archive-readers.ts +10 -1
  432. package/src/domains/session/compaction/compact.ts +72 -22
  433. package/src/domains/session/decision-board.ts +101 -2
  434. package/src/domains/session/entries.ts +50 -7
  435. package/src/domains/session/extension.ts +4 -4
  436. package/src/domains/session/handoff.ts +2 -1
  437. package/src/domains/session/manager.ts +2 -3
  438. package/src/domains/session/task-board.ts +14 -1
  439. package/src/domains/session/tree/fork.ts +1 -2
  440. package/src/domains/session/tree/navigator.ts +1 -1
  441. package/src/domains/session/usage.ts +3 -3
  442. package/src/domains/user-tasks/acceptance.ts +56 -0
  443. package/src/domains/user-tasks/active-acceptance.ts +40 -0
  444. package/src/domains/user-tasks/store.ts +34 -3
  445. package/src/engine/acp/adapter.ts +24 -6
  446. package/src/engine/acp/server.ts +21 -4
  447. package/src/engine/acp/transport.ts +53 -8
  448. package/src/engine/acp/types.ts +4 -0
  449. package/src/engine/agent.ts +13 -3
  450. package/src/engine/ai.ts +26 -8
  451. package/src/engine/antigravity/subprocess-runtime.ts +386 -120
  452. package/src/engine/api-registry.ts +3 -0
  453. package/src/engine/apis/ollama-native.ts +15 -0
  454. package/src/engine/apis/openai-completions.ts +117 -14
  455. package/src/engine/claude/subprocess-runtime.ts +107 -60
  456. package/src/engine/external-subprocess.ts +122 -6
  457. package/src/entry/background-model-metadata.ts +18 -0
  458. package/src/entry/compaction-prompt.ts +57 -0
  459. package/src/entry/orchestrator.ts +416 -218
  460. package/src/entry/task-memory-lifecycle.ts +35 -0
  461. package/src/interactive/chat-loop-messages.ts +13 -4
  462. package/src/interactive/chat-loop.ts +65 -2
  463. package/src/interactive/chat-renderer.ts +1 -0
  464. package/src/interactive/cost-overlay.ts +26 -2
  465. package/src/interactive/dispatch-board.ts +46 -717
  466. package/src/interactive/fleet-run-preview.ts +2 -1
  467. package/src/interactive/interactive-application.ts +3 -2
  468. package/src/interactive/interactive-presentation.ts +55 -12
  469. package/src/interactive/interactive-slash-runtime.ts +4 -2
  470. package/src/interactive/oracle.ts +5 -2
  471. package/src/interactive/overlays/fleet-run-approval.ts +3 -2
  472. package/src/interactive/overlays/message-picker.ts +2 -2
  473. package/src/interactive/overlays/settings.ts +2 -2
  474. package/src/interactive/overlays/tree-selector.ts +2 -2
  475. package/src/interactive/renderers/branch-summary.ts +1 -1
  476. package/src/interactive/renderers/worker-entry.ts +32 -0
  477. package/src/interactive/slash-autocomplete.ts +4 -6
  478. package/src/interactive/slash-commands.ts +49 -45
  479. package/src/interactive/slash-spec.ts +28 -0
  480. package/src/interactive/theme/labels.ts +19 -13
  481. package/src/interactive/turn-context.ts +9 -5
  482. package/src/interactive/turn-recovery.ts +8 -0
  483. package/src/interactive/turn-runtime.ts +27 -11
  484. package/src/interactive/turn-state.ts +7 -0
  485. package/src/interactive/view/artifacts.ts +2 -0
  486. package/src/interactive/worker-receipts.ts +1 -0
  487. package/src/interactive/worker-stream.ts +13 -4
  488. package/src/tools/bootstrap.ts +4 -0
  489. package/src/tools/builtin-tool-catalog.ts +31 -0
  490. package/src/tools/compete-worktrees.ts +7 -1
  491. package/src/tools/context/index.ts +30 -9
  492. package/src/tools/core-bootstrap.ts +16 -0
  493. package/src/tools/decide.ts +136 -0
  494. package/src/tools/dispatch-admission.ts +21 -0
  495. package/src/tools/dispatch-arguments.ts +1 -0
  496. package/src/tools/dispatch-event-text.ts +10 -0
  497. package/src/tools/dispatch-plan.ts +6 -2
  498. package/src/tools/dispatch-runner.ts +27 -1
  499. package/src/tools/dispatch-types.ts +6 -0
  500. package/src/tools/evidence.ts +96 -0
  501. package/src/tools/limitation.ts +76 -0
  502. package/src/tools/policy.ts +9 -0
  503. package/src/tools/presentation.ts +3 -0
  504. package/src/tools/registry.ts +11 -5
  505. package/src/tools/result-shaping.ts +17 -5
  506. package/src/tools/task-worktree.ts +13 -3
  507. package/src/tools/tasks.ts +10 -1
  508. package/src/tools/verify/authoring.ts +170 -83
  509. package/src/tools/verify/catalog.ts +122 -5
  510. package/src/tools/verify/index.ts +2 -1
  511. package/src/tools/verify/numeric.ts +298 -0
  512. package/src/tools/verify/perf.ts +143 -0
  513. package/src/tools/verify/scripts.ts +229 -2
  514. package/src/tools/worker-evidence.ts +3 -1
  515. package/src/worker/spec-contract.ts +4 -0
  516. package/dist/chunk-2Z2IKEXI.js +0 -1554
  517. package/dist/chunk-RVG5JXAL.js +0 -41
  518. package/dist/chunk-T56WDKA5.js +0 -183
  519. package/dist/chunk-VN3SHNBN.js +0 -313
  520. package/dist/chunk-VPKWYKEY.js +0 -169
  521. package/dist/reset-OAQP3W4O.js +0 -230
  522. package/dist/uninstall-N34PCTGJ.js +0 -331
  523. package/dist/upgrade-PXK3S2YM.js +0 -325
@@ -1,14 +1,18 @@
1
+ import { resolve } from "node:path";
1
2
  import { ToolNames } from "../../core/tool-names.js";
2
3
  import { isProjectVerifierCheckId, isVerificationScriptName } from "../../core/verification-scripts.js";
4
+ import { type DeclaredCheckSourceRef, PROJECT_VERIFIER_CATALOG_RELATIVE_PATH } from "../../tools/verify/catalog.js";
5
+ import type { UserTaskAcceptance } from "../user-tasks/acceptance.js";
3
6
  import {
4
7
  detectValidationCommand,
5
8
  extractCommandDeleteTargets,
6
9
  extractCommandWriteTargets,
7
10
  toolMutationPaths,
8
11
  } from "./protected-artifacts.js";
12
+ import type { Rigor } from "./rigor.js";
9
13
 
10
14
  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.";
15
+ "[Clio Coder] finish-contract advisory: you changed files this turn without recording validation evidence or a limitation receipt. Run a verification command or call limitation with the scope and reason.";
12
16
 
13
17
  /**
14
18
  * The recent-window cap (entries since the last user message). Exported so a
@@ -17,11 +21,24 @@ export const FINISH_CONTRACT_ADVISORY_MESSAGE =
17
21
  */
18
22
  export const DEFAULT_RECENT_ENTRY_LIMIT = 80;
19
23
 
20
- export type FinishContractEvidenceKind = "validation_command" | "protected_artifact" | "dispatch_receipt";
24
+ export type FinishContractEvidenceKind =
25
+ | "validation_command"
26
+ | "protected_artifact"
27
+ | "dispatch_receipt"
28
+ | "limitation";
29
+
30
+ interface ValidationExecutionEvidence {
31
+ source?: DeclaredCheckSourceRef;
32
+ cwd?: string;
33
+ argv?: ReadonlyArray<string>;
34
+ durationMs?: number;
35
+ }
21
36
 
22
- export interface FinishContractEvidence {
37
+ export interface FinishContractEvidence extends ValidationExecutionEvidence {
23
38
  kind: FinishContractEvidenceKind;
24
39
  summary: string;
40
+ check?: string;
41
+ paths?: ReadonlyArray<string>;
25
42
  turnId?: string;
26
43
  }
27
44
 
@@ -48,16 +65,22 @@ export type FinishContractAssessment =
48
65
  };
49
66
 
50
67
  export interface FinishContractInput {
51
- assistantText: string;
52
68
  sessionEntries?: ReadonlyArray<unknown>;
53
69
  assistantTurnId?: string | null;
54
70
  recentEntryLimit?: number;
71
+ rigor?: Rigor;
72
+ activeAcceptance?: UserTaskAcceptance;
73
+ /** Owning session workspace, supplied by the finish registration. */
74
+ workspaceRoot?: string;
55
75
  }
56
76
 
57
77
  interface ToolCallEvidenceCandidate {
58
78
  turnId?: string;
59
79
  toolCallId: string;
60
80
  command: string;
81
+ check?: string;
82
+ paths?: string[];
83
+ execution?: ValidationExecutionEvidence;
61
84
  }
62
85
 
63
86
  interface MutationCandidate {
@@ -65,32 +88,26 @@ interface MutationCandidate {
65
88
  paths: string[];
66
89
  }
67
90
 
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
91
  /**
79
92
  * Action-scoped completion contract. The engine keys off what the turn actually
80
93
  * DID, not how the prompt was phrased: it engages only when the recent window
81
94
  * mutated workspace state and then settled (turn_end) without recording
82
- * validation evidence or an explicit limitation. The turn settling is itself
95
+ * validation evidence or a limitation receipt. The turn settling is itself
83
96
  * the completion signal, so the model never has to type "done" to be gated, and
84
97
  * a work request phrased as a question cannot bypass the gate.
85
98
  *
86
99
  * Decision order (pure function of ledger receipts):
87
100
  * 1. no mutating receipt in the window -> ok/no_mutation
88
101
  * 2. validation evidence present -> ok/validation_evidence
89
- * 3. explicit limitation stated in the text -> ok/explicit_limitation
102
+ * 3. successful `limitation` receipt present -> ok/explicit_limitation
90
103
  * 4. otherwise -> engage/unvalidated_mutation
104
+ *
105
+ * The assistant's prose never enters the decision. A limitation counts only
106
+ * as a `limitation` tool_call paired with a non-error tool_result inside the
107
+ * same window the mutation scan uses, so a run cannot satisfy the contract by
108
+ * wording alone and a real limitation is never missed for its phrasing.
91
109
  */
92
110
  export function assessFinishContract(input: FinishContractInput): FinishContractAssessment {
93
- const assistantText = input.assistantText.trim();
94
111
  const sessionEntries = input.sessionEntries ?? [];
95
112
  const assistantTurnId = input.assistantTurnId ?? null;
96
113
  const window = recentEntries(sessionEntries, assistantTurnId, input.recentEntryLimit ?? DEFAULT_RECENT_ENTRY_LIMIT);
@@ -100,13 +117,39 @@ export function assessFinishContract(input: FinishContractInput): FinishContract
100
117
  return { kind: "ok", reason: "no_mutation", evidence: [], mutatedPaths };
101
118
  }
102
119
 
103
- const evidence = collectValidationEvidence(window);
120
+ const acceptanceChecks = new Set(input.activeAcceptance?.verification.map((item) => item.check) ?? []);
121
+ const evidence = collectValidationEvidence(window, acceptanceChecks, input.workspaceRoot);
122
+ const limitations = collectLimitationEvidence(window);
123
+ const required = input.rigor === "high" ? (input.activeAcceptance?.verification ?? []) : [];
124
+ if (required.length > 0) {
125
+ const passes = new Set(
126
+ required.filter((check) => evidence.some((item) => acceptanceCheckPassed(item, check, input.workspaceRoot))),
127
+ );
128
+ const limited = new Set(limitations.flatMap((item) => item.paths ?? []));
129
+ const missing = [
130
+ ...new Set(required.filter((check) => !passes.has(check) && !limited.has(check.check)).map((item) => item.check)),
131
+ ];
132
+ if (missing.length > 0)
133
+ return {
134
+ kind: "engage",
135
+ reason: "unvalidated_mutation",
136
+ message: `[Clio Coder] high-rigor finish gate: operator acceptance still requires passing validation for: ${missing.join(", ")}. Run each named check or include its exact id in limitation.paths.`,
137
+ evidence: [...evidence, ...limitations],
138
+ mutatedPaths,
139
+ };
140
+ return {
141
+ kind: "ok",
142
+ reason: passes.size === required.length ? "validation_evidence" : "explicit_limitation",
143
+ evidence: [...evidence, ...limitations],
144
+ mutatedPaths,
145
+ };
146
+ }
104
147
  if (evidence.length > 0) {
105
148
  return { kind: "ok", reason: "validation_evidence", evidence, mutatedPaths };
106
149
  }
107
150
 
108
- if (hasExplicitLimitation(assistantText)) {
109
- return { kind: "ok", reason: "explicit_limitation", evidence: [], mutatedPaths };
151
+ if (limitations.length > 0) {
152
+ return { kind: "ok", reason: "explicit_limitation", evidence: limitations, mutatedPaths };
110
153
  }
111
154
 
112
155
  return {
@@ -118,16 +161,80 @@ export function assessFinishContract(input: FinishContractInput): FinishContract
118
161
  };
119
162
  }
120
163
 
164
+ function acceptanceCheckPassed(
165
+ evidence: FinishContractEvidence,
166
+ required: UserTaskAcceptance["verification"][number],
167
+ workspaceRoot: string | undefined,
168
+ ): boolean {
169
+ if (evidence.kind !== "validation_command" || evidence.check !== required.check || !workspaceRoot || !evidence.source)
170
+ return false;
171
+ if (evidence.durationMs !== undefined && evidence.durationMs > required.timeoutMs) return false;
172
+ const root = resolve(workspaceRoot);
173
+ if (evidence.source.kind === "project-catalog")
174
+ return evidence.source.path === resolve(root, PROJECT_VERIFIER_CATALOG_RELATIVE_PATH);
175
+ return (
176
+ evidence.source.path === resolve(root, "package.json") &&
177
+ evidence.cwd === root &&
178
+ validationCheckId(evidence.argv?.join(" ") ?? "") === required.check
179
+ );
180
+ }
181
+
121
182
  /**
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.
183
+ * Successful `limitation` receipts over the recent window. A receipt is a
184
+ * `limitation` tool_call whose tool_result in the same window is not an
185
+ * error, judged by the same `successfulToolResultId` rule the mutation and
186
+ * validation scans use. A call the tool rejected (bad reason, empty scope)
187
+ * leaves no receipt, so it cannot settle the contract.
126
188
  */
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));
189
+ function collectLimitationEvidence(recent: ReadonlyArray<unknown>): FinishContractEvidence[] {
190
+ const evidence: FinishContractEvidence[] = [];
191
+ const calls = new Map<string, ToolCallEvidenceCandidate>();
192
+ const seen = new Set<string>();
193
+
194
+ for (const entry of recent) {
195
+ const call = limitationToolCall(entry);
196
+ if (call !== null) {
197
+ calls.set(call.toolCallId, call);
198
+ continue;
199
+ }
200
+ const resultId = successfulToolResultId(entry);
201
+ if (resultId === null) continue;
202
+ const candidate = calls.get(resultId);
203
+ if (candidate === undefined) continue;
204
+ const item: FinishContractEvidence = {
205
+ kind: "limitation",
206
+ summary: candidate.command,
207
+ ...(candidate.paths ? { paths: candidate.paths } : {}),
208
+ };
209
+ if (candidate.turnId !== undefined) item.turnId = candidate.turnId;
210
+ pushEvidence(evidence, seen, item);
211
+ }
212
+
213
+ return evidence;
214
+ }
215
+
216
+ function limitationToolCall(entry: unknown): ToolCallEvidenceCandidate | null {
217
+ const record = asRecord(entry);
218
+ if (record?.kind !== "message" || record.role !== "tool_call") return null;
219
+ const payload = asRecord(record.payload);
220
+ if (payload === null) return null;
221
+ const toolName = stringFromFirst(payload, ["name", "toolName", "tool"]);
222
+ if (toolName !== ToolNames.Limitation) return null;
223
+ const toolCallId = stringFromFirst(payload, ["toolCallId", "tool_call_id", "id"]) ?? turnIdOf(entry);
224
+ if (toolCallId === null) return null;
225
+ const args = asRecord(payload.args ?? payload.arguments ?? payload.input);
226
+ const scope = typeof args?.scope === "string" ? args.scope.trim() : "";
227
+ const reason = typeof args?.reason === "string" ? args.reason.trim() : "";
228
+ const candidate: ToolCallEvidenceCandidate = {
229
+ toolCallId,
230
+ paths: Array.isArray(args?.paths)
231
+ ? args.paths.filter((item): item is string => typeof item === "string").map((item) => item.trim())
232
+ : [],
233
+ command: `limitation recorded: ${scope.length > 0 ? scope : "unspecified"} (reason=${reason.length > 0 ? reason : "unspecified"})`,
234
+ };
235
+ const turnId = turnIdOf(entry);
236
+ if (turnId !== null) candidate.turnId = turnId;
237
+ return candidate;
131
238
  }
132
239
 
133
240
  /**
@@ -226,7 +333,11 @@ function pushPath(paths: string[], seen: Set<string>, path: string): void {
226
333
  * Inspection was removed because inspecting the repo is never a mutation, so it
227
334
  * can no longer be on the path to engaging the contract.
228
335
  */
229
- function collectValidationEvidence(recent: ReadonlyArray<unknown>): FinishContractEvidence[] {
336
+ function collectValidationEvidence(
337
+ recent: ReadonlyArray<unknown>,
338
+ acceptanceChecks: ReadonlySet<string>,
339
+ workspaceRoot: string | undefined,
340
+ ): FinishContractEvidence[] {
230
341
  const evidence: FinishContractEvidence[] = [];
231
342
  const toolCalls = new Map<string, ToolCallEvidenceCandidate>();
232
343
  const dispatchCalls = new Map<string, ToolCallEvidenceCandidate>();
@@ -239,7 +350,7 @@ function collectValidationEvidence(recent: ReadonlyArray<unknown>): FinishContra
239
350
  continue;
240
351
  }
241
352
 
242
- const call = bashValidationCall(entry);
353
+ const call = bashValidationCall(entry, acceptanceChecks, workspaceRoot);
243
354
  if (call !== null) {
244
355
  toolCalls.set(call.toolCallId, call);
245
356
  continue;
@@ -267,19 +378,19 @@ function collectValidationEvidence(recent: ReadonlyArray<unknown>): FinishContra
267
378
  }
268
379
  const candidate = toolCalls.get(resultId);
269
380
  if (candidate !== undefined) {
270
- pushEvidence(evidence, seen, validationEvidence(candidate));
381
+ pushEvidence(evidence, seen, validationEvidence(candidate, entry));
271
382
  }
272
383
  continue;
273
384
  }
274
385
 
275
- const bashExecution = bashExecutionEvidence(entry);
386
+ const bashExecution = bashExecutionEvidence(entry, acceptanceChecks, workspaceRoot);
276
387
  if (bashExecution !== null) pushEvidence(evidence, seen, bashExecution);
277
388
  }
278
389
 
279
390
  return evidence;
280
391
  }
281
392
 
282
- function recentEntries(
393
+ export function recentEntries(
283
394
  entries: ReadonlyArray<unknown>,
284
395
  assistantTurnId: string | null,
285
396
  recentEntryLimit: number,
@@ -299,7 +410,11 @@ function recentEntries(
299
410
  return entries.slice(startInclusive, endExclusive);
300
411
  }
301
412
 
302
- function bashValidationCall(entry: unknown): ToolCallEvidenceCandidate | null {
413
+ function bashValidationCall(
414
+ entry: unknown,
415
+ acceptanceChecks: ReadonlySet<string>,
416
+ workspaceRoot: string | undefined,
417
+ ): ToolCallEvidenceCandidate | null {
303
418
  const record = asRecord(entry);
304
419
  if (record?.kind !== "message" || record.role !== "tool_call") return null;
305
420
  const payload = asRecord(record.payload);
@@ -309,13 +424,15 @@ function bashValidationCall(entry: unknown): ToolCallEvidenceCandidate | null {
309
424
  const args = asRecord(payload.args ?? payload.arguments ?? payload.input);
310
425
  const command = typeof args?.command === "string" ? args.command : null;
311
426
  if (command === null) return null;
312
- const detected = detectValidationCommand(command);
427
+ const detected = acceptanceValidationCommand(command, acceptanceChecks);
313
428
  if (detected.kind !== "validation") return null;
314
429
  const toolCallId = stringFromFirst(payload, ["toolCallId", "tool_call_id", "id"]) ?? turnIdOf(entry);
315
430
  if (toolCallId === null) return null;
316
431
  const candidate: ToolCallEvidenceCandidate = {
317
432
  toolCallId,
318
433
  command: detected.matched,
434
+ ...validationCheckFields(detected.matched),
435
+ execution: packageCommandExecution(command, args?.cwd, workspaceRoot),
319
436
  };
320
437
  const turnId = turnIdOf(entry);
321
438
  if (turnId !== null) candidate.turnId = turnId;
@@ -380,6 +497,7 @@ function validationToolCall(entry: unknown): ToolCallEvidenceCandidate | null {
380
497
  const candidate: ToolCallEvidenceCandidate = {
381
498
  toolCallId,
382
499
  command: summary,
500
+ ...validationCheckFields(summary),
383
501
  };
384
502
  const turnId = turnIdOf(entry);
385
503
  if (turnId !== null) candidate.turnId = turnId;
@@ -414,7 +532,8 @@ function successfulToolResultId(entry: unknown): string | null {
414
532
  if (payload.isError === true || payload.error === true) return null;
415
533
  const result = asRecord(payload.result);
416
534
  const details = asRecord(result?.details);
417
- if (details?.kind === "error") return null;
535
+ if (result?.kind === "error" || details?.kind === "error") return null;
536
+ if (typeof details?.exitCode === "number" && details.exitCode !== 0) return null;
418
537
  return stringFromFirst(payload, ["toolCallId", "tool_call_id", "id"]);
419
538
  }
420
539
 
@@ -482,18 +601,24 @@ function dispatchReceiptAgentId(
482
601
  return candidate?.command.match(/^agent=([^\s]+)/)?.[1] ?? "unknown";
483
602
  }
484
603
 
485
- function bashExecutionEvidence(entry: unknown): FinishContractEvidence | null {
604
+ function bashExecutionEvidence(
605
+ entry: unknown,
606
+ acceptanceChecks: ReadonlySet<string>,
607
+ workspaceRoot: string | undefined,
608
+ ): FinishContractEvidence | null {
486
609
  const record = asRecord(entry);
487
610
  if (record?.kind !== "bashExecution") return null;
488
611
  if (typeof record.command !== "string") return null;
489
612
  if (record.cancelled === true) return null;
490
613
  if (record.exitCode !== 0) return null;
491
- const detected = detectValidationCommand(record.command);
614
+ const detected = acceptanceValidationCommand(record.command, acceptanceChecks);
492
615
  if (detected.kind !== "validation") return null;
493
616
  const contextMarker = record.excludeFromContext === true ? " [not sent to model]" : "";
494
617
  const evidence: FinishContractEvidence = {
495
618
  kind: "validation_command",
496
619
  summary: `validation command passed: ${detected.matched}${contextMarker}`,
620
+ ...validationCheckFields(detected.matched),
621
+ ...packageCommandExecution(record.command, record.cwd, workspaceRoot),
497
622
  };
498
623
  const turnId = turnIdOf(entry);
499
624
  if (turnId !== null) evidence.turnId = turnId;
@@ -515,17 +640,80 @@ function protectedArtifactEvidence(entry: unknown): FinishContractEvidence | nul
515
640
  return evidence;
516
641
  }
517
642
 
518
- function validationEvidence(candidate: ToolCallEvidenceCandidate): FinishContractEvidence {
643
+ function validationEvidence(candidate: ToolCallEvidenceCandidate, entry: unknown): FinishContractEvidence {
519
644
  const evidence: FinishContractEvidence = {
520
645
  kind: "validation_command",
521
646
  summary: `validation command passed: ${candidate.command}`,
647
+ ...(candidate.check ? { check: candidate.check } : {}),
648
+ ...(candidate.execution ?? declaredCheckExecution(entry, candidate.check)),
522
649
  };
523
650
  if (candidate.turnId !== undefined) evidence.turnId = candidate.turnId;
524
651
  return evidence;
525
652
  }
526
653
 
654
+ /** Preserve the verifier's execution facts only when they identify the declared check. */
655
+ function declaredCheckExecution(entry: unknown, check: string | undefined): ValidationExecutionEvidence {
656
+ const payload = asRecord(asRecord(entry)?.payload);
657
+ const details = asRecord(asRecord(payload?.result)?.details);
658
+ const source = asRecord(details?.source);
659
+ if (
660
+ !details ||
661
+ details.check !== check ||
662
+ details.exitCode !== 0 ||
663
+ details.aborted === true ||
664
+ details.timedOut === true ||
665
+ details.outputCapped === true ||
666
+ (source?.kind !== "package.json" && source?.kind !== "project-catalog") ||
667
+ typeof source.path !== "string" ||
668
+ typeof details.cwd !== "string" ||
669
+ !Array.isArray(details.argv) ||
670
+ !details.argv.every((arg): arg is string => typeof arg === "string")
671
+ )
672
+ return {};
673
+ if (source.kind === "project-catalog") {
674
+ const argv = details.argv;
675
+ if (
676
+ !Array.isArray(details.declaredCommand) ||
677
+ details.declaredCommand.length !== details.argv.length ||
678
+ !details.declaredCommand.every((arg, index) => arg === argv[index]) ||
679
+ typeof details.declaredCwd !== "string" ||
680
+ typeof details.declaredTimeoutMs !== "number" ||
681
+ typeof details.durationMs !== "number" ||
682
+ details.durationMs > details.declaredTimeoutMs ||
683
+ resolve(source.path, "../..", details.declaredCwd) !== details.cwd
684
+ )
685
+ return {};
686
+ }
687
+ return {
688
+ source: { kind: source.kind, path: source.path },
689
+ cwd: details.cwd,
690
+ argv: details.argv,
691
+ ...(typeof details.durationMs === "number" ? { durationMs: details.durationMs } : {}),
692
+ };
693
+ }
694
+
695
+ /** Exact package commands retain their execution cwd; a matched substring proves no project identity. */
696
+ function packageCommandExecution(
697
+ command: string,
698
+ cwd: unknown,
699
+ workspaceRoot: string | undefined,
700
+ ): ValidationExecutionEvidence {
701
+ if (
702
+ !workspaceRoot ||
703
+ !/^(?:npm|pnpm|yarn|bun) /u.test(command.trim()) ||
704
+ validationCheckId(command.trim()) === undefined
705
+ )
706
+ return {};
707
+ const executionCwd = resolve(workspaceRoot, typeof cwd === "string" ? cwd : ".");
708
+ return {
709
+ source: { kind: "package.json", path: resolve(executionCwd, "package.json") },
710
+ cwd: executionCwd,
711
+ argv: command.trim().split(/\s+/u),
712
+ };
713
+ }
714
+
527
715
  function pushEvidence(evidence: FinishContractEvidence[], seen: Set<string>, item: FinishContractEvidence): void {
528
- const key = `${item.kind}\0${item.summary}\0${item.turnId ?? ""}`;
716
+ const key = JSON.stringify(item);
529
717
  if (seen.has(key)) return;
530
718
  seen.add(key);
531
719
  evidence.push(item);
@@ -554,3 +742,27 @@ function stringFromFirst(record: Record<string, unknown>, keys: ReadonlyArray<st
554
742
  function asRecord(value: unknown): Record<string, unknown> | null {
555
743
  return value !== null && typeof value === "object" ? (value as Record<string, unknown>) : null;
556
744
  }
745
+
746
+ /** Exact check ids, never substring matches against rendered evidence summaries. */
747
+ function validationCheckId(command: string): string | undefined {
748
+ return (
749
+ /^(?:npm|pnpm|yarn|bun) (?:run )?([a-z0-9][a-z0-9._:-]*)$/.exec(command)?.[1] ??
750
+ /^verify ([a-z0-9][a-z0-9._:-]*)$/.exec(command)?.[1]
751
+ );
752
+ }
753
+
754
+ function validationCheckFields(command: string): { check?: string } {
755
+ const check = validationCheckId(command);
756
+ return check ? { check } : {};
757
+ }
758
+
759
+ /** Additional package scripts are admitted only by the operator's typed acceptance. */
760
+ function acceptanceValidationCommand(
761
+ command: string,
762
+ checks: ReadonlySet<string>,
763
+ ): ReturnType<typeof detectValidationCommand> {
764
+ const exact = command.trim();
765
+ const check = /^npm run ([a-z0-9][a-z0-9._:-]*)$/.exec(exact)?.[1];
766
+ if (check && checks.has(check)) return { kind: "validation", matched: exact };
767
+ return detectValidationCommand(command);
768
+ }
@@ -19,6 +19,7 @@ export {
19
19
  DEFAULT_AUTONOMY_LEVEL,
20
20
  isAutonomyLevel,
21
21
  mapAutonomy,
22
+ modelMayActivateSkills,
22
23
  } from "./autonomy.js";
23
24
  export type { SafetyContract, SafetyDecision } from "./contract.js";
24
25
  export type {
@@ -41,4 +42,23 @@ export {
41
42
  type PathPolicyKind,
42
43
  type PathPolicyOperation,
43
44
  } from "./path-policy.js";
44
- export { parseRigorOverride, type Rigor, resolveRigor } from "./rigor.js";
45
+ export {
46
+ parseRigorOverride,
47
+ type Rigor,
48
+ type RigorResolution,
49
+ type RigorSource,
50
+ resolveRigor,
51
+ rigorResolution,
52
+ } from "./rigor.js";
53
+ export {
54
+ describeValidationContract,
55
+ loadValidationContract,
56
+ parseValidationContractText,
57
+ VALIDATION_CONTRACT_CAPS,
58
+ VALIDATION_CONTRACT_MARKDOWN_PATH,
59
+ VALIDATION_CONTRACT_YAML_PATHS,
60
+ type ValidationContract,
61
+ type ValidationContractArtifact,
62
+ type ValidationContractLoadResult,
63
+ type ValidationContractRuntime,
64
+ } from "./validation-contract.js";
@@ -41,7 +41,7 @@ export function isSameOrDescendant(candidatePath: string, policyPath: string): b
41
41
  const candidate = path.resolve(candidatePath);
42
42
  const policy = path.resolve(policyPath);
43
43
  const relative = path.relative(policy, candidate);
44
- return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
44
+ return relative === "" || (relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative));
45
45
  }
46
46
 
47
47
  function expandTilde(rawPath: string): string {
@@ -25,10 +25,12 @@ import {
25
25
  extractCommandDeleteTargets,
26
26
  extractCommandWriteTargets,
27
27
  inlineShellScript,
28
- tokenizeShellLike,
28
+ invokesClioSkillMutation,
29
+ scanShellLike,
29
30
  } from "./protected-artifacts.js";
30
31
  import { formatRejection, type RejectionMessage } from "./rejection-feedback.js";
31
32
  import { getCachedDefaultRulePacks, type PackId, type RulePacks } from "./rule-pack-loader.js";
33
+ import { activeClioSkillRoots, skillMutationReason } from "./skill-authority.js";
32
34
 
33
35
  export type SafetyPolicySource =
34
36
  | "damage-control:base"
@@ -194,6 +196,7 @@ export function createSafetyPolicyEngine(options: SafetyPolicyEngineOptions = {}
194
196
  // cwd and roots to compare like against like (the design mandates no symlink chasing).
195
197
  const writeRootCwd = path.resolve(options.cwd ?? process.cwd());
196
198
  const writeRoots = (options.writeRoots ?? []).map((root) => resolvePathBoundary(writeRootCwd, root));
199
+ const skillRoots = activeClioSkillRoots(cwd);
197
200
  const packs = options.rulePacks ?? getCachedDefaultRulePacks();
198
201
  const projectPolicy = options.projectPolicy ?? loadProjectSafetyPolicy(cwd);
199
202
  const projectPolicyRoot =
@@ -201,12 +204,15 @@ export function createSafetyPolicyEngine(options: SafetyPolicyEngineOptions = {}
201
204
  const pathPolicyInput = projectPolicy.disableDefaultPathPolicy
202
205
  ? projectPolicy.pathPolicy
203
206
  : mergePathPolicyInputs(DEFAULT_DAMAGE_CONTROL_PATH_POLICY, projectPolicy.pathPolicy);
204
- // Clio's own secret store, by absolute path. The static default list carries
205
- // the `credentials.yaml` literal; the expansion has to happen here because
207
+ // Clio's own secret store and user skills, by absolute path.
208
+ // Config directory expansion has to happen here because
206
209
  // the list cannot call config helpers at module scope.
207
210
  const expandedDefaults = projectPolicy.disableDefaultPathPolicy
208
211
  ? pathPolicyInput
209
- : mergePathPolicyInputs(pathPolicyInput, { zeroAccessPaths: clioCredentialStorePaths() });
212
+ : mergePathPolicyInputs(pathPolicyInput, {
213
+ zeroAccessPaths: clioCredentialStorePaths(),
214
+ readOnlyPaths: clioSkillsRootPaths(),
215
+ });
210
216
  const pathPolicy = compilePathPolicy(expandedDefaults, projectPolicyRoot);
211
217
  // Bash-read scanning tests argument tokens against zero-access entries only:
212
218
  // read-only paths stay readable from bash by design, secrets do not.
@@ -308,6 +314,27 @@ export function createSafetyPolicyEngine(options: SafetyPolicyEngineOptions = {}
308
314
  return blockDecision(base, blockInput);
309
315
  }
310
316
 
317
+ // Editing active instructions is an operator privilege at every autonomy
318
+ // level, in both the coordinator and the shared worker safety contract.
319
+ const mutationCommand = call.tool === ToolNames.Bash ? command : catalogCommand;
320
+ const skillReason =
321
+ mutationCommand !== null && invokesClioSkillMutation(mutationCommand)
322
+ ? "skill installation and updates require the operator CLI or an explicit operator install choice; draft outside active skill roots"
323
+ : skillMutationReason(
324
+ skillRoots,
325
+ pathPolicyTargets(catalogCommand === null ? call : { tool: ToolNames.Bash, args: { command: catalogCommand } }),
326
+ callCwd,
327
+ mutationCommand,
328
+ );
329
+ if (skillReason !== null) {
330
+ return blockDecision(base, {
331
+ ruleId: "skill-authority",
332
+ reasonCode: "skill-authority",
333
+ reasons: [skillReason],
334
+ policySource: "builtin-classifier",
335
+ });
336
+ }
337
+
311
338
  // The path policy runs regardless of project policy validity. When
312
339
  // `.clio-coder/safety.yaml` is invalid, the loader has already dropped every
313
340
  // project-authored path entry and forced `disableDefaultPathPolicy`
@@ -454,6 +481,15 @@ function clioCredentialStorePaths(): string[] {
454
481
  }
455
482
  }
456
483
 
484
+ /** Absolute path of Clio's user skills, when resolvable. */
485
+ function clioSkillsRootPaths(): string[] {
486
+ try {
487
+ return [path.join(clioConfigDir(), "skills")];
488
+ } catch {
489
+ return [];
490
+ }
491
+ }
492
+
457
493
  /**
458
494
  * The exact safe presence form: `grep -q` or `grep -sq` (either flag order)
459
495
  * with a `^NAME=`-shaped pattern and a single file argument. Exit code only;
@@ -488,10 +524,10 @@ function stripQuotes(token: string): string {
488
524
  */
489
525
  function bashPathTokenCandidates(command: string): string[] {
490
526
  const candidates: string[] = [];
491
- for (const token of tokenizeShellLike(command)) {
527
+ for (const scanned of scanShellLike(command)) {
528
+ if (scanned.operator) continue;
529
+ const token = scanned.value;
492
530
  if (token.length === 0) continue;
493
- if (token === ";" || token === "&&" || token === "||" || token === "|" || token === ">" || token === ">>") continue;
494
- if (token === "<" || token === "<<") continue;
495
531
  // A token containing whitespace came from a quoted string of prose, not
496
532
  // a path argument; and flags are not paths unless they embed one
497
533
  // (--file=~/.aws/credentials).
@@ -821,9 +857,6 @@ function matchingProjectCommand(
821
857
  return null;
822
858
  }
823
859
 
824
- /** Operators that end chain recognition; only `&&` keeps a chain readable. */
825
- const CHAIN_BREAKING_TOKENS: ReadonlySet<string> = new Set([";", "|", "||", ">", ">>", "<", "<<"]);
826
-
827
860
  /** Chain length ceiling. Real compound calls are two or three steps. */
828
861
  const CHAIN_MAX_SEGMENTS = 6;
829
862
 
@@ -856,14 +889,16 @@ function recognizeCommandChain(
856
889
  ): ChainRecognition | null {
857
890
  const segments: string[][] = [];
858
891
  let current: string[] = [];
859
- for (const token of tokenizeShellLike(command)) {
860
- if (token === "&&") {
892
+ for (const token of scanShellLike(command)) {
893
+ if (token.operator && token.value === "&&") {
861
894
  segments.push(current);
862
895
  current = [];
863
896
  continue;
864
897
  }
865
- if (CHAIN_BREAKING_TOKENS.has(token)) return null;
866
- current.push(token);
898
+ // Only an actual && operator joins recognizable commands. Quoted words
899
+ // remain argv and every other real operator makes this chain unrecognized.
900
+ if (token.operator) return null;
901
+ current.push(token.value);
867
902
  }
868
903
  segments.push(current);
869
904
  if (segments.length < 2 || segments.length > CHAIN_MAX_SEGMENTS) return null;
@@ -943,10 +978,16 @@ function cwdArg(args: Record<string, unknown> | undefined, fallback: string): st
943
978
  }
944
979
 
945
980
  /**
946
- * Tools whose arguments are a file's contents rather than a command line.
947
- * Their damage-control scan is the destination path alone.
981
+ * Tools whose arguments carry file contents or task prose, not command lines.
982
+ * Their damage-control scan is the destination path alone, when present.
948
983
  */
949
- const CONTENT_BEARING_TOOLS: ReadonlySet<string> = new Set([ToolNames.Write, ToolNames.Edit, ToolNames.Artifact]);
984
+ const CONTENT_BEARING_TOOLS: ReadonlySet<string> = new Set([
985
+ ToolNames.Write,
986
+ ToolNames.Edit,
987
+ ToolNames.Artifact,
988
+ ToolNames.Dispatch,
989
+ ToolNames.Tasks,
990
+ ]);
950
991
 
951
992
  /**
952
993
  * The text damage-control rules are matched against.
@@ -968,6 +1009,8 @@ const CONTENT_BEARING_TOOLS: ReadonlySet<string> = new Set([ToolNames.Write, Too
968
1009
  * full. Only the destination path is scanned for a mutation tool, which keeps
969
1010
  * any path-shaped rule working; where the file may land is the write tool's own
970
1011
  * gate in `writePathClass`.
1012
+ * Dispatch and task-board prose likewise does not execute; worker commands
1013
+ * are scanned when the worker calls an execute-class tool.
971
1014
  */
972
1015
  function damageControlScan(call: ClassifierCall): string {
973
1016
  if (!CONTENT_BEARING_TOOLS.has(call.tool)) return serializeArgs(call.args);