@iowarp/clio-coder 0.4.1 → 0.4.3

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 (604) hide show
  1. package/CHANGELOG.md +127 -0
  2. package/CONTRIBUTING.md +142 -52
  3. package/README.md +434 -473
  4. package/SECURITY.md +2 -1
  5. package/dist/{acp-ZILU3AUO.js → acp-H2NGRPWO.js} +12 -12
  6. package/dist/{agents-HYWGBGQR.js → agents-TL5LLUQP.js} +56 -55
  7. package/dist/assets/codewiki.json +1 -1
  8. package/dist/{auth-N3QT7CBO.js → auth-E5SW4HMS.js} +23 -21
  9. package/dist/builtins-IA7V7FUC.js +22 -0
  10. package/dist/{chunk-7RY5VZPH.js → chunk-2APPQIER.js} +8 -8
  11. package/dist/{chunk-72GZI5EV.js → chunk-2JH2WHGE.js} +2 -2
  12. package/dist/{chunk-JA5QWE4Z.js → chunk-2UG5F4C5.js} +1973 -1664
  13. package/dist/{chunk-5YHDIDBP.js → chunk-2UH2KFUP.js} +2 -2
  14. package/dist/{chunk-CTJ4RNAA.js → chunk-2VIKGWFZ.js} +2 -2
  15. package/dist/{chunk-I66EAJFY.js → chunk-2WZ546HR.js} +267 -232
  16. package/dist/{chunk-GIZNH63R.js → chunk-35MSIRKH.js} +9 -4
  17. package/dist/chunk-3EBYEESD.js +314 -0
  18. package/dist/{chunk-J5LZHVIT.js → chunk-3M6DQK6S.js} +113 -35
  19. package/dist/{chunk-RKSR6VSF.js → chunk-4IUZQIJ3.js} +29 -1
  20. package/dist/{chunk-6FN3E6KX.js → chunk-4O6MANBS.js} +2 -2
  21. package/dist/chunk-4UVU7BJ5.js +39 -0
  22. package/dist/{chunk-VKRH2TCS.js → chunk-4WR7VSYB.js} +2 -2
  23. package/dist/{chunk-BBTJOK6Y.js → chunk-54CBCGIR.js} +5 -5
  24. package/dist/{chunk-AP73CFDC.js → chunk-5ICU3EUH.js} +2 -2
  25. package/dist/chunk-5MEZN6CB.js +1334 -0
  26. package/dist/{chunk-O42A54GG.js → chunk-5OIVVPHF.js} +2 -2
  27. package/dist/{chunk-ABLSQ6JX.js → chunk-64I3JVYM.js} +8 -2
  28. package/dist/{chunk-AFKWHWXF.js → chunk-6PTFB5VS.js} +39 -22
  29. package/dist/{chunk-VN3SHNBN.js → chunk-7DICMOS6.js} +2 -2
  30. package/dist/chunk-7DRAWPTZ.js +360 -0
  31. package/dist/chunk-7E7I3WLS.js +3762 -0
  32. package/dist/{chunk-BJGUKIG4.js → chunk-7ZYNNDKC.js} +7 -7
  33. package/dist/{chunk-XKA2ICR3.js → chunk-AF4YM7Z4.js} +652 -252
  34. package/dist/{chunk-GVQJ5CCZ.js → chunk-AX2THNSA.js} +12 -12
  35. package/dist/{chunk-IG7BCQBA.js → chunk-B4OAX3SI.js} +65 -3
  36. package/dist/{chunk-TD3PGPQA.js → chunk-B4VEBZKF.js} +3 -3
  37. package/dist/{chunk-74YWRRU5.js → chunk-BEPZRGGU.js} +10 -10
  38. package/dist/{chunk-FEFIFZTL.js → chunk-CE5AX47J.js} +2 -2
  39. package/dist/{chunk-UAPGZHYC.js → chunk-DWUOQKRU.js} +25 -11
  40. package/dist/{chunk-THYWACCR.js → chunk-E3TPLWFX.js} +3 -3
  41. package/dist/{chunk-7EPLI7VL.js → chunk-EKCHAPYA.js} +2 -2
  42. package/dist/{chunk-HLW2MRKE.js → chunk-F4EKGO4N.js} +3 -1
  43. package/dist/{chunk-PJJ6MY27.js → chunk-F5JHEYZM.js} +7 -7
  44. package/dist/{chunk-6CCS4G3W.js → chunk-FTMGRKEF.js} +3 -3
  45. package/dist/{chunk-SINK3QR6.js → chunk-G76U63X4.js} +17 -17
  46. package/dist/{chunk-EIMVLWB3.js → chunk-GHS5EBTQ.js} +64 -9
  47. package/dist/{chunk-QMXC4JB7.js → chunk-GI7YYQ3F.js} +187 -1419
  48. package/dist/{chunk-TZSKNMZG.js → chunk-GTUD2WMY.js} +2 -1
  49. package/dist/{chunk-6HMJX2VU.js → chunk-GWZNEVM2.js} +44 -12
  50. package/dist/chunk-GYV6VZOC.js +26 -0
  51. package/dist/{chunk-MQXIVJ35.js → chunk-HAXOFFRH.js} +5 -5
  52. package/dist/{chunk-UXN6JT4W.js → chunk-HEQY7ZFI.js} +3 -3
  53. package/dist/{chunk-7PWAODYW.js → chunk-I7XBWTYH.js} +2 -2
  54. package/dist/{chunk-GCSMB2KY.js → chunk-I7ZPNEJM.js} +145 -102
  55. package/dist/{chunk-WNP7O5WZ.js → chunk-ID64D7PE.js} +4 -4
  56. package/dist/{chunk-QTFGO774.js → chunk-IGLP3ODT.js} +29 -16
  57. package/dist/chunk-IJNZMHLA.js +101 -0
  58. package/dist/{chunk-BDPT6GTK.js → chunk-INY6HTFL.js} +7 -7
  59. package/dist/{chunk-PBP4B7XR.js → chunk-IUE3Y34X.js} +2 -2
  60. package/dist/{chunk-6NJQITNH.js → chunk-IWT4SF4R.js} +6 -3
  61. package/dist/{chunk-R23Z6K6I.js → chunk-JDAY6FIL.js} +19 -19
  62. package/dist/chunk-JEQ3XTHC.js +42 -0
  63. package/dist/{chunk-FSP7CMNU.js → chunk-JGRC33J2.js} +50 -4
  64. package/dist/{chunk-TVH4ONAM.js → chunk-JKKCYP3C.js} +10 -10
  65. package/dist/{chunk-HJWWJ6IL.js → chunk-JSC3U7TI.js} +16 -4
  66. package/dist/{chunk-C537JADH.js → chunk-KK4JZPBQ.js} +19 -141
  67. package/dist/{chunk-K6BF4U2H.js → chunk-KKOJXO6R.js} +62 -14
  68. package/dist/{chunk-IHXBNWMM.js → chunk-KXDSS5WJ.js} +7 -3
  69. package/dist/{chunk-6DWBAZ5U.js → chunk-L47TF46W.js} +5 -7
  70. package/dist/{chunk-HUAS7ITX.js → chunk-LDJG7DW3.js} +91 -42
  71. package/dist/{chunk-CDNVLKUX.js → chunk-LLDJM5XK.js} +13 -7
  72. package/dist/{chunk-YPI3QQCF.js → chunk-MCEPRMZW.js} +2 -4
  73. package/dist/{chunk-Y4CAGMM6.js → chunk-MNJGS2IN.js} +5 -6
  74. package/dist/{chunk-VKFQTNDV.js → chunk-MUW2BDDH.js} +4 -4
  75. package/dist/{chunk-E67WX76H.js → chunk-MWUZBSAQ.js} +104 -152
  76. package/dist/{chunk-OJTRZGR3.js → chunk-N2Z7HLVY.js} +21 -21
  77. package/dist/{chunk-TVHHYFHE.js → chunk-NEDJ26B5.js} +2 -2
  78. package/dist/{chunk-FYUN5KZ3.js → chunk-NIQJ66N4.js} +21 -21
  79. package/dist/{chunk-U2WB7TZS.js → chunk-NMJXSHBJ.js} +97 -85
  80. package/dist/{chunk-CWVRRIEI.js → chunk-NZMNUPZZ.js} +2 -2
  81. package/dist/{chunk-VEGN6WIQ.js → chunk-O5CVSAG5.js} +3 -3
  82. package/dist/{chunk-MOPSG2X7.js → chunk-OML5D5V5.js} +8 -8
  83. package/dist/{chunk-2VG7KLYV.js → chunk-PAJQJ7BS.js} +5816 -3255
  84. package/dist/{chunk-ZW55JB7N.js → chunk-PUVDKJ2Y.js} +2 -2
  85. package/dist/{chunk-BTGG6BG2.js → chunk-QWGDJJYJ.js} +158 -19
  86. package/dist/chunk-R6Q67RJH.js +134 -0
  87. package/dist/{chunk-ZJLUDYFY.js → chunk-RRNP2ANY.js} +6 -6
  88. package/dist/{chunk-PVAMAVBB.js → chunk-RSJ25QSL.js} +102 -2
  89. package/dist/{chunk-NLFAQR7Z.js → chunk-S66XZJOF.js} +3 -23
  90. package/dist/chunk-SKHCAU7K.js +385 -0
  91. package/dist/chunk-SZAA6XDG.js +30 -0
  92. package/dist/{chunk-J4HBWF6Y.js → chunk-TM6LQDI3.js} +131 -28
  93. package/dist/chunk-UOIZ7DA4.js +41 -0
  94. package/dist/{chunk-MA3H6DM5.js → chunk-UPZU6GE4.js} +25 -3
  95. package/dist/{chunk-BWW4HLO4.js → chunk-UXCU4E3T.js} +8 -6
  96. package/dist/{chunk-N5UK64DP.js → chunk-V2ANDPVT.js} +4 -4
  97. package/dist/{chunk-AK5XEFVZ.js → chunk-VA5FNYMT.js} +26 -13
  98. package/dist/{chunk-6VC4OV3Z.js → chunk-VIA6RFQZ.js} +3 -11
  99. package/dist/{chunk-ZAZB4JMW.js → chunk-VKPAQYEB.js} +27 -8
  100. package/dist/{chunk-QKIFBZKT.js → chunk-VW6DOEDG.js} +497 -81
  101. package/dist/{chunk-SCYB3HA4.js → chunk-W6RRQCPQ.js} +63 -19
  102. package/dist/{chunk-2NM363SV.js → chunk-WBKFA554.js} +10 -10
  103. package/dist/{chunk-R32CLGZ6.js → chunk-WCXUNS7U.js} +82 -21
  104. package/dist/{chunk-GPPB3JBE.js → chunk-WRBAGUNF.js} +3 -3
  105. package/dist/{chunk-IXJT6DCX.js → chunk-XIVNBFZS.js} +85 -30
  106. package/dist/{chunk-UEDMSP56.js → chunk-XPWWI35G.js} +417 -201
  107. package/dist/chunk-XRZT5WY5.js +47 -0
  108. package/dist/{chunk-3QSOM6PA.js → chunk-Y3CBHOR6.js} +2 -2
  109. package/dist/{chunk-VXMFAE2W.js → chunk-YPC6ZR5L.js} +19 -6
  110. package/dist/{chunk-AKB4GYDL.js → chunk-YQWYVTMC.js} +5 -5
  111. package/dist/{chunk-6I5ILFOF.js → chunk-ZA4VCIGV.js} +3 -3
  112. package/dist/{chunk-7OBGU7UB.js → chunk-ZDN3Y73Y.js} +12 -18
  113. package/dist/{chunk-3I5NY75V.js → chunk-ZWPRK62N.js} +8 -5
  114. package/dist/cli/index.js +41 -39
  115. package/dist/{clio-IT3G3VQH.js → clio-CMMK4KRR.js} +9 -9
  116. package/dist/{code-nav-RK6S7F6E.js → code-nav-MDZNQS33.js} +89 -21
  117. package/dist/{components-UBWCQSRW.js → components-UCUQ4QXW.js} +4 -4
  118. package/dist/{config-3QZRWZJF.js → config-SVM5P5YI.js} +131 -84
  119. package/dist/{configure-FL7Y3KJF.js → configure-LE3IK2TJ.js} +28 -26
  120. package/dist/{context-5HE7ODYK.js → context-2OHRKS42.js} +69 -64
  121. package/dist/{context-KYQFRVDC.js → context-E3VC7RX5.js} +15 -11
  122. package/dist/{context-XNHL75JV.js → context-VNCR7KAG.js} +93 -65
  123. package/dist/{context-clear-N545L53A.js → context-clear-BW4O37TG.js} +64 -60
  124. package/dist/context-map-COB37XXN.js +505 -0
  125. package/dist/{context-working-set-QHKXSV2F.js → context-working-set-VDS25HXZ.js} +19 -18
  126. package/dist/{dispatch-runner-RGIE5PCT.js → dispatch-runner-5AHT53RF.js} +93 -82
  127. package/dist/{docs-5NAF6AU7.js → docs-PD3EXDKU.js} +21 -20
  128. package/dist/{doctor-ZGPEGHIP.js → doctor-WNNVO6FY.js} +48 -47
  129. package/dist/{eval-GXLL44RD.js → eval-7G7SGAYO.js} +287 -115
  130. package/dist/{eval-inventory-HBWSWQOK.js → eval-inventory-Y6QRFOH5.js} +4 -4
  131. package/dist/{evidence-HWLBRH3Q.js → evidence-VD6736FQ.js} +67 -64
  132. package/dist/{evolve-FTZBMNVW.js → evolve-AL3NGVRL.js} +65 -62
  133. package/dist/{extensions-VHRBEID7.js → extensions-MOVJ32NM.js} +9 -7
  134. package/dist/{fleet-CKZHJWZJ.js → fleet-QZHUMAGI.js} +114 -111
  135. package/dist/{fleet-commands-EXDXBMV6.js → fleet-commands-BAYT5FJZ.js} +10 -10
  136. package/dist/{fleet-decisions-OTHB6KRL.js → fleet-decisions-IREVMRU4.js} +7 -6
  137. package/dist/{fleet-graph-YTEZUCUT.js → fleet-graph-YCTT3HTI.js} +22 -19
  138. package/dist/{fleet-inspect-SS6YMDCK.js → fleet-inspect-QVJTDAVB.js} +58 -55
  139. package/dist/{fleet-preflight-PBY4VYOM.js → fleet-preflight-25QAFPK4.js} +4 -4
  140. package/dist/{fleet-validate-KMEM5L3S.js → fleet-validate-5O57AAJ7.js} +26 -23
  141. package/dist/{fleet-verify-QD5M7E7Q.js → fleet-verify-CPH2W2T6.js} +59 -56
  142. package/dist/{fleet-view-WAMJYNDT.js → fleet-view-SWBR3VGQ.js} +58 -55
  143. package/dist/{init-5XQRBOFV.js → init-J477LKZH.js} +82 -79
  144. package/dist/{interop-34TVO25M.js → interop-3FCM6XLG.js} +11 -11
  145. package/dist/{library-3QY6KF57.js → library-QUQEIUG6.js} +30 -27
  146. package/dist/{memory-L4UTIIIW.js → memory-SGGSEP65.js} +67 -64
  147. package/dist/{models-ZVX3QOWE.js → models-HEKUAXXK.js} +53 -46
  148. package/dist/{monitor-CEKVSYTS.js → monitor-HKU57TYQ.js} +63 -60
  149. package/dist/{orchestrator-77BAP6BC.js → orchestrator-VDFAEFAI.js} +1831 -1057
  150. package/dist/{panes-7STHOAUJ.js → panes-DN2SSFOH.js} +5 -5
  151. package/dist/{panes-SHAUIRXY.js → panes-TALGNPZT.js} +29 -14
  152. package/dist/{paths-L7LGY6RN.js → paths-NBMFAIEZ.js} +5 -5
  153. package/dist/reset-EAJFFJVB.js +344 -0
  154. package/dist/{resources-74GKTLSF.js → resources-OVKSEFVE.js} +29 -20
  155. package/dist/{run-HBAUJNNZ.js → run-7DP7ZF2J.js} +120 -115
  156. package/dist/{share-G3APVLVP.js → share-WML67FT3.js} +32 -27
  157. package/dist/{skills-35HHUKCR.js → skills-SG662R2K.js} +41 -31
  158. package/dist/{skills-eval-QN4HSHDC.js → skills-eval-VVZEUU46.js} +78 -77
  159. package/dist/{skills-inventory-J357J34F.js → skills-inventory-I2E23GET.js} +23 -20
  160. package/dist/{slash-commands-JZZCQA32.js → slash-commands-S7MBJDQK.js} +40 -36
  161. package/dist/{steer-XAVHJM22.js → steer-2LQOMCPB.js} +3 -3
  162. package/dist/{support-U7QOWY26.js → support-CC2UJBJ6.js} +6 -6
  163. package/dist/{targets-DSM6CY3M.js → targets-4QC3HIEW.js} +54 -54
  164. package/dist/{terminal-lease-JOPFUVEM.js → terminal-lease-TUHIJ6Y2.js} +5 -5
  165. package/dist/{tools-MKNWVPBH.js → tools-TFGJICCU.js} +10 -10
  166. package/dist/{trace-ECQ7TIYZ.js → trace-FXMXUZUF.js} +55 -7
  167. package/dist/uninstall-5PEVOE5B.js +408 -0
  168. package/dist/upgrade-M4WXY6KN.js +303 -0
  169. package/dist/{usage-X52N3IDJ.js → usage-N7ZNVLEM.js} +151 -104
  170. package/dist/{verifiers-EJTVVSMA.js → verifiers-DJTP4XX6.js} +15 -15
  171. package/dist/{verify-YJL6XET2.js → verify-RWE4PPEK.js} +9 -9
  172. package/dist/{web-fetch-MPIFL3LL.js → web-fetch-MPARV2K7.js} +2 -2
  173. package/dist/{wiki-generate-4NDZTQ4B.js → wiki-generate-C7IQOXSP.js} +89 -86
  174. package/dist/{with-panes-OBOBFIIR.js → with-panes-4GCGSL7J.js} +53 -257
  175. package/dist/worker/entry.js +90 -74
  176. package/docs/README.md +176 -81
  177. package/docs/{acp.md → architecture/acp.md} +36 -20
  178. package/docs/{alcf-provider.md → architecture/alcf-provider.md} +8 -5
  179. package/docs/{architecture.md → architecture/architecture.md} +43 -22
  180. package/docs/{artifact-placement.md → architecture/artifact-placement.md} +27 -23
  181. package/docs/architecture/artifact-versions.md +90 -0
  182. package/docs/{capacity-and-scheduling.md → architecture/capacity-and-scheduling.md} +26 -13
  183. package/docs/{context-engine.md → architecture/context-engine.md} +29 -25
  184. package/docs/{context-working-set.md → architecture/context-working-set.md} +13 -10
  185. package/docs/{dispatch-architecture-rationale.md → architecture/dispatch-architecture-rationale.md} +12 -9
  186. package/docs/{dispatch-typed-intent.md → architecture/dispatch-typed-intent.md} +68 -46
  187. package/docs/{evidence-and-memory.md → architecture/evidence-and-memory.md} +23 -16
  188. package/docs/{middleware-and-components.md → architecture/middleware-and-components.md} +11 -5
  189. package/docs/{model-catalog.md → architecture/model-catalog.md} +61 -27
  190. package/docs/{observability.md → architecture/observability.md} +38 -14
  191. package/docs/{pi-boundary.md → architecture/pi-boundary.md} +24 -11
  192. package/docs/{prompt-envelope-and-tools.md → architecture/prompt-envelope-and-tools.md} +57 -20
  193. package/docs/{provider-adapter-cookbook.md → architecture/provider-adapter-cookbook.md} +99 -25
  194. package/docs/{safety-model.md → architecture/safety-model.md} +35 -20
  195. package/docs/{session-lifecycle.md → architecture/session-lifecycle.md} +8 -5
  196. package/docs/architecture/time-conventions.md +125 -0
  197. package/docs/{trace-store.md → architecture/trace-store.md} +13 -5
  198. package/docs/{tui-design.md → architecture/tui-design.md} +13 -13
  199. package/docs/{worker-dispatch-mechanics.md → architecture/worker-dispatch-mechanics.md} +27 -30
  200. package/docs/{built-in-agents.md → guide/built-in-agents.md} +65 -35
  201. package/docs/{commands-and-modes.md → guide/commands-and-modes.md} +66 -61
  202. package/docs/{configuration-and-targets.md → guide/configuration-and-targets.md} +323 -297
  203. package/docs/guide/configuration-reference.md +1163 -0
  204. package/docs/{environment-variables.md → guide/environment-variables.md} +33 -28
  205. package/docs/{exit-codes-and-output.md → guide/exit-codes-and-output.md} +6 -3
  206. package/docs/{extensions-and-sharing.md → guide/extensions-and-sharing.md} +41 -14
  207. package/docs/{fleet-dispatch.md → guide/fleet-dispatch.md} +39 -43
  208. package/docs/{glossary.md → guide/glossary.md} +14 -11
  209. package/docs/{installation-and-lifecycle.md → guide/installation-and-lifecycle.md} +81 -17
  210. package/docs/guide/panes-and-files.md +290 -0
  211. package/docs/{proactive-memory.md → guide/proactive-memory.md} +131 -107
  212. package/docs/{resource-library.md → guide/resource-library.md} +13 -4
  213. package/docs/{skills-marketplace.md → guide/skills-marketplace.md} +25 -3
  214. package/docs/{tool-usage.md → guide/tool-usage.md} +87 -23
  215. package/docs/{troubleshooting.md → guide/troubleshooting.md} +9 -4
  216. package/docs/{config-knobs-audit.md → history/config-knobs-audit.md} +11 -11
  217. package/docs/{release-cut-checklist.md → history/release-cut-checklist.md} +29 -2
  218. package/docs/process/development-pipeline.md +152 -0
  219. package/docs/process/documentation-coverage.md +100 -0
  220. package/docs/process/documentation-guide.md +187 -0
  221. package/docs/{eval-runner.md → process/eval-runner.md} +108 -53
  222. package/docs/{evals-internal.md → process/evals-internal.md} +10 -10
  223. package/docs/{evolution.md → process/evolution.md} +2 -2
  224. package/docs/{fleet-demo-runbook.md → process/fleet-demo-runbook.md} +11 -7
  225. package/docs/{git-commit-provenance.md → process/git-commit-provenance.md} +11 -4
  226. package/docs/{performance-methodology.md → process/performance-methodology.md} +87 -69
  227. package/docs/{scientific-validation.md → process/scientific-validation.md} +4 -4
  228. package/evals/README.md +2 -2
  229. package/evals/behavioral-model.yaml +3 -2
  230. package/package.json +10 -8
  231. package/skills/README.md +52 -41
  232. package/skills/coding/ast-grep/SKILL.md +102 -31
  233. package/skills/coding/ast-grep/evals.md +26 -0
  234. package/skills/coding/coding-standards/SKILL.md +41 -6
  235. package/skills/coding/coding-standards/evals.md +23 -0
  236. package/skills/coding/prototype/SKILL.md +88 -29
  237. package/skills/coding/prototype/evals.md +19 -0
  238. package/skills/coding/tdd/SKILL.md +81 -54
  239. package/skills/coding/tdd/evals.md +20 -0
  240. package/skills/context/context-handoff/SKILL.md +44 -3
  241. package/skills/context/context-handoff/evals.md +44 -0
  242. package/skills/context/context-prime/SKILL.md +46 -16
  243. package/skills/context/context-prime/evals.md +45 -0
  244. package/skills/git/branch-closeout/SKILL.md +132 -0
  245. package/skills/git/branch-closeout/evals.md +133 -0
  246. package/skills/git/branch-closeout/references/closeout-checklist.md +81 -0
  247. package/skills/git/file-ticket/SKILL.md +78 -64
  248. package/skills/git/file-ticket/assets/issue-template.md +22 -0
  249. package/skills/git/file-ticket/evals.md +31 -26
  250. package/skills/git/file-ticket/references/issue-discovery.md +49 -0
  251. package/skills/git/fix-issue/SKILL.md +88 -65
  252. package/skills/git/fix-issue/evals.md +35 -31
  253. package/skills/git/fix-issue/references/diagnosis-and-rca.md +46 -0
  254. package/skills/git/resolve-merge-conflicts/SKILL.md +101 -52
  255. package/skills/git/resolve-merge-conflicts/evals.md +52 -25
  256. package/skills/git/resolve-merge-conflicts/references/conflict-matrix.md +126 -0
  257. package/skills/git/ship/SKILL.md +103 -67
  258. package/skills/git/ship/assets/pr-template.md +21 -0
  259. package/skills/git/ship/evals.md +44 -28
  260. package/skills/git/ship/references/remote-and-branch-policy.md +62 -0
  261. package/skills/git/worktree-create/SKILL.md +80 -50
  262. package/skills/git/worktree-create/evals.md +40 -33
  263. package/skills/git/worktree-create/references/worktree-setup.md +62 -66
  264. package/skills/git/worktree-merge/SKILL.md +112 -65
  265. package/skills/git/worktree-merge/evals.md +42 -34
  266. package/skills/git/worktree-merge/references/merge-strategies.md +52 -0
  267. package/skills/meta/clio-coder-dev/SKILL.md +9 -5
  268. package/skills/meta/clio-coder-dev/evals.md +3 -2
  269. package/skills/meta/clio-coder-test/SKILL.md +102 -95
  270. package/skills/meta/clio-coder-test/evals.md +9 -4
  271. package/skills/meta/clio-coder-test/references/harness.md +100 -124
  272. package/skills/meta/clio-coder-test/references/test-map.md +77 -50
  273. package/skills/meta/credentials/SKILL.md +2 -2
  274. package/skills/meta/find-skills/SKILL.md +2 -2
  275. package/skills/meta/herdr/SKILL.md +2 -2
  276. package/skills/meta/skill-craft/SKILL.md +22 -16
  277. package/skills/planning/archify/SKILL.md +196 -0
  278. package/skills/planning/archify/evals.md +65 -0
  279. package/skills/planning/architecture/SKILL.md +62 -13
  280. package/skills/planning/architecture/evals.md +65 -0
  281. package/skills/planning/backlog/SKILL.md +131 -15
  282. package/skills/planning/backlog/evals.md +142 -0
  283. package/skills/planning/prd/SKILL.md +47 -7
  284. package/skills/planning/prd/evals.md +54 -0
  285. package/skills/planning/product-intent/SKILL.md +58 -3
  286. package/skills/planning/product-intent/evals.md +70 -0
  287. package/skills/planning/tech-spec/SKILL.md +54 -3
  288. package/skills/planning/tech-spec/evals.md +73 -0
  289. package/skills/registry.yaml +70 -62
  290. package/skills/remote.yaml +13 -0
  291. package/skills/research/arxiv-literature/SKILL.md +77 -19
  292. package/skills/research/arxiv-literature/evals.md +50 -0
  293. package/skills/research/experiment-protocol/SKILL.md +21 -2
  294. package/skills/research/experiment-protocol/evals.md +23 -0
  295. package/skills/research/scientific-debugging/SKILL.md +24 -2
  296. package/skills/research/scientific-debugging/evals.md +18 -0
  297. package/skills/research/scientific-modernization/SKILL.md +27 -2
  298. package/skills/research/scientific-modernization/evals.md +27 -0
  299. package/skills/skill-marketplace.json +97 -62
  300. package/skills/workflow/cut-it/SKILL.md +66 -6
  301. package/skills/workflow/cut-it/evals.md +101 -0
  302. package/skills/workflow/design-council/SKILL.md +118 -28
  303. package/skills/workflow/design-council/evals.md +161 -0
  304. package/skills/workflow/grill-me/SKILL.md +87 -11
  305. package/skills/workflow/grill-me/evals.md +153 -0
  306. package/skills/workflow/workflow-distiller/SKILL.md +77 -18
  307. package/skills/workflow/workflow-distiller/evals.md +118 -0
  308. package/src/cli/args.ts +2 -2
  309. package/src/cli/bootstrap-generate.ts +1 -1
  310. package/src/cli/config-inspect.ts +65 -12
  311. package/src/cli/configure-interop.ts +105 -13
  312. package/src/cli/configure-oauth.ts +57 -0
  313. package/src/cli/configure-onboarding.ts +980 -0
  314. package/src/cli/configure-target.ts +594 -0
  315. package/src/cli/configure.ts +1082 -532
  316. package/src/cli/context-map.ts +114 -0
  317. package/src/cli/context.ts +4 -0
  318. package/src/cli/docs.ts +22 -14
  319. package/src/cli/doctor-naming.ts +5 -5
  320. package/src/cli/doctor-toolchain.ts +3 -3
  321. package/src/cli/eval.ts +1 -2
  322. package/src/cli/extensions.ts +2 -1
  323. package/src/cli/fleet.ts +1 -1
  324. package/src/cli/index.ts +3 -1
  325. package/src/cli/internal-dispatch.ts +3 -4
  326. package/src/cli/lifecycle-presenter.ts +436 -0
  327. package/src/cli/models.ts +10 -2
  328. package/src/cli/modes/print.ts +5 -1
  329. package/src/cli/panes.ts +19 -5
  330. package/src/cli/reset.ts +228 -106
  331. package/src/cli/run.ts +9 -4
  332. package/src/cli/select.ts +664 -0
  333. package/src/cli/share.ts +5 -1
  334. package/src/cli/skills-eval.ts +3 -3
  335. package/src/cli/skills.ts +9 -2
  336. package/src/cli/targets.ts +5 -6
  337. package/src/cli/trace.ts +55 -4
  338. package/src/cli/uninstall.ts +233 -165
  339. package/src/cli/upgrade.ts +204 -149
  340. package/src/cli/usage.ts +86 -27
  341. package/src/cli/validate-model.ts +3 -3
  342. package/src/cli/wiki-generate.ts +1 -1
  343. package/src/core/artifact-paths.ts +1 -1
  344. package/src/core/bash-exec.ts +131 -86
  345. package/src/core/bus-events.ts +51 -6
  346. package/src/core/config.ts +61 -1
  347. package/src/core/defaults.ts +7 -4
  348. package/src/core/dispatch-outcome.ts +16 -0
  349. package/src/core/external-diagnostic.ts +44 -0
  350. package/src/core/gateway-routing.ts +157 -0
  351. package/src/core/guardrails.ts +10 -49
  352. package/src/core/prompt-hint.ts +9 -0
  353. package/src/core/safe-exec.ts +17 -2
  354. package/src/core/skill-activation.ts +89 -2
  355. package/src/domains/agents/builtins/architect.md +2 -3
  356. package/src/domains/agents/builtins/coder.md +3 -2
  357. package/src/domains/agents/builtins/debugger.md +2 -2
  358. package/src/domains/agents/builtins/documenter.md +2 -2
  359. package/src/domains/agents/builtins/git-master.md +1 -1
  360. package/src/domains/agents/builtins/oracle.md +1 -1
  361. package/src/domains/agents/builtins/provenance.md +1 -1
  362. package/src/domains/agents/builtins/researcher.md +1 -1
  363. package/src/domains/agents/builtins/scout.md +1 -1
  364. package/src/domains/agents/builtins/tester.md +2 -2
  365. package/src/domains/agents/builtins/verifier.md +2 -2
  366. package/src/domains/agents/builtins/wiki-writer.md +1 -1
  367. package/src/domains/agents/builtins/world-knowledge.md +31 -0
  368. package/src/domains/agents/catalog.ts +13 -15
  369. package/src/domains/agents/contract.ts +2 -0
  370. package/src/domains/agents/extension.ts +23 -1
  371. package/src/domains/agents/result-contract.ts +70 -0
  372. package/src/domains/config/keybindings.ts +8 -0
  373. package/src/domains/context/extension.ts +0 -3
  374. package/src/domains/context/wiki/map-seed.ts +589 -0
  375. package/src/domains/context/wiki/plan.ts +2 -2
  376. package/src/domains/context/working-set/path-index.ts +1 -0
  377. package/src/domains/dispatch/admission.ts +29 -0
  378. package/src/domains/dispatch/agent-candidates.ts +10 -0
  379. package/src/domains/dispatch/budget-envelope.ts +86 -1
  380. package/src/domains/dispatch/capability-match.ts +11 -0
  381. package/src/domains/dispatch/capacity-lease.ts +17 -0
  382. package/src/domains/dispatch/contract.ts +11 -1
  383. package/src/domains/dispatch/extension.ts +237 -49
  384. package/src/domains/dispatch/host-verification.ts +435 -39
  385. package/src/domains/dispatch/intent-requirements.ts +10 -0
  386. package/src/domains/dispatch/intent.ts +18 -1
  387. package/src/domains/dispatch/path-scope.ts +235 -24
  388. package/src/domains/dispatch/run-event-journal.ts +4 -15
  389. package/src/domains/dispatch/state.ts +2 -3
  390. package/src/domains/dispatch/transport.ts +45 -21
  391. package/src/domains/dispatch/types.ts +58 -3
  392. package/src/domains/dispatch/worker-model-metadata.ts +38 -0
  393. package/src/domains/eval/artifacts/store.ts +5 -0
  394. package/src/domains/eval/metrics/call-ledger-stream.ts +34 -11
  395. package/src/domains/eval/metrics/token-stream.ts +201 -31
  396. package/src/domains/eval/metrics/tracked.ts +40 -4
  397. package/src/domains/eval/runners/clio-run.ts +5 -2
  398. package/src/domains/eval/schema/suite.ts +28 -0
  399. package/src/domains/eval/schema/verdict.ts +2 -2
  400. package/src/domains/eval/store.ts +8 -1
  401. package/src/domains/eval/suites/resolve.ts +13 -1
  402. package/src/domains/eval/suites/run.ts +24 -3
  403. package/src/domains/evidence/trust-status.ts +10 -1
  404. package/src/domains/extensions/contract.ts +15 -1
  405. package/src/domains/extensions/discovery.ts +238 -41
  406. package/src/domains/extensions/extension.ts +105 -6
  407. package/src/domains/extensions/index.ts +24 -0
  408. package/src/domains/extensions/integrity.ts +189 -0
  409. package/src/domains/extensions/manager.ts +17 -1
  410. package/src/domains/extensions/resource-path.ts +27 -0
  411. package/src/domains/extensions/resources.ts +18 -38
  412. package/src/domains/extensions/snapshot-store.ts +39 -0
  413. package/src/domains/extensions/snapshot.ts +180 -0
  414. package/src/domains/extensions/state.ts +385 -57
  415. package/src/domains/extensions/types.ts +118 -1
  416. package/src/domains/interop/registry.ts +6 -2
  417. package/src/domains/interop/types.ts +4 -0
  418. package/src/domains/lifecycle/migrations/2026-09-01-extension-install-digests.ts +27 -0
  419. package/src/domains/lifecycle/migrations/index.ts +6 -0
  420. package/src/domains/lifecycle/naming-resources.ts +19 -4
  421. package/src/domains/lifecycle/naming-yazi.ts +10 -5
  422. package/src/domains/memory/task-memory-policy.ts +70 -26
  423. package/src/domains/memory/task-memory-telemetry.ts +1 -0
  424. package/src/domains/middleware/contract.ts +26 -0
  425. package/src/domains/middleware/extension.ts +24 -24
  426. package/src/domains/middleware/hook-receipts.ts +27 -4
  427. package/src/domains/middleware/hooks-io.ts +65 -32
  428. package/src/domains/middleware/hooks.ts +64 -0
  429. package/src/domains/middleware/index.ts +28 -5
  430. package/src/domains/middleware/marketplace-offer.ts +3 -35
  431. package/src/domains/middleware/memory-intervention.ts +127 -32
  432. package/src/domains/middleware/memory-step-endpoint.ts +3 -2
  433. package/src/domains/middleware/registrations.ts +326 -0
  434. package/src/domains/middleware/runtime.ts +28 -0
  435. package/src/domains/middleware/skills-reminder.ts +31 -2
  436. package/src/domains/middleware/snapshot.ts +20 -7
  437. package/src/domains/mux/contract.ts +38 -0
  438. package/src/domains/mux/detect.ts +6 -13
  439. package/src/domains/mux/index.ts +1 -1
  440. package/src/domains/mux/operations.ts +44 -5
  441. package/src/domains/mux/yazi/assets/yazi.toml +2 -2
  442. package/src/domains/mux/yazi/session.ts +53 -4
  443. package/src/domains/mux/yazi/theme.ts +117 -17
  444. package/src/domains/observability/compaction-usage.ts +118 -0
  445. package/src/domains/observability/contract.ts +10 -11
  446. package/src/domains/observability/cost.ts +1 -1
  447. package/src/domains/observability/extension.ts +17 -4
  448. package/src/domains/observability/out-of-turn-usage.ts +52 -21
  449. package/src/domains/observability/projection.ts +14 -90
  450. package/src/domains/observability/trace-store.ts +43 -7
  451. package/src/domains/prompts/compiler.ts +73 -53
  452. package/src/domains/prompts/contract.ts +15 -3
  453. package/src/domains/prompts/extension.ts +97 -9
  454. package/src/domains/prompts/fragments/identity/clio-worker.md +1 -3
  455. package/src/domains/prompts/fragments/identity/clio.md +6 -12
  456. package/src/domains/prompts/fragments/identity/docs-routing.md +1 -2
  457. package/src/domains/prompts/fragments/identity/self-awareness.md +3 -11
  458. package/src/domains/prompts/fragments/operating/contract.md +7 -15
  459. package/src/domains/prompts/fragments/operating/delegation.md +32 -34
  460. package/src/domains/prompts/fragments/operating/skills.md +10 -24
  461. package/src/domains/prompts/fragments/operating/worker.md +1 -8
  462. package/src/domains/providers/contract.ts +4 -1
  463. package/src/domains/providers/extension.ts +40 -9
  464. package/src/domains/providers/index.ts +1 -1
  465. package/src/domains/providers/model-capabilities.ts +9 -0
  466. package/src/domains/providers/model-discovery.ts +2 -0
  467. package/src/domains/providers/model-runtime-capabilities.ts +99 -25
  468. package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +699 -114
  469. package/src/domains/providers/runtime-resolution.ts +31 -0
  470. package/src/domains/providers/runtimes/antigravity/antigravity-code.ts +225 -45
  471. package/src/domains/providers/runtimes/common/lmstudio-http.ts +6 -2
  472. package/src/domains/providers/runtimes/common/local-synth.ts +2 -0
  473. package/src/domains/providers/runtimes/common/probe-helpers.ts +7 -2
  474. package/src/domains/providers/runtimes/local-native/llamacpp.ts +9 -1
  475. package/src/domains/providers/runtimes/protocol/litellm.ts +119 -29
  476. package/src/domains/providers/support.ts +11 -5
  477. package/src/domains/providers/target-model-cache.ts +25 -2
  478. package/src/domains/providers/types/capability-flags.ts +2 -0
  479. package/src/domains/providers/types/cost-provenance.ts +19 -0
  480. package/src/domains/providers/types/local-model-quirks.ts +85 -37
  481. package/src/domains/providers/types/runtime-descriptor.ts +20 -1
  482. package/src/domains/providers/types/target-descriptor.ts +19 -0
  483. package/src/domains/resources/index.ts +3 -0
  484. package/src/domains/resources/skills/install.ts +72 -7
  485. package/src/domains/resources/skills/loader.ts +23 -19
  486. package/src/domains/resources/skills/marketplace.ts +63 -11
  487. package/src/domains/safety/autonomy.ts +15 -0
  488. package/src/domains/safety/call-target.ts +1 -1
  489. package/src/domains/safety/index.ts +1 -0
  490. package/src/domains/safety/loop-detector.ts +7 -4
  491. package/src/domains/safety/path-policy.ts +1 -1
  492. package/src/domains/safety/policy-engine.ts +34 -11
  493. package/src/domains/safety/protected-artifacts.ts +191 -88
  494. package/src/domains/safety/run-effects.ts +2 -22
  495. package/src/domains/safety/skill-authority.ts +55 -0
  496. package/src/domains/session/compaction/compact.ts +72 -22
  497. package/src/domains/session/entries.ts +6 -0
  498. package/src/domains/session/task-board.ts +10 -9
  499. package/src/domains/session/usage.ts +3 -3
  500. package/src/domains/share/archive.ts +164 -7
  501. package/src/engine/acp/server.ts +62 -9
  502. package/src/engine/agent.ts +13 -3
  503. package/src/engine/ai.ts +26 -8
  504. package/src/engine/antigravity/subprocess-runtime.ts +386 -120
  505. package/src/engine/api-registry.ts +3 -0
  506. package/src/engine/apis/llamacpp-residency.ts +3 -4
  507. package/src/engine/apis/lmstudio.ts +3 -3
  508. package/src/engine/apis/ollama-native.ts +6 -6
  509. package/src/engine/apis/openai-completions.ts +145 -39
  510. package/src/engine/apis/output-budget.ts +8 -18
  511. package/src/engine/apis/residency.ts +8 -27
  512. package/src/engine/external-subprocess.ts +114 -6
  513. package/src/engine/gemma-channel-filter.ts +19 -0
  514. package/src/engine/loop-guard.ts +92 -12
  515. package/src/engine/worker-runtime.ts +40 -11
  516. package/src/engine/worker-tools.ts +3 -1
  517. package/src/entry/background-model-metadata.ts +18 -0
  518. package/src/entry/compaction-prompt.ts +57 -0
  519. package/src/entry/extension-hook-sources.ts +28 -0
  520. package/src/entry/extension-reload.ts +309 -0
  521. package/src/entry/orchestrator.ts +464 -251
  522. package/src/entry/task-memory-lifecycle.ts +35 -0
  523. package/src/interactive/application-controller.ts +2 -1
  524. package/src/interactive/bus-notices.ts +8 -1
  525. package/src/interactive/chat-loop-messages.ts +16 -17
  526. package/src/interactive/chat-loop.ts +75 -3
  527. package/src/interactive/chat-panel.ts +36 -13
  528. package/src/interactive/chat-renderer.ts +72 -7
  529. package/src/interactive/cost-overlay.ts +26 -2
  530. package/src/interactive/dispatch-board.ts +6 -11
  531. package/src/interactive/footer/widgets.ts +13 -0
  532. package/src/interactive/interactive-application.ts +39 -4
  533. package/src/interactive/interactive-input-runtime.ts +4 -0
  534. package/src/interactive/interactive-presentation.ts +2 -2
  535. package/src/interactive/interactive-slash-runtime.ts +4 -1
  536. package/src/interactive/overlays/extensions.ts +9 -1
  537. package/src/interactive/overlays/help-reference.ts +13 -0
  538. package/src/interactive/overlays/settings.ts +27 -16
  539. package/src/interactive/panes-runtime.ts +111 -35
  540. package/src/interactive/prompt-cache-identity.ts +88 -0
  541. package/src/interactive/renderers/worker-entry.ts +32 -0
  542. package/src/interactive/slash-commands.ts +153 -20
  543. package/src/interactive/stream-pacing-policy.ts +0 -23
  544. package/src/interactive/theme/labels.ts +19 -13
  545. package/src/interactive/turn-context.ts +39 -20
  546. package/src/interactive/turn-recovery.ts +8 -0
  547. package/src/interactive/turn-runtime.ts +27 -11
  548. package/src/interactive/turn-state.ts +7 -0
  549. package/src/interactive/worker-receipts.ts +1 -0
  550. package/src/interactive/worker-stream.ts +6 -1
  551. package/src/interactive/yazi-bridge.ts +60 -6
  552. package/src/tools/agent-tools.ts +30 -1
  553. package/src/tools/artifact.ts +2 -2
  554. package/src/tools/ask-user.ts +3 -3
  555. package/src/tools/bash.ts +1 -1
  556. package/src/tools/bootstrap.ts +4 -0
  557. package/src/tools/builtin-tool-catalog.ts +52 -22
  558. package/src/tools/codewiki/code-nav-surface.ts +6 -0
  559. package/src/tools/codewiki/code-nav.ts +99 -13
  560. package/src/tools/context/docs-engine.ts +20 -7
  561. package/src/tools/context/index.ts +59 -21
  562. package/src/tools/core-bootstrap.ts +28 -6
  563. package/src/tools/credential-present.ts +1 -2
  564. package/src/tools/dispatch-arguments.ts +6 -1
  565. package/src/tools/dispatch-event-text.ts +10 -0
  566. package/src/tools/dispatch-plan.ts +49 -4
  567. package/src/tools/dispatch-run-events.ts +1 -1
  568. package/src/tools/dispatch-runner.ts +12 -0
  569. package/src/tools/dispatch-schema.ts +338 -0
  570. package/src/tools/dispatch-types.ts +3 -0
  571. package/src/tools/dispatch.ts +9 -254
  572. package/src/tools/ledger.ts +3 -5
  573. package/src/tools/monitor-surface.ts +5 -13
  574. package/src/tools/observation.ts +4 -5
  575. package/src/tools/panes-surface.ts +4 -11
  576. package/src/tools/panes.ts +4 -2
  577. package/src/tools/policy.ts +15 -2
  578. package/src/tools/read.ts +5 -6
  579. package/src/tools/registry.ts +41 -12
  580. package/src/tools/result-shaping.ts +18 -14
  581. package/src/tools/steer-surface.ts +1 -1
  582. package/src/tools/tasks.ts +1 -1
  583. package/src/tools/truncate.ts +6 -5
  584. package/src/tools/verify/surface.ts +6 -12
  585. package/src/tools/web-fetch-surface.ts +1 -3
  586. package/src/tools/worker-evidence.ts +3 -1
  587. package/src/worker/spec-contract.ts +4 -0
  588. package/dist/builtins-UJLMOVOV.js +0 -17
  589. package/dist/chunk-5QIAJV2D.js +0 -48
  590. package/dist/chunk-JZWT5J3Y.js +0 -814
  591. package/dist/chunk-K7VKOLQQ.js +0 -15
  592. package/dist/chunk-PMZCIOCJ.js +0 -25
  593. package/dist/chunk-SUW5DORT.js +0 -819
  594. package/dist/chunk-UOV2BYIW.js +0 -107
  595. package/dist/chunk-WR6U3OVP.js +0 -45
  596. package/dist/chunk-Y45G3AXC.js +0 -1558
  597. package/dist/reset-EOLM7GVE.js +0 -230
  598. package/dist/uninstall-N34PCTGJ.js +0 -331
  599. package/dist/upgrade-H7TOM7YL.js +0 -323
  600. package/docs/artifact-versions.md +0 -67
  601. package/docs/development-pipeline.md +0 -121
  602. package/docs/documentation-coverage.md +0 -46
  603. package/docs/documentation-guide.md +0 -167
  604. package/docs/time-conventions.md +0 -101
@@ -2,17 +2,34 @@ import { execFileSync } from "node:child_process";
2
2
  import { createHash, randomUUID } from "node:crypto";
3
3
  import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
4
4
  import { dirname, join, resolve } from "node:path";
5
+ import { PATH_BOUNDARY_MAX_ENTRIES, pathBoundaryCovers, resolvePathBoundary } from "../../core/path-boundary.js";
5
6
  import { withStateFileLockSync } from "../../core/state-file-lock.js";
6
7
  import { clioStateDir } from "../../core/xdg.js";
7
8
  import { FLEET_COMMAND_BASE_ENV, type FleetCommand } from "../agents/fleet-commands.js";
8
9
  import { runCodeStep } from "./code-step.js";
9
10
  import type { DispatchRequest } from "./contract.js";
10
- import type { RunHostVerification, RunHostVerificationCheck } from "./types.js";
11
+ import type { RunHostVerification, RunHostVerificationAttribution, RunHostVerificationCheck } from "./types.js";
11
12
  import { captureWorkspaceSnapshot } from "./write-boundary.js";
12
13
 
13
14
  const OUTPUT_TAIL_BYTES = 2_048;
14
15
  const MEMO_VERSION = 1;
15
16
 
17
+ type ResolvedCheck = NonNullable<DispatchRequest["resolvedVerification"]>[number];
18
+
19
+ const HTTP_URL_RE = /\bhttps?:\/\/\S+/gu;
20
+ /**
21
+ * Path-like tokens a failing check named. A separator and a source or document
22
+ * extension are both required, which is the grammar `path-scope.ts:302` already
23
+ * uses to decide which prose tokens read as repository paths; without the
24
+ * extension list `10/20 passing` and `v1.2.3` become implicated files. Probed
25
+ * against node:test, tsc, and stack-trace output: relative, absolute, and
26
+ * `./`-prefixed forms all match and stop at a trailing `:line:col`.
27
+ */
28
+ const CHECK_OUTPUT_PATH_RE =
29
+ /\/?(?:[A-Za-z0-9_.@+-]+\/)+[A-Za-z0-9_.@+-]*\.(?:[cm]?[jt]sx?|json|ya?ml|md|txt|py|go|rs|c|h|cc|cpp|hpp|java|rb|sh|toml|css|html|sql)\b/gu;
30
+ /** Implicated paths recorded on a receipt, matching the intent path-list cap. */
31
+ const IMPLICATED_PATH_CAP = PATH_BOUNDARY_MAX_ENTRIES;
32
+
16
33
  interface MemoEntry {
17
34
  key: string;
18
35
  runId: string;
@@ -111,6 +128,69 @@ export function hostVerificationRejection(
111
128
  };
112
129
  }
113
130
 
131
+ async function runResolvedCheck(input: {
132
+ runId: string;
133
+ index: number;
134
+ resolvedCheck: ResolvedCheck;
135
+ stateDir: string;
136
+ env: NodeJS.ProcessEnv;
137
+ onDiagnostic?: (error: unknown) => void;
138
+ }): Promise<{ check: RunHostVerificationCheck; outputExcerpt: string }> {
139
+ const resolvedCheck = input.resolvedCheck;
140
+ const command: FleetCommand = {
141
+ id: resolvedCheck.check,
142
+ argv: [...resolvedCheck.argv],
143
+ cwd: "",
144
+ timeoutMs: resolvedCheck.timeoutMs,
145
+ env: [],
146
+ description: `Host verification check ${resolvedCheck.check}.`,
147
+ };
148
+ const fingerprint = workspaceFingerprint(resolvedCheck.cwd);
149
+ const key =
150
+ fingerprint === null ? null : memoKey({ ...command, cwd: resolve(resolvedCheck.cwd) }, fingerprint, input.env);
151
+ const hit =
152
+ key === null
153
+ ? undefined
154
+ : readMemo(input.stateDir).entries.find((entry) => entry.key === key && entry.check.exitCode === 0);
155
+ // A memo hit is always a pass, so no caller ever needs its output for
156
+ // attribution; the empty excerpt says the fresh output does not exist.
157
+ if (hit !== undefined) {
158
+ return {
159
+ check: { ...hit.check, argv: [...hit.check.argv], memo: true, evidenceRunId: hit.runId },
160
+ outputExcerpt: "",
161
+ };
162
+ }
163
+ const outcome = await runCodeStep({
164
+ stepId: `verification-${input.index + 1}-${resolvedCheck.check.replace(/[^a-z0-9._-]/giu, "_")}`,
165
+ command,
166
+ workspaceRoot: resolvedCheck.cwd,
167
+ artifactDir: join(input.stateDir, "artifacts", input.runId, "verification"),
168
+ env: input.env,
169
+ });
170
+ const artifactPath = outcome.record.artifactPaths[0];
171
+ const check: RunHostVerificationCheck = {
172
+ check: resolvedCheck.check,
173
+ argv: [...outcome.record.argv],
174
+ cwd: outcome.record.cwd,
175
+ exitCode: outcome.record.exitCode,
176
+ durationMs: outcome.record.durationMs,
177
+ memo: false,
178
+ outputTail: outputTail(outcome.report.outputExcerpt),
179
+ ...(artifactPath !== undefined ? { artifactPath } : {}),
180
+ };
181
+ if (check.exitCode === 0 && key !== null) {
182
+ try {
183
+ storeMemoEntry(input.stateDir, { key, runId: input.runId, check });
184
+ } catch (error) {
185
+ input.onDiagnostic?.(error);
186
+ }
187
+ }
188
+ // The 8KB code-step excerpt (code-step.ts:37), not the 2KB receipt tail:
189
+ // attribution reads the runner's own failure summary and a 2KB window loses
190
+ // it on a large suite.
191
+ return { check, outputExcerpt: outcome.report.outputExcerpt };
192
+ }
193
+
114
194
  export async function runHostVerification(input: {
115
195
  runId: string;
116
196
  request: Pick<DispatchRequest, "resolvedVerification">;
@@ -126,53 +206,369 @@ export async function runHostVerification(input: {
126
206
  const env = input.env ?? process.env;
127
207
  const results: RunHostVerificationCheck[] = [];
128
208
  for (const [index, resolvedCheck] of checks.entries()) {
129
- const command: FleetCommand = {
130
- id: resolvedCheck.check,
209
+ const outcome = await runResolvedCheck({
210
+ runId: input.runId,
211
+ index,
212
+ resolvedCheck,
213
+ stateDir,
214
+ env,
215
+ ...(input.onDiagnostic !== undefined ? { onDiagnostic: input.onDiagnostic } : {}),
216
+ });
217
+ results.push(outcome.check);
218
+ }
219
+ return {
220
+ status: results.every((check) => check.exitCode === 0) ? "verified" : "rejected",
221
+ checks: results,
222
+ };
223
+ }
224
+
225
+ function implicatedPaths(outputExcerpt: string, checkCwd: string): string[] {
226
+ const withoutUrls = outputExcerpt.replace(HTTP_URL_RE, (url) => " ".repeat(url.length));
227
+ const paths = new Set<string>();
228
+ for (const match of withoutUrls.matchAll(CHECK_OUTPUT_PATH_RE)) paths.add(resolve(checkCwd, match[0]));
229
+ return [...paths].sort();
230
+ }
231
+
232
+ /** Identity of a resolved check across batch members: same command, same cwd, same bound. */
233
+ function checkDedupeKey(resolvedCheck: ResolvedCheck): string {
234
+ return sha256(
235
+ JSON.stringify({
236
+ check: resolvedCheck.check,
131
237
  argv: [...resolvedCheck.argv],
132
- cwd: "",
238
+ cwd: resolve(resolvedCheck.cwd),
133
239
  timeoutMs: resolvedCheck.timeoutMs,
134
- env: [],
135
- description: `Host verification check ${resolvedCheck.check}.`,
136
- };
137
- const fingerprint = workspaceFingerprint(resolvedCheck.cwd);
138
- const key = fingerprint === null ? null : memoKey({ ...command, cwd: resolve(resolvedCheck.cwd) }, fingerprint, env);
139
- const hit =
140
- key === null
141
- ? undefined
142
- : readMemo(stateDir).entries.find((entry) => entry.key === key && entry.check.exitCode === 0);
143
- if (hit !== undefined) {
144
- results.push({ ...hit.check, argv: [...hit.check.argv], memo: true, evidenceRunId: hit.runId });
240
+ }),
241
+ );
242
+ }
243
+
244
+ export interface BatchVerificationParticipant {
245
+ runId: string;
246
+ request: Pick<DispatchRequest, "resolvedVerification" | "intent" | "cwd">;
247
+ workerSuccessful: boolean;
248
+ onDiagnostic?: (error: unknown) => void;
249
+ }
250
+
251
+ export interface BatchVerificationGate {
252
+ /** This run holds a capacity lease and its worker is spawned, so it may be writing. */
253
+ live(runId: string): void;
254
+ /** Park until every live member has arrived or left, then return this run's verdict. */
255
+ arrive(input: BatchVerificationParticipant): Promise<RunHostVerification | undefined>;
256
+ /** Release a member that will never arrive. Idempotent, and a no-op for one already parked. */
257
+ abandon(runId: string): void;
258
+ }
259
+
260
+ interface ParkedMember {
261
+ participant: BatchVerificationParticipant;
262
+ settle: (value: RunHostVerification | undefined) => void;
263
+ /**
264
+ * Reject the parked promise so the member's finalization takes the identical
265
+ * path a single-task dispatch takes when its declared check cannot run at all
266
+ * (`extension.ts:5544` throws into the finalization catch at 5669 and the run
267
+ * is marked failed). Silently dropping a declared check must never look like
268
+ * never having declared one.
269
+ */
270
+ fail: (error: unknown) => void;
271
+ }
272
+
273
+ /**
274
+ * The member's declared write roots resolved in the frame its own request ran in.
275
+ *
276
+ * An empty result means UNCONFINED, never "writes nothing": `intent.ts:139`
277
+ * normalizes a `"."` scope entry to an empty list, a request may omit
278
+ * `write_roots` entirely, and `extension.ts:1949` only builds a write boundary
279
+ * for a non-empty list, so such a run executed with no write confinement at all.
280
+ */
281
+ function memberBoundary(participant: BatchVerificationParticipant): string[] {
282
+ const writeRoots = participant.request.intent?.writeRoots ?? [];
283
+ return writeRoots.map((root) => resolvePathBoundary(participant.request.cwd ?? process.cwd(), root));
284
+ }
285
+
286
+ /**
287
+ * Charge one failing batch check to the members that own it.
288
+ *
289
+ * The charge follows write-root coverage across the whole wave, not just across
290
+ * the members that declared the check: a live sibling that declared no check, or
291
+ * whose own worker failed, still edited the shared checkout, so a named path
292
+ * inside its boundary and inside no declarer's is positive evidence that the
293
+ * declarers are innocent. That exculpation demands every named path be owned
294
+ * elsewhere; one path nobody claims leaves the failure unowned and every
295
+ * declarer is charged. When the owner is a member that declared no check the
296
+ * charge set comes out empty, because a run has nothing to reject on for a check
297
+ * it never asked for; that is the attribution rule applied faithfully, and the
298
+ * alternative is rejecting a worker the evidence points away from, which is the
299
+ * defect this gate exists to remove.
300
+ *
301
+ * Exculpation always requires positive evidence, so a declarer that ran
302
+ * unconfined is charged unconditionally: with no boundary there is nothing to
303
+ * test the failing paths against, and it is the member most able to have broken
304
+ * the tree. `basis` is the weakest evidence behind the charge set, never the
305
+ * strongest, so `write_roots` on a receipt means every charged run has a named
306
+ * path inside its own declared boundary.
307
+ */
308
+ function attributeFailure(input: {
309
+ implicated: ReadonlyArray<string>;
310
+ declarers: ReadonlyArray<BatchVerificationParticipant>;
311
+ wave: ReadonlyArray<BatchVerificationParticipant>;
312
+ }): { charged: Set<string>; basis: RunHostVerificationAttribution["basis"]; decisive: string[] } {
313
+ const declared = new Set(input.declarers.map((member) => member.runId));
314
+ const implicatedDeclarers = new Set<string>();
315
+ const unconfined = new Set<string>();
316
+ const decisive = new Set<string>();
317
+ for (const member of input.declarers) {
318
+ const boundary = memberBoundary(member);
319
+ if (boundary.length === 0) {
320
+ unconfined.add(member.runId);
145
321
  continue;
146
322
  }
147
- const outcome = await runCodeStep({
148
- stepId: `verification-${index + 1}-${resolvedCheck.check.replace(/[^a-z0-9._-]/giu, "_")}`,
149
- command,
150
- workspaceRoot: resolvedCheck.cwd,
151
- artifactDir: join(stateDir, "artifacts", input.runId, "verification"),
323
+ const hits = input.implicated.filter((path) => pathBoundaryCovers(boundary, path));
324
+ if (hits.length === 0) continue;
325
+ implicatedDeclarers.add(member.runId);
326
+ for (const hit of hits) decisive.add(hit);
327
+ }
328
+ const others = input.wave.filter((member) => !declared.has(member.runId));
329
+ const ownedElsewhere =
330
+ input.implicated.length > 0 &&
331
+ input.implicated.every((path) => others.some((member) => pathBoundaryCovers(memberBoundary(member), path)));
332
+ const localized = implicatedDeclarers.size > 0 || ownedElsewhere;
333
+ const charged = localized ? new Set(implicatedDeclarers) : new Set(declared);
334
+ for (const runId of unconfined) charged.add(runId);
335
+ return {
336
+ charged,
337
+ basis:
338
+ !localized || unconfined.size > 0
339
+ ? "unattributable"
340
+ : implicatedDeclarers.size > 0
341
+ ? "write_roots"
342
+ : "attributed_elsewhere",
343
+ decisive: [...decisive].sort(),
344
+ };
345
+ }
346
+
347
+ /**
348
+ * One settlement barrier per wave of a parallel dispatch batch.
349
+ *
350
+ * A check run while a sibling is still editing the shared checkout judges a tree
351
+ * neither worker authored: three coders on one kvlog batch (round 5, 2026-09-02)
352
+ * all sealed `host_verification_rejected` for one worker's broken test. Every
353
+ * live member parks at the verification step, each distinct resolved check runs
354
+ * once for the whole wave on the settled tree, and a failure is charged by
355
+ * write-root coverage across the wave.
356
+ *
357
+ * Membership is what is LIVE, never what was requested. A run still queued for
358
+ * capacity holds no lease and cannot write, and waiting on it would deadlock
359
+ * every batch larger than `fleet.concurrency`: parked members keep their lease
360
+ * until dispatch finalization ends (`extension.ts:5720`), so the queued member's
361
+ * `admit` would time out (`admission.ts:244-291`) and take the whole batch down
362
+ * with it. Live-only membership still costs a queued member the difference
363
+ * between the first live member finishing and the last, charged against the same
364
+ * 60 s admission deadline (`extension.ts:2669`). That wait is not free: a batch
365
+ * whose first member finishes inside the deadline and whose last does not now
366
+ * expires the queued member's `admit`, and `dispatchBatch` aborts every already
367
+ * dispatched run when one member's admission throws (`extension.ts:6197-6205`).
368
+ * Releasing the lease before parking would let a fresh writer into the checkout
369
+ * the settlement is about to judge, which is the defect itself, so the wait
370
+ * stands until the lease lifecycle is restructured.
371
+ *
372
+ * The gate is multi-shot: a batch larger than the effective capacity admits in
373
+ * waves, and each wave forms its own barrier from the members live at that
374
+ * moment. Latching after the first settlement would drop every later member onto
375
+ * the per-run path and reproduce the original defect verbatim, since those
376
+ * members are admitted together and would run the shared check concurrently on
377
+ * the checkout their siblings are still editing.
378
+ *
379
+ * One narrow window survives, and it is the reason `live()` registers as early
380
+ * as the worker spawn: a member that goes live WHILE a wave's checks are
381
+ * executing joins the next wave, so its edits can land in the tree the running
382
+ * check is judging. Reaching it takes either a lease freed mid-settlement, which
383
+ * means a sibling whose finalization failed before the barrier, or a member of
384
+ * `dispatchBatch`'s sequential loop (`extension.ts:6194`) whose worker had not
385
+ * spawned yet when every earlier member had already finished. The next wave
386
+ * re-runs the check on the settled tree, so a stale verdict is bounded to the
387
+ * one wave that raced.
388
+ */
389
+ export function createBatchVerificationGate(
390
+ options: { stateDir?: string; env?: NodeJS.ProcessEnv } = {},
391
+ ): BatchVerificationGate {
392
+ const stateDir = options.stateDir ?? clioStateDir();
393
+ const env = options.env ?? process.env;
394
+ const liveMembers = new Set<string>();
395
+ const parked = new Map<string, ParkedMember>();
396
+ let settling = false;
397
+
398
+ const perRun = (participant: BatchVerificationParticipant): Promise<RunHostVerification | undefined> =>
399
+ runHostVerification({
400
+ runId: participant.runId,
401
+ request: participant.request,
402
+ workerSuccessful: participant.workerSuccessful,
403
+ stateDir,
152
404
  env,
405
+ ...(participant.onDiagnostic !== undefined ? { onDiagnostic: participant.onDiagnostic } : {}),
153
406
  });
154
- const artifactPath = outcome.record.artifactPaths[0];
155
- const check: RunHostVerificationCheck = {
156
- check: resolvedCheck.check,
157
- argv: [...outcome.record.argv],
158
- cwd: outcome.record.cwd,
159
- exitCode: outcome.record.exitCode,
160
- durationMs: outcome.record.durationMs,
161
- memo: false,
162
- outputTail: outputTail(outcome.report.outputExcerpt),
163
- ...(artifactPath !== undefined ? { artifactPath } : {}),
164
- };
165
- results.push(check);
166
- if (check.exitCode === 0 && key !== null) {
167
- try {
168
- storeMemoEntry(stateDir, { key, runId: input.runId, check });
169
- } catch (error) {
170
- input.onDiagnostic?.(error);
407
+
408
+ /** Today's value for a member that contributes no check; runs no command. */
409
+ const nothingToRun = (participant: BatchVerificationParticipant): RunHostVerification | undefined => {
410
+ const checks = participant.request.resolvedVerification;
411
+ if (checks === undefined || checks.length === 0) return undefined;
412
+ return { status: "skipped", reason: "worker_not_successful", checks: [] };
413
+ };
414
+
415
+ async function settleBatch(wave: ReadonlyArray<ParkedMember>): Promise<void> {
416
+ const members = wave.map((entry) => entry.participant);
417
+ const contributors = members.filter(
418
+ (member) => member.workerSuccessful && (member.request.resolvedVerification?.length ?? 0) > 0,
419
+ );
420
+ const distinct = new Map<
421
+ string,
422
+ { resolvedCheck: ResolvedCheck; owner: BatchVerificationParticipant; index: number }
423
+ >();
424
+ for (const member of contributors) {
425
+ for (const resolvedCheck of member.request.resolvedVerification ?? []) {
426
+ const key = checkDedupeKey(resolvedCheck);
427
+ if (!distinct.has(key)) distinct.set(key, { resolvedCheck, owner: member, index: distinct.size });
171
428
  }
172
429
  }
430
+ const ran = new Map<string, { check: RunHostVerificationCheck; owner: string; outputExcerpt: string }>();
431
+ for (const [key, entry] of distinct) {
432
+ const outcome = await runResolvedCheck({
433
+ runId: entry.owner.runId,
434
+ index: entry.index,
435
+ resolvedCheck: entry.resolvedCheck,
436
+ stateDir,
437
+ env,
438
+ // The owning member's callback, because the artifact directory is
439
+ // named for that same run and the diagnostic text is closed over the
440
+ // run id it was built for (`extension.ts:5534`); any other member's
441
+ // callback would name a run whose artifacts the failure is not under.
442
+ ...(entry.owner.onDiagnostic !== undefined ? { onDiagnostic: entry.owner.onDiagnostic } : {}),
443
+ });
444
+ ran.set(key, { check: outcome.check, owner: entry.owner.runId, outputExcerpt: outcome.outputExcerpt });
445
+ }
446
+ const attribution: RunHostVerificationAttribution[] = [];
447
+ const chargedByKey = new Map<string, Set<string>>();
448
+ for (const [key, entry] of ran) {
449
+ if (entry.check.exitCode === 0) continue;
450
+ const declarers = contributors.filter((member) =>
451
+ (member.request.resolvedVerification ?? []).some((candidate) => checkDedupeKey(candidate) === key),
452
+ );
453
+ const implicated = implicatedPaths(entry.outputExcerpt, entry.check.cwd);
454
+ const verdict = attributeFailure({ implicated, declarers, wave: members });
455
+ chargedByKey.set(key, verdict.charged);
456
+ const decisive = new Set(verdict.decisive);
457
+ attribution.push({
458
+ check: entry.check.check,
459
+ // The paths that decided the charge lead the capped list. A large
460
+ // suite names more than 32 files and the sealed evidence has to
461
+ // contain the path a receipt was charged on, or it documents nothing.
462
+ implicated: [...verdict.decisive, ...implicated.filter((path) => !decisive.has(path))].slice(
463
+ 0,
464
+ IMPLICATED_PATH_CAP,
465
+ ),
466
+ charged: [...verdict.charged].sort(),
467
+ basis: verdict.basis,
468
+ });
469
+ }
470
+ attribution.sort((first, second) => (first.check < second.check ? -1 : first.check > second.check ? 1 : 0));
471
+ for (const entry of wave) {
472
+ const member = entry.participant;
473
+ if (!contributors.includes(member)) {
474
+ entry.settle(nothingToRun(member));
475
+ continue;
476
+ }
477
+ const own: RunHostVerificationCheck[] = [];
478
+ let rejected = false;
479
+ let unimplicated = false;
480
+ for (const resolvedCheck of member.request.resolvedVerification ?? []) {
481
+ const key = checkDedupeKey(resolvedCheck);
482
+ const shared = ran.get(key);
483
+ if (shared === undefined) continue;
484
+ own.push(
485
+ shared.owner === member.runId || shared.check.evidenceRunId !== undefined
486
+ ? { ...shared.check, argv: [...shared.check.argv] }
487
+ : { ...shared.check, argv: [...shared.check.argv], evidenceRunId: shared.owner },
488
+ );
489
+ if (shared.check.exitCode === 0) continue;
490
+ if (chargedByKey.get(key)?.has(member.runId) === true) rejected = true;
491
+ else unimplicated = true;
492
+ }
493
+ entry.settle({
494
+ // `verified` states that every declared check passed, which is what
495
+ // `trust-status.ts:619` certifies and what the board and
496
+ // `worker-evidence.ts:161` print. An exculpated member's checks array
497
+ // still carries a non-zero exit code, so it seals its own status
498
+ // instead of borrowing that claim.
499
+ status: rejected ? "rejected" : unimplicated ? "not_implicated" : "verified",
500
+ ...(!rejected && unimplicated ? { reason: "batch_settled_not_implicated" } : {}),
501
+ checks: own,
502
+ strategy: "batch-settled",
503
+ // Copied per receipt so no two members of the batch share a mutable array.
504
+ ...(attribution.length > 0
505
+ ? {
506
+ attribution: attribution.map((record) => ({
507
+ ...record,
508
+ implicated: [...record.implicated],
509
+ charged: [...record.charged],
510
+ })),
511
+ }
512
+ : {}),
513
+ });
514
+ }
515
+ }
516
+
517
+ function maybeSettle(): void {
518
+ if (settling || parked.size === 0) return;
519
+ for (const runId of liveMembers) {
520
+ if (!parked.has(runId)) return;
521
+ }
522
+ settling = true;
523
+ // The wave closes here. Its members leave `liveMembers` so a member that
524
+ // arrives during the settlement forms the next barrier instead of joining
525
+ // one whose checks are already executing.
526
+ const wave = [...parked.values()];
527
+ for (const runId of parked.keys()) liveMembers.delete(runId);
528
+ parked.clear();
529
+ void settleBatch(wave)
530
+ .catch(async (error) => {
531
+ // The barrier must never be the reason a receipt cannot seal, so a
532
+ // member whose own checks still run gets today's per-run result. A
533
+ // member whose per-run attempt throws the same way takes the throw:
534
+ // swallowing it would seal a run that declared a check it never
535
+ // executed as `host_verification=not_requested` and succeeded, while
536
+ // the identical single-task dispatch fails the run.
537
+ for (const entry of wave) {
538
+ entry.participant.onDiagnostic?.(error);
539
+ try {
540
+ entry.settle(await perRun(entry.participant));
541
+ } catch (fallbackError) {
542
+ entry.fail(fallbackError);
543
+ }
544
+ }
545
+ })
546
+ .finally(() => {
547
+ settling = false;
548
+ maybeSettle();
549
+ });
173
550
  }
551
+
174
552
  return {
175
- status: results.every((check) => check.exitCode === 0) ? "verified" : "rejected",
176
- checks: results,
553
+ live(runId) {
554
+ liveMembers.add(runId);
555
+ },
556
+ abandon(runId) {
557
+ // Dropping the id out of `liveMembers` rather than remembering it in a
558
+ // second set keeps the membership of a later wave exact: the same run
559
+ // abandons again when its finalPromise settles, long after its own wave.
560
+ if (parked.has(runId) || !liveMembers.delete(runId)) return;
561
+ maybeSettle();
562
+ },
563
+ arrive(input) {
564
+ liveMembers.add(input.runId);
565
+ // The executor runs synchronously, so the member is registered before
566
+ // arrive() yields and two concurrent arrivals cannot miss each other.
567
+ const parkedPromise = new Promise<RunHostVerification | undefined>((settle, fail) => {
568
+ parked.set(input.runId, { participant: input, settle, fail });
569
+ });
570
+ maybeSettle();
571
+ return parkedPromise;
572
+ },
177
573
  };
178
574
  }
@@ -7,6 +7,16 @@ export function renderDispatchIntentRequirements(intent: DispatchIntent | undefi
7
7
  "# Declared Result Requirements",
8
8
  "These entries are requirements to satisfy and verify. They are not evidence that an output exists or a check passed.",
9
9
  ];
10
+ // A run confined to write roots has no bash or verify tool: the rail cannot
11
+ // police a shell, so it is not offered. Left unsaid, a worker told to "run
12
+ // the tests" spent 40 code_nav calls looking for a way to run them and
13
+ // exhausted its budget before touching the source (kvlog exercise, r5).
14
+ if (intent.writeRoots.length > 0) {
15
+ lines.push(
16
+ "",
17
+ "This run is confined to its write roots and has no bash or verify tool, so you cannot run tests, scripts, or the checks below yourself. Write the code and the tests, re-read them, and report what you wrote; the host runs the declared checks after you finish and records the result on the receipt.",
18
+ );
19
+ }
10
20
  if (intent.expectedOutputs.length > 0) {
11
21
  lines.push("", "Expected outputs:", ...intent.expectedOutputs.map((output) => `- ${output}`));
12
22
  }
@@ -135,6 +135,14 @@ function normalizePathList(
135
135
  }
136
136
  const normalized: string[] = [];
137
137
  for (const [index, entry] of value.entries()) {
138
+ // A scope entry of "." or "./" names the repository root, which is what
139
+ // an empty scope list already means. Local models write it to say "the
140
+ // whole repository" and then spend a round on the rejection, so it is
141
+ // read as that rather than refused; an output path must still name a
142
+ // file, so the leniency stops at scope fields.
143
+ if (normalizeEntry === normalizeScopePathEntry && typeof entry === "string" && /^\.\/?$/u.test(entry.trim())) {
144
+ continue;
145
+ }
138
146
  const result = normalizeEntry(entry, field, index);
139
147
  if (typeof result !== "string") return result;
140
148
  normalized.push(result);
@@ -286,10 +294,19 @@ export function normalizeDispatchIntent(
286
294
  }
287
295
  const check = entry.check.trim();
288
296
  const declared = checks.get(check);
297
+ // The word a model writes to say "no verification". It is not a check
298
+ // id, and refusing it cost a dispatch round every time it appeared, so
299
+ // it reads as the empty declaration it means unless the project really
300
+ // declared a check by that name.
301
+ if (declared === undefined && check.toLowerCase() === "none") continue;
289
302
  if (declared === undefined) {
303
+ // The model that hits this most often has put a shell command here
304
+ // ("git diff src/x.ts"), so the message has to say what an entry is
305
+ // and offer the move that always works: leave verification out and
306
+ // run the check after the receipt.
290
307
  return fail(
291
308
  "verification_check_undeclared",
292
- `verification check '${check}' is undeclared; add a package.json verification script or .clio-coder/verifiers.yaml entry`,
309
+ `verification check '${check}' is undeclared: intent.verification takes only check ids that verify() lists (package.json verification scripts or .clio-coder/verifiers.yaml entries), never a shell command; omit verification and run the check yourself after the receipt, or declare the check first`,
293
310
  );
294
311
  }
295
312
  if (