@iowarp/clio-coder 0.4.1 → 0.4.2

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 (437) hide show
  1. package/CHANGELOG.md +92 -0
  2. package/CONTRIBUTING.md +59 -36
  3. package/README.md +404 -472
  4. package/SECURITY.md +2 -1
  5. package/dist/{acp-ZILU3AUO.js → acp-TMDQZDIG.js} +7 -7
  6. package/dist/{agents-HYWGBGQR.js → agents-5N5NG3XG.js} +28 -28
  7. package/dist/assets/codewiki.json +1 -1
  8. package/dist/{auth-N3QT7CBO.js → auth-Z5CCBXKQ.js} +8 -9
  9. package/dist/{builtins-UJLMOVOV.js → builtins-K6TNDT24.js} +4 -4
  10. package/dist/{chunk-GVQJ5CCZ.js → chunk-2HFQNRV3.js} +7 -7
  11. package/dist/{chunk-QMXC4JB7.js → chunk-2NHR3NAY.js} +163 -1401
  12. package/dist/chunk-2X4RYJTJ.js +39 -0
  13. package/dist/{chunk-Y45G3AXC.js → chunk-2Z2IKEXI.js} +6 -10
  14. package/dist/{chunk-EIMVLWB3.js → chunk-34BHNEE3.js} +7 -3
  15. package/dist/{chunk-GIZNH63R.js → chunk-35MSIRKH.js} +9 -4
  16. package/dist/chunk-3EBYEESD.js +314 -0
  17. package/dist/{chunk-CTJ4RNAA.js → chunk-3F7VUY77.js} +2 -2
  18. package/dist/{chunk-AP73CFDC.js → chunk-3KIPBMUA.js} +2 -2
  19. package/dist/{chunk-J5LZHVIT.js → chunk-3M6DQK6S.js} +113 -35
  20. package/dist/{chunk-VEGN6WIQ.js → chunk-462T4EGZ.js} +2 -2
  21. package/dist/{chunk-AFKWHWXF.js → chunk-4JDLP6ZS.js} +33 -16
  22. package/dist/{chunk-6FN3E6KX.js → chunk-4O6MANBS.js} +2 -2
  23. package/dist/{chunk-AKB4GYDL.js → chunk-54ODD65L.js} +5 -5
  24. package/dist/{chunk-BBTJOK6Y.js → chunk-5KW52TEP.js} +3 -3
  25. package/dist/{chunk-6CCS4G3W.js → chunk-5PFYMY2V.js} +2 -2
  26. package/dist/chunk-77QIVUZB.js +1334 -0
  27. package/dist/{chunk-7OBGU7UB.js → chunk-7BHIY2MW.js} +7 -13
  28. package/dist/{chunk-3QSOM6PA.js → chunk-AZ4WMN4W.js} +2 -2
  29. package/dist/{chunk-6NJQITNH.js → chunk-B74PXLU7.js} +6 -3
  30. package/dist/{chunk-R23Z6K6I.js → chunk-B7HM5Z7T.js} +15 -15
  31. package/dist/{chunk-R32CLGZ6.js → chunk-BO7Y52RY.js} +81 -20
  32. package/dist/{chunk-UEDMSP56.js → chunk-BYMNWQ7O.js} +123 -148
  33. package/dist/{chunk-ZJLUDYFY.js → chunk-CRFOIAX3.js} +4 -4
  34. package/dist/{chunk-2NM363SV.js → chunk-CYZW7JHJ.js} +7 -7
  35. package/dist/{chunk-6HMJX2VU.js → chunk-DYHAXKHD.js} +38 -10
  36. package/dist/{chunk-THYWACCR.js → chunk-DZAW46HP.js} +3 -3
  37. package/dist/{chunk-FYUN5KZ3.js → chunk-DZEK6CJN.js} +17 -17
  38. package/dist/{chunk-3I5NY75V.js → chunk-E7GT7O5N.js} +5 -5
  39. package/dist/{chunk-VKFQTNDV.js → chunk-F2I26BDK.js} +4 -4
  40. package/dist/{chunk-HLW2MRKE.js → chunk-F4EKGO4N.js} +3 -1
  41. package/dist/{chunk-IXJT6DCX.js → chunk-FVDGR2ZL.js} +3 -3
  42. package/dist/{chunk-TZSKNMZG.js → chunk-GTUD2WMY.js} +2 -1
  43. package/dist/{chunk-7EPLI7VL.js → chunk-HIICAHCJ.js} +2 -2
  44. package/dist/{chunk-E67WX76H.js → chunk-HKMD33FO.js} +29 -80
  45. package/dist/chunk-HLAFFSEK.js +360 -0
  46. package/dist/{chunk-UAPGZHYC.js → chunk-I64IFBLB.js} +9 -2
  47. package/dist/{chunk-XKA2ICR3.js → chunk-I66ZTYNP.js} +440 -175
  48. package/dist/{chunk-7PWAODYW.js → chunk-I7XBWTYH.js} +2 -2
  49. package/dist/{chunk-PVAMAVBB.js → chunk-IDNA72AH.js} +102 -2
  50. package/dist/{chunk-GCSMB2KY.js → chunk-IKOZFYBN.js} +1 -1
  51. package/dist/{chunk-2VG7KLYV.js → chunk-IKSLQ4XV.js} +5460 -3241
  52. package/dist/{chunk-QKIFBZKT.js → chunk-IMXMHHMQ.js} +166 -25
  53. package/dist/{chunk-74YWRRU5.js → chunk-JBCS7CRR.js} +2 -2
  54. package/dist/{chunk-BDPT6GTK.js → chunk-JWJGP5DQ.js} +2 -2
  55. package/dist/{chunk-K6BF4U2H.js → chunk-KKOJXO6R.js} +62 -14
  56. package/dist/chunk-KPXDY6QF.js +47 -0
  57. package/dist/{chunk-ABLSQ6JX.js → chunk-LJID3DYZ.js} +7 -1
  58. package/dist/{chunk-VKRH2TCS.js → chunk-M2DAX4F6.js} +2 -2
  59. package/dist/{chunk-6I5ILFOF.js → chunk-M2WXEHER.js} +2 -2
  60. package/dist/{chunk-YPI3QQCF.js → chunk-MCEPRMZW.js} +2 -4
  61. package/dist/{chunk-N5UK64DP.js → chunk-MCMZMDAC.js} +2 -2
  62. package/dist/{chunk-Y4CAGMM6.js → chunk-MNJGS2IN.js} +5 -6
  63. package/dist/{chunk-TVHHYFHE.js → chunk-NEDJ26B5.js} +2 -2
  64. package/dist/{chunk-U2WB7TZS.js → chunk-NMJXSHBJ.js} +97 -85
  65. package/dist/{chunk-HUAS7ITX.js → chunk-O3YUNJZ2.js} +13 -21
  66. package/dist/{chunk-MA3H6DM5.js → chunk-P75RZCJW.js} +25 -3
  67. package/dist/{chunk-IG7BCQBA.js → chunk-PGF63K6I.js} +2 -2
  68. package/dist/chunk-PJX3WQUQ.js +42 -0
  69. package/dist/{chunk-6DWBAZ5U.js → chunk-Q4XWMHX6.js} +4 -6
  70. package/dist/{chunk-OJTRZGR3.js → chunk-QQLGQY2A.js} +8 -8
  71. package/dist/{chunk-J4HBWF6Y.js → chunk-RLYRBIYQ.js} +115 -20
  72. package/dist/{chunk-NLFAQR7Z.js → chunk-S66XZJOF.js} +3 -23
  73. package/dist/{chunk-C537JADH.js → chunk-SSEYRH53.js} +6 -7
  74. package/dist/chunk-SZAA6XDG.js +30 -0
  75. package/dist/{chunk-MOPSG2X7.js → chunk-TPEQIQIE.js} +6 -6
  76. package/dist/{chunk-JA5QWE4Z.js → chunk-UBRFI4HS.js} +1879 -1650
  77. package/dist/{chunk-BTGG6BG2.js → chunk-UH347SHR.js} +154 -15
  78. package/dist/{chunk-5YHDIDBP.js → chunk-UH632ZYL.js} +2 -2
  79. package/dist/{chunk-BWW4HLO4.js → chunk-UXCU4E3T.js} +8 -6
  80. package/dist/{chunk-6VC4OV3Z.js → chunk-VIA6RFQZ.js} +3 -11
  81. package/dist/{chunk-ZAZB4JMW.js → chunk-VKPAQYEB.js} +27 -8
  82. package/dist/{chunk-UXN6JT4W.js → chunk-W4YEMFBX.js} +2 -2
  83. package/dist/{chunk-TD3PGPQA.js → chunk-W6NIE6OW.js} +2 -2
  84. package/dist/{chunk-TVH4ONAM.js → chunk-X7IARSHT.js} +3 -3
  85. package/dist/{chunk-PJJ6MY27.js → chunk-XE3PCIXH.js} +3 -3
  86. package/dist/{chunk-FEFIFZTL.js → chunk-XGDPUNND.js} +2 -2
  87. package/dist/{chunk-SCYB3HA4.js → chunk-XOXV5GKE.js} +51 -16
  88. package/dist/{chunk-QTFGO774.js → chunk-XQRY4DTA.js} +24 -11
  89. package/dist/{chunk-BJGUKIG4.js → chunk-YJISEZKC.js} +2 -2
  90. package/dist/{chunk-GPPB3JBE.js → chunk-ZGNYYXQ6.js} +2 -2
  91. package/dist/{chunk-SINK3QR6.js → chunk-ZNT2M6TG.js} +7 -7
  92. package/dist/{chunk-7RY5VZPH.js → chunk-ZW4HH5JJ.js} +6 -6
  93. package/dist/cli/index.js +33 -32
  94. package/dist/{clio-IT3G3VQH.js → clio-7VB377CC.js} +7 -7
  95. package/dist/{code-nav-RK6S7F6E.js → code-nav-YVLCYA7V.js} +85 -17
  96. package/dist/{config-3QZRWZJF.js → config-4HVOS65E.js} +88 -43
  97. package/dist/{configure-FL7Y3KJF.js → configure-PIWO7B24.js} +10 -10
  98. package/dist/{context-5HE7ODYK.js → context-IYEHL3WQ.js} +33 -31
  99. package/dist/{context-XNHL75JV.js → context-KQYIWPWT.js} +47 -34
  100. package/dist/{context-KYQFRVDC.js → context-N6ZE3LGJ.js} +11 -11
  101. package/dist/{context-clear-N545L53A.js → context-clear-G4OGZJDS.js} +33 -31
  102. package/dist/{context-working-set-QHKXSV2F.js → context-working-set-BWLF6LJP.js} +7 -7
  103. package/dist/{dispatch-runner-RGIE5PCT.js → dispatch-runner-2QQAITS3.js} +38 -38
  104. package/dist/{docs-5NAF6AU7.js → docs-PD3EXDKU.js} +21 -20
  105. package/dist/{doctor-ZGPEGHIP.js → doctor-LHBD36VU.js} +23 -22
  106. package/dist/{eval-GXLL44RD.js → eval-C45FYRJ6.js} +21 -20
  107. package/dist/{eval-inventory-HBWSWQOK.js → eval-inventory-6DEJPLBF.js} +2 -2
  108. package/dist/{evidence-HWLBRH3Q.js → evidence-6SHONYAF.js} +30 -28
  109. package/dist/{evolve-FTZBMNVW.js → evolve-KRKMV72X.js} +30 -28
  110. package/dist/{extensions-VHRBEID7.js → extensions-KPZ2UHBB.js} +5 -3
  111. package/dist/{fleet-CKZHJWZJ.js → fleet-IVTCKDHT.js} +62 -61
  112. package/dist/{fleet-commands-EXDXBMV6.js → fleet-commands-EDWL3IT7.js} +5 -5
  113. package/dist/{fleet-decisions-OTHB6KRL.js → fleet-decisions-YP3YEFGK.js} +4 -4
  114. package/dist/{fleet-graph-YTEZUCUT.js → fleet-graph-ZFWKHY2M.js} +16 -14
  115. package/dist/{fleet-inspect-SS6YMDCK.js → fleet-inspect-FVUNCBML.js} +31 -29
  116. package/dist/{fleet-preflight-PBY4VYOM.js → fleet-preflight-UN5XED4R.js} +2 -2
  117. package/dist/{fleet-validate-KMEM5L3S.js → fleet-validate-XOWC4HSX.js} +17 -15
  118. package/dist/{fleet-verify-QD5M7E7Q.js → fleet-verify-UN3SODEL.js} +30 -28
  119. package/dist/{fleet-view-WAMJYNDT.js → fleet-view-TWHJKCN6.js} +31 -29
  120. package/dist/{init-5XQRBOFV.js → init-T2QORQ3Y.js} +50 -49
  121. package/dist/{interop-34TVO25M.js → interop-IN5I2A66.js} +5 -5
  122. package/dist/{library-3QY6KF57.js → library-LSCATDLZ.js} +15 -13
  123. package/dist/{memory-L4UTIIIW.js → memory-HYOKAGGJ.js} +31 -29
  124. package/dist/{models-ZVX3QOWE.js → models-2GPMFYCM.js} +22 -21
  125. package/dist/{monitor-CEKVSYTS.js → monitor-E4ASVUJH.js} +34 -32
  126. package/dist/{orchestrator-77BAP6BC.js → orchestrator-DDMPR3PY.js} +984 -583
  127. package/dist/{panes-7STHOAUJ.js → panes-E3RUXOW5.js} +4 -4
  128. package/dist/{panes-SHAUIRXY.js → panes-IXKLOKA2.js} +23 -8
  129. package/dist/{reset-EOLM7GVE.js → reset-OAQP3W4O.js} +4 -4
  130. package/dist/{resources-74GKTLSF.js → resources-OTRSN34L.js} +15 -13
  131. package/dist/{run-HBAUJNNZ.js → run-5DEYH5QK.js} +60 -59
  132. package/dist/{share-G3APVLVP.js → share-IHWTLO3M.js} +19 -15
  133. package/dist/{skills-35HHUKCR.js → skills-IYMXMKW4.js} +17 -15
  134. package/dist/{skills-eval-QN4HSHDC.js → skills-eval-DROHSJAR.js} +36 -36
  135. package/dist/{skills-inventory-J357J34F.js → skills-inventory-D7X4L4ZX.js} +15 -13
  136. package/dist/{slash-commands-JZZCQA32.js → slash-commands-QBM7UZ3B.js} +21 -18
  137. package/dist/{steer-XAVHJM22.js → steer-Z5DO23FJ.js} +2 -2
  138. package/dist/{targets-DSM6CY3M.js → targets-P2FUC4IL.js} +25 -28
  139. package/dist/{terminal-lease-JOPFUVEM.js → terminal-lease-YREJ3JX2.js} +5 -5
  140. package/dist/{tools-MKNWVPBH.js → tools-5B7RO6MV.js} +4 -4
  141. package/dist/{trace-ECQ7TIYZ.js → trace-YMGMUM6A.js} +55 -7
  142. package/dist/{upgrade-H7TOM7YL.js → upgrade-PXK3S2YM.js} +11 -9
  143. package/dist/{usage-X52N3IDJ.js → usage-ME5MPXGX.js} +36 -34
  144. package/dist/{verifiers-EJTVVSMA.js → verifiers-BVZ7IWOO.js} +5 -5
  145. package/dist/{verify-YJL6XET2.js → verify-5K7ZKQFC.js} +4 -4
  146. package/dist/{web-fetch-MPIFL3LL.js → web-fetch-MPARV2K7.js} +2 -2
  147. package/dist/{wiki-generate-4NDZTQ4B.js → wiki-generate-F5W5QTYY.js} +48 -47
  148. package/dist/{with-panes-OBOBFIIR.js → with-panes-BYOJCLAM.js} +51 -255
  149. package/dist/worker/entry.js +45 -30
  150. package/docs/README.md +176 -81
  151. package/docs/{acp.md → architecture/acp.md} +36 -20
  152. package/docs/{alcf-provider.md → architecture/alcf-provider.md} +8 -5
  153. package/docs/{architecture.md → architecture/architecture.md} +43 -22
  154. package/docs/{artifact-placement.md → architecture/artifact-placement.md} +26 -23
  155. package/docs/architecture/artifact-versions.md +90 -0
  156. package/docs/{capacity-and-scheduling.md → architecture/capacity-and-scheduling.md} +26 -13
  157. package/docs/{context-engine.md → architecture/context-engine.md} +25 -25
  158. package/docs/{context-working-set.md → architecture/context-working-set.md} +13 -10
  159. package/docs/{dispatch-architecture-rationale.md → architecture/dispatch-architecture-rationale.md} +12 -9
  160. package/docs/{dispatch-typed-intent.md → architecture/dispatch-typed-intent.md} +68 -46
  161. package/docs/{evidence-and-memory.md → architecture/evidence-and-memory.md} +23 -16
  162. package/docs/{middleware-and-components.md → architecture/middleware-and-components.md} +11 -5
  163. package/docs/{model-catalog.md → architecture/model-catalog.md} +40 -17
  164. package/docs/{observability.md → architecture/observability.md} +26 -13
  165. package/docs/{pi-boundary.md → architecture/pi-boundary.md} +24 -11
  166. package/docs/{prompt-envelope-and-tools.md → architecture/prompt-envelope-and-tools.md} +55 -20
  167. package/docs/{provider-adapter-cookbook.md → architecture/provider-adapter-cookbook.md} +35 -24
  168. package/docs/{safety-model.md → architecture/safety-model.md} +20 -15
  169. package/docs/{session-lifecycle.md → architecture/session-lifecycle.md} +8 -5
  170. package/docs/architecture/time-conventions.md +125 -0
  171. package/docs/{trace-store.md → architecture/trace-store.md} +13 -5
  172. package/docs/{tui-design.md → architecture/tui-design.md} +13 -13
  173. package/docs/{worker-dispatch-mechanics.md → architecture/worker-dispatch-mechanics.md} +27 -30
  174. package/docs/{built-in-agents.md → guide/built-in-agents.md} +50 -34
  175. package/docs/{commands-and-modes.md → guide/commands-and-modes.md} +65 -60
  176. package/docs/{configuration-and-targets.md → guide/configuration-and-targets.md} +227 -289
  177. package/docs/guide/configuration-reference.md +1158 -0
  178. package/docs/{environment-variables.md → guide/environment-variables.md} +31 -28
  179. package/docs/{exit-codes-and-output.md → guide/exit-codes-and-output.md} +6 -3
  180. package/docs/{extensions-and-sharing.md → guide/extensions-and-sharing.md} +41 -14
  181. package/docs/{fleet-dispatch.md → guide/fleet-dispatch.md} +39 -43
  182. package/docs/{glossary.md → guide/glossary.md} +14 -11
  183. package/docs/{installation-and-lifecycle.md → guide/installation-and-lifecycle.md} +44 -13
  184. package/docs/guide/panes-and-files.md +290 -0
  185. package/docs/{proactive-memory.md → guide/proactive-memory.md} +79 -66
  186. package/docs/{resource-library.md → guide/resource-library.md} +13 -4
  187. package/docs/{skills-marketplace.md → guide/skills-marketplace.md} +7 -3
  188. package/docs/{tool-usage.md → guide/tool-usage.md} +87 -23
  189. package/docs/{troubleshooting.md → guide/troubleshooting.md} +9 -4
  190. package/docs/{config-knobs-audit.md → history/config-knobs-audit.md} +11 -11
  191. package/docs/{release-cut-checklist.md → history/release-cut-checklist.md} +29 -2
  192. package/docs/{development-pipeline.md → process/development-pipeline.md} +24 -26
  193. package/docs/process/documentation-coverage.md +100 -0
  194. package/docs/process/documentation-guide.md +187 -0
  195. package/docs/{eval-runner.md → process/eval-runner.md} +41 -50
  196. package/docs/{evals-internal.md → process/evals-internal.md} +10 -10
  197. package/docs/{evolution.md → process/evolution.md} +2 -2
  198. package/docs/{fleet-demo-runbook.md → process/fleet-demo-runbook.md} +11 -7
  199. package/docs/{git-commit-provenance.md → process/git-commit-provenance.md} +11 -4
  200. package/docs/{performance-methodology.md → process/performance-methodology.md} +87 -69
  201. package/docs/{scientific-validation.md → process/scientific-validation.md} +4 -4
  202. package/evals/README.md +2 -2
  203. package/package.json +9 -7
  204. package/skills/README.md +46 -37
  205. package/skills/coding/ast-grep/SKILL.md +2 -2
  206. package/skills/coding/coding-standards/SKILL.md +2 -2
  207. package/skills/coding/prototype/SKILL.md +2 -2
  208. package/skills/coding/tdd/SKILL.md +2 -2
  209. package/skills/context/context-handoff/SKILL.md +2 -2
  210. package/skills/context/context-prime/SKILL.md +2 -2
  211. package/skills/git/file-ticket/SKILL.md +2 -2
  212. package/skills/git/fix-issue/SKILL.md +3 -3
  213. package/skills/git/resolve-merge-conflicts/SKILL.md +2 -2
  214. package/skills/git/ship/SKILL.md +2 -2
  215. package/skills/git/worktree-create/SKILL.md +2 -2
  216. package/skills/git/worktree-merge/SKILL.md +2 -2
  217. package/skills/meta/clio-coder-dev/SKILL.md +9 -5
  218. package/skills/meta/clio-coder-dev/evals.md +3 -2
  219. package/skills/meta/clio-coder-test/SKILL.md +102 -95
  220. package/skills/meta/clio-coder-test/evals.md +9 -4
  221. package/skills/meta/clio-coder-test/references/harness.md +100 -124
  222. package/skills/meta/clio-coder-test/references/test-map.md +77 -50
  223. package/skills/meta/credentials/SKILL.md +2 -2
  224. package/skills/meta/find-skills/SKILL.md +2 -2
  225. package/skills/meta/herdr/SKILL.md +2 -2
  226. package/skills/meta/skill-craft/SKILL.md +22 -16
  227. package/skills/planning/architecture/SKILL.md +2 -2
  228. package/skills/planning/backlog/SKILL.md +2 -2
  229. package/skills/planning/prd/SKILL.md +2 -2
  230. package/skills/planning/product-intent/SKILL.md +2 -2
  231. package/skills/planning/tech-spec/SKILL.md +2 -2
  232. package/skills/registry.yaml +62 -62
  233. package/skills/research/arxiv-literature/SKILL.md +2 -2
  234. package/skills/research/experiment-protocol/SKILL.md +2 -2
  235. package/skills/research/scientific-debugging/SKILL.md +2 -2
  236. package/skills/research/scientific-modernization/SKILL.md +2 -2
  237. package/skills/skill-marketplace.json +62 -62
  238. package/skills/workflow/cut-it/SKILL.md +2 -2
  239. package/skills/workflow/design-council/SKILL.md +2 -2
  240. package/skills/workflow/grill-me/SKILL.md +2 -2
  241. package/skills/workflow/workflow-distiller/SKILL.md +2 -2
  242. package/src/cli/args.ts +2 -2
  243. package/src/cli/bootstrap-generate.ts +1 -1
  244. package/src/cli/config-inspect.ts +65 -12
  245. package/src/cli/configure.ts +0 -4
  246. package/src/cli/docs.ts +22 -14
  247. package/src/cli/doctor-naming.ts +5 -5
  248. package/src/cli/doctor-toolchain.ts +3 -3
  249. package/src/cli/eval.ts +1 -2
  250. package/src/cli/extensions.ts +2 -1
  251. package/src/cli/fleet.ts +1 -1
  252. package/src/cli/index.ts +2 -1
  253. package/src/cli/internal-dispatch.ts +3 -4
  254. package/src/cli/panes.ts +19 -5
  255. package/src/cli/run.ts +2 -2
  256. package/src/cli/share.ts +5 -1
  257. package/src/cli/skills-eval.ts +3 -3
  258. package/src/cli/targets.ts +2 -6
  259. package/src/cli/trace.ts +55 -4
  260. package/src/cli/wiki-generate.ts +1 -1
  261. package/src/core/artifact-paths.ts +1 -1
  262. package/src/core/bash-exec.ts +131 -86
  263. package/src/core/bus-events.ts +51 -6
  264. package/src/core/config.ts +5 -1
  265. package/src/core/defaults.ts +7 -4
  266. package/src/core/dispatch-outcome.ts +16 -0
  267. package/src/core/guardrails.ts +10 -49
  268. package/src/core/prompt-hint.ts +9 -0
  269. package/src/domains/agents/builtins/architect.md +2 -3
  270. package/src/domains/agents/builtins/coder.md +3 -2
  271. package/src/domains/agents/builtins/debugger.md +2 -2
  272. package/src/domains/agents/builtins/documenter.md +2 -2
  273. package/src/domains/agents/builtins/git-master.md +1 -1
  274. package/src/domains/agents/builtins/oracle.md +1 -1
  275. package/src/domains/agents/builtins/provenance.md +1 -1
  276. package/src/domains/agents/builtins/researcher.md +1 -1
  277. package/src/domains/agents/builtins/scout.md +1 -1
  278. package/src/domains/agents/builtins/tester.md +2 -2
  279. package/src/domains/agents/builtins/verifier.md +2 -2
  280. package/src/domains/agents/builtins/wiki-writer.md +1 -1
  281. package/src/domains/agents/catalog.ts +12 -14
  282. package/src/domains/agents/contract.ts +2 -0
  283. package/src/domains/agents/extension.ts +23 -1
  284. package/src/domains/config/keybindings.ts +8 -0
  285. package/src/domains/context/extension.ts +0 -3
  286. package/src/domains/context/working-set/path-index.ts +1 -0
  287. package/src/domains/dispatch/capability-match.ts +10 -0
  288. package/src/domains/dispatch/extension.ts +105 -22
  289. package/src/domains/dispatch/host-verification.ts +435 -39
  290. package/src/domains/dispatch/intent-requirements.ts +10 -0
  291. package/src/domains/dispatch/intent.ts +18 -1
  292. package/src/domains/dispatch/path-scope.ts +235 -24
  293. package/src/domains/dispatch/run-event-journal.ts +4 -15
  294. package/src/domains/dispatch/state.ts +2 -3
  295. package/src/domains/dispatch/transport.ts +45 -21
  296. package/src/domains/dispatch/types.ts +55 -3
  297. package/src/domains/eval/artifacts/store.ts +5 -0
  298. package/src/domains/eval/store.ts +8 -1
  299. package/src/domains/evidence/trust-status.ts +10 -1
  300. package/src/domains/extensions/contract.ts +15 -1
  301. package/src/domains/extensions/discovery.ts +238 -41
  302. package/src/domains/extensions/extension.ts +105 -6
  303. package/src/domains/extensions/index.ts +24 -0
  304. package/src/domains/extensions/integrity.ts +189 -0
  305. package/src/domains/extensions/manager.ts +17 -1
  306. package/src/domains/extensions/resource-path.ts +27 -0
  307. package/src/domains/extensions/resources.ts +18 -38
  308. package/src/domains/extensions/snapshot-store.ts +39 -0
  309. package/src/domains/extensions/snapshot.ts +180 -0
  310. package/src/domains/extensions/state.ts +385 -57
  311. package/src/domains/extensions/types.ts +118 -1
  312. package/src/domains/lifecycle/migrations/2026-09-01-extension-install-digests.ts +27 -0
  313. package/src/domains/lifecycle/migrations/index.ts +2 -0
  314. package/src/domains/lifecycle/naming-resources.ts +19 -4
  315. package/src/domains/lifecycle/naming-yazi.ts +10 -5
  316. package/src/domains/middleware/contract.ts +26 -0
  317. package/src/domains/middleware/extension.ts +24 -24
  318. package/src/domains/middleware/hook-receipts.ts +27 -4
  319. package/src/domains/middleware/hooks-io.ts +65 -32
  320. package/src/domains/middleware/hooks.ts +64 -0
  321. package/src/domains/middleware/index.ts +28 -4
  322. package/src/domains/middleware/registrations.ts +326 -0
  323. package/src/domains/middleware/runtime.ts +28 -0
  324. package/src/domains/middleware/snapshot.ts +20 -7
  325. package/src/domains/mux/contract.ts +38 -0
  326. package/src/domains/mux/detect.ts +6 -13
  327. package/src/domains/mux/index.ts +1 -1
  328. package/src/domains/mux/operations.ts +44 -5
  329. package/src/domains/mux/yazi/assets/yazi.toml +2 -2
  330. package/src/domains/mux/yazi/session.ts +53 -4
  331. package/src/domains/mux/yazi/theme.ts +117 -17
  332. package/src/domains/observability/contract.ts +10 -11
  333. package/src/domains/observability/extension.ts +11 -3
  334. package/src/domains/observability/projection.ts +14 -90
  335. package/src/domains/observability/trace-store.ts +43 -7
  336. package/src/domains/prompts/compiler.ts +73 -53
  337. package/src/domains/prompts/contract.ts +15 -3
  338. package/src/domains/prompts/extension.ts +97 -9
  339. package/src/domains/prompts/fragments/identity/clio-worker.md +1 -3
  340. package/src/domains/prompts/fragments/identity/clio.md +6 -12
  341. package/src/domains/prompts/fragments/identity/docs-routing.md +1 -2
  342. package/src/domains/prompts/fragments/identity/self-awareness.md +3 -11
  343. package/src/domains/prompts/fragments/operating/contract.md +7 -15
  344. package/src/domains/prompts/fragments/operating/delegation.md +32 -34
  345. package/src/domains/prompts/fragments/operating/skills.md +10 -24
  346. package/src/domains/prompts/fragments/operating/worker.md +1 -8
  347. package/src/domains/providers/index.ts +1 -1
  348. package/src/domains/providers/model-runtime-capabilities.ts +85 -21
  349. package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +669 -104
  350. package/src/domains/providers/runtime-resolution.ts +31 -0
  351. package/src/domains/providers/runtimes/common/probe-helpers.ts +7 -2
  352. package/src/domains/providers/runtimes/local-native/llamacpp.ts +9 -1
  353. package/src/domains/providers/types/cost-provenance.ts +19 -0
  354. package/src/domains/providers/types/local-model-quirks.ts +85 -37
  355. package/src/domains/resources/skills/loader.ts +16 -19
  356. package/src/domains/safety/call-target.ts +1 -1
  357. package/src/domains/safety/loop-detector.ts +7 -4
  358. package/src/domains/session/task-board.ts +10 -9
  359. package/src/domains/share/archive.ts +164 -7
  360. package/src/engine/acp/server.ts +62 -9
  361. package/src/engine/apis/llamacpp-residency.ts +3 -4
  362. package/src/engine/apis/lmstudio.ts +3 -3
  363. package/src/engine/apis/ollama-native.ts +6 -6
  364. package/src/engine/apis/openai-completions.ts +28 -25
  365. package/src/engine/apis/output-budget.ts +8 -18
  366. package/src/engine/apis/residency.ts +8 -27
  367. package/src/engine/gemma-channel-filter.ts +19 -0
  368. package/src/engine/loop-guard.ts +92 -12
  369. package/src/engine/worker-runtime.ts +40 -11
  370. package/src/engine/worker-tools.ts +3 -1
  371. package/src/entry/extension-hook-sources.ts +28 -0
  372. package/src/entry/extension-reload.ts +309 -0
  373. package/src/entry/orchestrator.ts +59 -35
  374. package/src/interactive/application-controller.ts +2 -1
  375. package/src/interactive/bus-notices.ts +8 -1
  376. package/src/interactive/chat-loop-messages.ts +3 -13
  377. package/src/interactive/chat-loop.ts +10 -1
  378. package/src/interactive/chat-panel.ts +36 -13
  379. package/src/interactive/chat-renderer.ts +71 -7
  380. package/src/interactive/dispatch-board.ts +6 -11
  381. package/src/interactive/footer/widgets.ts +13 -0
  382. package/src/interactive/interactive-application.ts +39 -4
  383. package/src/interactive/interactive-input-runtime.ts +4 -0
  384. package/src/interactive/interactive-presentation.ts +2 -2
  385. package/src/interactive/interactive-slash-runtime.ts +2 -0
  386. package/src/interactive/overlays/extensions.ts +9 -1
  387. package/src/interactive/overlays/help-reference.ts +13 -0
  388. package/src/interactive/overlays/settings.ts +27 -16
  389. package/src/interactive/panes-runtime.ts +111 -35
  390. package/src/interactive/prompt-cache-identity.ts +88 -0
  391. package/src/interactive/slash-commands.ts +129 -14
  392. package/src/interactive/stream-pacing-policy.ts +0 -23
  393. package/src/interactive/turn-context.ts +30 -15
  394. package/src/interactive/yazi-bridge.ts +60 -6
  395. package/src/tools/agent-tools.ts +30 -1
  396. package/src/tools/artifact.ts +2 -2
  397. package/src/tools/ask-user.ts +3 -3
  398. package/src/tools/bash.ts +1 -1
  399. package/src/tools/bootstrap.ts +4 -0
  400. package/src/tools/builtin-tool-catalog.ts +52 -22
  401. package/src/tools/codewiki/code-nav-surface.ts +6 -0
  402. package/src/tools/codewiki/code-nav.ts +99 -13
  403. package/src/tools/context/docs-engine.ts +20 -7
  404. package/src/tools/context/index.ts +29 -12
  405. package/src/tools/core-bootstrap.ts +28 -6
  406. package/src/tools/credential-present.ts +1 -2
  407. package/src/tools/dispatch-arguments.ts +5 -1
  408. package/src/tools/dispatch-plan.ts +48 -4
  409. package/src/tools/dispatch-run-events.ts +1 -1
  410. package/src/tools/dispatch-schema.ts +338 -0
  411. package/src/tools/dispatch-types.ts +3 -0
  412. package/src/tools/dispatch.ts +9 -254
  413. package/src/tools/ledger.ts +3 -5
  414. package/src/tools/monitor-surface.ts +5 -13
  415. package/src/tools/observation.ts +4 -5
  416. package/src/tools/panes-surface.ts +4 -11
  417. package/src/tools/panes.ts +4 -2
  418. package/src/tools/policy.ts +15 -2
  419. package/src/tools/read.ts +5 -6
  420. package/src/tools/registry.ts +30 -7
  421. package/src/tools/result-shaping.ts +18 -14
  422. package/src/tools/steer-surface.ts +1 -1
  423. package/src/tools/tasks.ts +1 -1
  424. package/src/tools/truncate.ts +6 -5
  425. package/src/tools/verify/surface.ts +6 -12
  426. package/src/tools/web-fetch-surface.ts +1 -3
  427. package/dist/chunk-5QIAJV2D.js +0 -48
  428. package/dist/chunk-JZWT5J3Y.js +0 -814
  429. package/dist/chunk-K7VKOLQQ.js +0 -15
  430. package/dist/chunk-PMZCIOCJ.js +0 -25
  431. package/dist/chunk-SUW5DORT.js +0 -819
  432. package/dist/chunk-UOV2BYIW.js +0 -107
  433. package/dist/chunk-WR6U3OVP.js +0 -45
  434. package/docs/artifact-versions.md +0 -67
  435. package/docs/documentation-coverage.md +0 -46
  436. package/docs/documentation-guide.md +0 -167
  437. package/docs/time-conventions.md +0 -101
@@ -1,3 +1,4 @@
1
+ import { existsSync } from "node:fs";
1
2
  import {
2
3
  asDirectoryPathBoundary,
3
4
  normalizePathBoundaryEntry,
@@ -14,6 +15,7 @@ const POSIX_ABSOLUTE_TOKEN_RE = /(?:^|[\s("'])((?:\/[\w.~+-]+)+)/gu;
14
15
  const WINDOWS_ABSOLUTE_TOKEN_RE = /(?:^|[\s("'])([A-Za-z]:[\\/][^\s"']+)/gu;
15
16
  const BACKSLASH_PATH_RE = /\b[A-Za-z_.-][\w.-]*\\(?:(?:[\w.-]+\\)+[\w.-]+|[\w-]+\.[A-Za-z0-9]{1,8})\b/gu;
16
17
  const DOUBLE_SEPARATOR_PATH_RE = /\b[\w.-]+\/\/[\w./-]+/gu;
18
+ const PARENT_PREFIX_RE = /^(?:\.\.\/)+/u;
17
19
 
18
20
  export type DispatchPathProvenanceKind = "declared" | "derived" | "inferred";
19
21
  export type DispatchPathConfidence = "certain" | "high" | "medium" | "low";
@@ -49,11 +51,24 @@ export interface DispatchPathScopeProvenance {
49
51
  writeBoundaries: DispatchPathProvenanceEntry[];
50
52
  }
51
53
 
54
+ /**
55
+ * A prose token whose leading "../" run inference had to reinterpret, kept so
56
+ * the notice can name the raw token beside the scope it produced. `resolved` is
57
+ * the repository path the stripped remainder anchored to, or null when nothing
58
+ * under the dispatch root carried it and the token took no part in scope.
59
+ */
60
+ export interface DispatchInferredParentToken {
61
+ token: string;
62
+ resolved: string | null;
63
+ source: "task" | "briefing";
64
+ }
65
+
52
66
  export interface DispatchPathScope {
53
67
  source: "declared" | "inferred";
54
68
  workingContextPaths: ReadonlyArray<string>;
55
69
  writeBoundaries: ReadonlyArray<string>;
56
70
  inferredOnlyPaths: ReadonlyArray<string>;
71
+ parentTokens: ReadonlyArray<DispatchInferredParentToken>;
57
72
  provenance: DispatchPathScopeProvenance;
58
73
  }
59
74
 
@@ -64,6 +79,19 @@ export interface DeclaredScopeReplacementNotice {
64
79
  message: string;
65
80
  }
66
81
 
82
+ export interface InferredScopeParentTokenNotice {
83
+ code: "legacy_scope_inferred";
84
+ level: "warning";
85
+ paths: ReadonlyArray<{
86
+ path: string;
87
+ policy: "working-context";
88
+ provenance: "inferred";
89
+ source: "task" | "briefing";
90
+ confidence: "low";
91
+ }>;
92
+ message: string;
93
+ }
94
+
67
95
  export type DispatchPathScopeInferenceErrorCode = "legacy_scope_path_absolute" | "legacy_scope_path_malformed";
68
96
 
69
97
  export class DispatchPathScopeInferenceError extends Error {
@@ -139,19 +167,78 @@ export function declaredIntentPathProvenance(input: {
139
167
  return sortedEntries(entries);
140
168
  }
141
169
 
142
- function inferredPaths(req: Pick<DispatchRequest, "task" | "briefing">): string[] {
170
+ /** One prose token read as a repository path, as an anchored "../" quote, or as neither. */
171
+ type InferredPathToken =
172
+ | { kind: "token"; token: string }
173
+ | { kind: "anchored"; token: string; resolved: string }
174
+ | { kind: "dropped"; token: string };
175
+
176
+ function inferredPaths(
177
+ req: Pick<DispatchRequest, "task" | "briefing">,
178
+ root: string,
179
+ ): { paths: string[]; droppedTokens: string[] } {
143
180
  const paths = new Set<string>();
181
+ const droppedTokens = new Set<string>();
144
182
  const text = `${req.task}\n${req.briefing ?? ""}`;
145
183
  for (const match of text.matchAll(DISPATCH_PATH_TOKEN_RE)) {
146
- const token = inferredPathToken(match[0]);
184
+ const inferred = inferredPathToken(match[0], root);
185
+ if (inferred.kind === "dropped") {
186
+ droppedTokens.add(inferred.token);
187
+ continue;
188
+ }
189
+ const token = inferred.kind === "anchored" ? inferred.resolved : inferred.token;
147
190
  if (token.startsWith("http://") || token.startsWith("https://")) continue;
148
191
  paths.add(token);
149
192
  }
150
- return [...paths];
193
+ return { paths: [...paths], droppedTokens: [...droppedTokens] };
151
194
  }
152
195
 
153
- function inferredPathToken(token: string): string {
154
- return token.replace(/\.+$/u, "");
196
+ /**
197
+ * A leading "./" is how prose quotes an import specifier ("./parser.js"); it
198
+ * names the same repository path without the prefix, and the boundary grammar
199
+ * would otherwise refuse the whole dispatch for a dot segment.
200
+ *
201
+ * A leading "../" run is that same quote copied out of a file whose location
202
+ * this function never sees. Both callers, strictInferredPaths and
203
+ * inferredPaths, are handed the task or briefing text and nothing else, so the
204
+ * origin the run is measured against is unknowable here and no arithmetic on
205
+ * the run's length can decide whether it escapes. What is decidable is whether
206
+ * the remainder names something under the dispatch root, so the run is
207
+ * stripped and the remainder probed: "../src/store.js" quoted out of
208
+ * test/store.test.ts anchors to src/store.js, and "../../../etc/passwd"
209
+ * anchors to nothing in a checkout that holds no etc/passwd.
210
+ *
211
+ * That is a deliberate reading of issue #266, recorded here because it is the
212
+ * one place the choice is made. Criterion 1 ("never rejects the dispatch") and
213
+ * criterion 2 ("a prose token whose .. segments would leave the repository
214
+ * root is still refused") ask for opposite answers on a leading run, and only
215
+ * criterion 1 is decidable without an origin, so a run that names nothing is
216
+ * dropped rather than refused. Neither outcome widens authority: an inferred
217
+ * path selects project rules and compiles context but never becomes a write
218
+ * boundary, and an anchored remainder carries no ".." so path.resolve keeps it
219
+ * under the root. Both outcomes are named to the operator by
220
+ * inferredScopeParentTokenNotice, so the reinterpretation is never silent.
221
+ *
222
+ * The probe costs one existsSync per "../"-leading token (3 microseconds on a
223
+ * hit and 2 on a miss over 5,000 warm calls on this checkout) and no stat at
224
+ * all for the ordinary token, which the grammar matches dozens of per dispatch
225
+ * (the 27 tokens per task measured for REPORTABLE_OMITTED_PATH_RE below).
226
+ *
227
+ * A ".." or "." outside the leading run ("../src/../../b.ts", "../src/./b.ts")
228
+ * walks back out of a segment it already anchored, which is decidable without
229
+ * an origin, so it falls through to the boundary grammar and keeps its
230
+ * refusal, as does a run that leaves no remainder at all ("../..").
231
+ */
232
+ function inferredPathToken(raw: string, root: string): InferredPathToken {
233
+ const token = raw.replace(/^\.\//u, "").replace(/\.+$/u, "");
234
+ const parents = PARENT_PREFIX_RE.exec(token)?.[0];
235
+ if (parents === undefined) return { kind: "token", token };
236
+ const rest = token.slice(parents.length);
237
+ const segments = rest.split("/");
238
+ if (rest.length === 0 || segments.includes("..") || segments.includes(".")) return { kind: "token", token };
239
+ return existsSync(resolvePathBoundary(root, rest))
240
+ ? { kind: "anchored", token, resolved: rest }
241
+ : { kind: "dropped", token };
155
242
  }
156
243
 
157
244
  function failMalformedText(text: string, source: "task" | "briefing"): void {
@@ -188,18 +275,31 @@ function failMalformedText(text: string, source: "task" | "briefing"): void {
188
275
  function strictInferredPaths(
189
276
  text: string,
190
277
  source: "task" | "briefing",
191
- ): Array<{ path: string; evidence: DispatchPathProvenanceEvidence }> {
278
+ root: string,
279
+ ): {
280
+ paths: Array<{ path: string; evidence: DispatchPathProvenanceEvidence }>;
281
+ parentTokens: DispatchInferredParentToken[];
282
+ } {
192
283
  failMalformedText(text, source);
193
284
  const withoutUrls = text.replace(HTTP_URL_RE, (url) => " ".repeat(url.length));
194
285
  const evidence: DispatchPathProvenanceEvidence =
195
286
  source === "task"
196
287
  ? { provenance: "inferred", source, confidence: "medium", reason: "task_path_token" }
197
288
  : { provenance: "inferred", source, confidence: "low", reason: "briefing_path_token" };
198
- const result: Array<{ path: string; evidence: DispatchPathProvenanceEvidence }> = [];
289
+ const paths: Array<{ path: string; evidence: DispatchPathProvenanceEvidence }> = [];
290
+ const parentTokens: DispatchInferredParentToken[] = [];
199
291
  for (const match of withoutUrls.matchAll(DISPATCH_PATH_TOKEN_RE)) {
200
- const token = inferredPathToken(match[0]);
292
+ const inferred = inferredPathToken(match[0], root);
293
+ if (inferred.kind === "dropped") {
294
+ parentTokens.push({ token: inferred.token, resolved: null, source });
295
+ continue;
296
+ }
297
+ if (inferred.kind === "anchored") {
298
+ parentTokens.push({ token: inferred.token, resolved: inferred.resolved, source });
299
+ }
300
+ const token = inferred.kind === "anchored" ? inferred.resolved : inferred.token;
201
301
  try {
202
- result.push({ path: normalizePathBoundaryEntry(token), evidence });
302
+ paths.push({ path: normalizePathBoundaryEntry(token), evidence });
203
303
  } catch (error) {
204
304
  const code =
205
305
  error instanceof PathBoundaryError && error.code === "absolute"
@@ -213,7 +313,7 @@ function strictInferredPaths(
213
313
  );
214
314
  }
215
315
  }
216
- return result;
316
+ return { paths, parentTokens };
217
317
  }
218
318
 
219
319
  function legacyPathScope(req: DispatchRequest, cwd: string): DispatchPathScope {
@@ -229,13 +329,21 @@ function legacyPathScope(req: DispatchRequest, cwd: string): DispatchPathScope {
229
329
  addProvenance(workingEntries, root, writeEvidence);
230
330
  addProvenance(writeEntries, asDirectoryPathBoundary(resolvePathBoundary(cwd, root)), writeEvidence);
231
331
  }
232
- for (const candidate of strictInferredPaths(req.task, "task")) {
233
- addProvenance(workingEntries, candidate.path, candidate.evidence);
234
- }
332
+ // One map across both fields, first field winning: an orchestrator that
333
+ // restates the file it is asking about quotes the same specifier in the task
334
+ // and in the briefing, and the notice must name it once rather than spend two
335
+ // of its twelve render slots on the same token.
336
+ const parentTokens = new Map<string, DispatchInferredParentToken>();
337
+ const recordParentTokens = (entries: ReadonlyArray<DispatchInferredParentToken>): void => {
338
+ for (const entry of entries) if (!parentTokens.has(entry.token)) parentTokens.set(entry.token, entry);
339
+ };
340
+ const taskScope = strictInferredPaths(req.task, "task", cwd);
341
+ for (const candidate of taskScope.paths) addProvenance(workingEntries, candidate.path, candidate.evidence);
342
+ recordParentTokens(taskScope.parentTokens);
235
343
  if (req.briefing !== undefined) {
236
- for (const candidate of strictInferredPaths(req.briefing, "briefing")) {
237
- addProvenance(workingEntries, candidate.path, candidate.evidence);
238
- }
344
+ const briefingScope = strictInferredPaths(req.briefing, "briefing", cwd);
345
+ for (const candidate of briefingScope.paths) addProvenance(workingEntries, candidate.path, candidate.evidence);
346
+ recordParentTokens(briefingScope.parentTokens);
239
347
  }
240
348
  const workingContext = [...workingEntries.values()].map((entry) => ({
241
349
  path: entry.path,
@@ -250,6 +358,7 @@ function legacyPathScope(req: DispatchRequest, cwd: string): DispatchPathScope {
250
358
  workingContextPaths: workingContext.map((entry) => entry.path),
251
359
  writeBoundaries: writeBoundaries.map((entry) => entry.path),
252
360
  inferredOnlyPaths: [],
361
+ parentTokens: [...parentTokens.values()],
253
362
  provenance: {
254
363
  version: 1,
255
364
  mode: "legacy-inferred",
@@ -266,7 +375,15 @@ export function resolveDispatchPathScope(req: DispatchRequest): DispatchPathScop
266
375
 
267
376
  const declaredProvenance = declaredIntentPathProvenance(req.intent);
268
377
  const declaredPaths = declaredProvenance.map((entry) => entry.path);
269
- const inferredOnlyPaths = inferredPaths(req).filter((candidate) => !pathBoundaryCovers(declaredPaths, candidate));
378
+ const inferred = inferredPaths(req, cwd);
379
+ // A dropped token cannot be covered by a declaration, so it is always listed.
380
+ // An anchored one is listed under the path it anchored to and goes through
381
+ // the same coverage test the notice has always applied, which is why
382
+ // "../src/store.js" under a declared "src/" stops reading as an omitted path.
383
+ const inferredOnlyPaths = [
384
+ ...inferred.paths.filter((candidate) => !pathBoundaryCovers(declaredPaths, candidate)),
385
+ ...inferred.droppedTokens,
386
+ ];
270
387
  const writeEvidence = DECLARED_EVIDENCE.writeRoots;
271
388
  const writeBoundaries = req.intent.writeRoots.map((root) => ({
272
389
  path: resolvePathBoundary(cwd, root),
@@ -277,6 +394,11 @@ export function resolveDispatchPathScope(req: DispatchRequest): DispatchPathScop
277
394
  workingContextPaths: declaredPaths,
278
395
  writeBoundaries: writeBoundaries.map((entry) => entry.path),
279
396
  inferredOnlyPaths,
397
+ // Empty on purpose: the declaration is the scope here, so no "../" token
398
+ // changed what the worker sees and there is nothing for the legacy notice
399
+ // to report. A dropped one still reaches the operator through
400
+ // inferredOnlyPaths above.
401
+ parentTokens: [],
280
402
  provenance: {
281
403
  version: 1,
282
404
  mode: "declared",
@@ -286,24 +408,113 @@ export function resolveDispatchPathScope(req: DispatchRequest): DispatchPathScop
286
408
  };
287
409
  }
288
410
 
411
+ /**
412
+ * The prose token grammar also matches version numbers, ratios, and Latin
413
+ * abbreviations ("0.5", "v24.9", "e.g", "dead/raw"). Those never select a rule
414
+ * or a boundary, so the replacement notice names only tokens that read as
415
+ * repository paths: a segment with a source or document file extension, or
416
+ * a trailing directory separator. Method names (`Store.fromText`, `store.set`)
417
+ * share the dotted shape and are excluded by the extension list. A live three-task dispatch printed 27
418
+ * "omitted paths" per task, most of them numbers, three times over.
419
+ */
420
+ const REPORTABLE_OMITTED_PATH_RE =
421
+ /\.(?:[cm]?[jt]sx?|json|ya?ml|md|txt|py|go|rs|c|h|cc|cpp|hpp|java|rb|sh|toml|css|html|sql|lock)(?:\/|$)|\/$/u;
422
+ const OMITTED_PATH_REPORT_CAP = 12;
423
+
424
+ /** Omitted prose paths worth telling the operator about, capped for the transcript. */
425
+ function reportableOmittedPaths(scope: DispatchPathScope): string[] {
426
+ return scope.inferredOnlyPaths.filter((path) => REPORTABLE_OMITTED_PATH_RE.test(path));
427
+ }
428
+
429
+ function renderOmittedPaths(paths: ReadonlyArray<string>): string {
430
+ if (paths.length <= OMITTED_PATH_REPORT_CAP) return paths.join(", ");
431
+ return `${paths.slice(0, OMITTED_PATH_REPORT_CAP).join(", ")} and ${paths.length - OMITTED_PATH_REPORT_CAP} more`;
432
+ }
433
+
289
434
  /** Render the named diagnostic for the declared-scope replacement tradeoff. */
290
435
  export function declaredScopeReplacementDiagnostic(scope: DispatchPathScope): string | null {
291
- if (scope.source !== "declared" || scope.inferredOnlyPaths.length === 0) return null;
292
- return `typed_scope_replaced_inferred_paths: typed intent omitted prose-inferred paths ${scope.inferredOnlyPaths.join(
293
- ", ",
436
+ if (scope.source !== "declared") return null;
437
+ const omitted = reportableOmittedPaths(scope);
438
+ if (omitted.length === 0) return null;
439
+ return `typed_scope_replaced_inferred_paths: typed intent omitted prose-inferred paths ${renderOmittedPaths(
440
+ omitted,
294
441
  )}; those paths did not select project rules or expand worker authority`;
295
442
  }
296
443
 
297
444
  /** Render the interactive warning for the declared-scope replacement tradeoff. */
298
445
  export function declaredScopeReplacementNotice(scope: DispatchPathScope): DeclaredScopeReplacementNotice | null {
299
- if (scope.source !== "declared" || scope.inferredOnlyPaths.length === 0) return null;
300
- const omittedPaths = [...scope.inferredOnlyPaths];
446
+ if (scope.source !== "declared") return null;
447
+ const omittedPaths = reportableOmittedPaths(scope);
448
+ if (omittedPaths.length === 0) return null;
301
449
  return {
302
450
  code: "typed_scope_replaced_inferred_paths",
303
451
  level: "warning",
304
452
  omittedPaths,
305
- message: `[dispatch scope] typed intent replaced prose path inference; omitted paths: ${omittedPaths.join(
306
- ", ",
453
+ message: `[dispatch scope] typed intent replaced prose path inference; omitted paths: ${renderOmittedPaths(
454
+ omittedPaths,
307
455
  )}. Those paths did not select project rules or expand worker authority.`,
308
456
  };
309
457
  }
458
+
459
+ /**
460
+ * A reinterpreted "../" token is the one legacy-mode scope fact worth the
461
+ * transcript. It fires only where a leading "../" run made inference choose
462
+ * between a path the prose never literally spelled and no path at all, which
463
+ * before this release failed the whole dispatch, so unlike a per-dispatch
464
+ * inference notice it cannot warn on the ordinary case that
465
+ * `publishDispatchPathScope` deliberately keeps quiet. The anchored token earns
466
+ * the line more than the dropped one: dropping subtracts from scope, while
467
+ * anchoring puts "src/store.js" in working context because prose said
468
+ * "../src/store.js", and a rewrite the operator cannot see is one nobody can
469
+ * check.
470
+ *
471
+ * Declared mode records none. The declaration is the scope there, and a prose
472
+ * token that never entered it is already the subject of
473
+ * `declaredScopeReplacementNotice`. That notice filters by
474
+ * REPORTABLE_OMITTED_PATH_RE, so a declared-mode drop of "../data/blob.bin" or
475
+ * "../src/helper" is in fact named nowhere; that is the accepted cost of not
476
+ * spending a second per-dispatch notice on a token that took no part in a scope
477
+ * the intent had already fixed.
478
+ *
479
+ * The legacy list is not filtered by REPORTABLE_OMITTED_PATH_RE, because the
480
+ * "../" prefix is itself the filter: the version numbers, ratios, and Latin
481
+ * abbreviations that filter exists for ("0.5", "v24.9", "e.g", "4/10") cannot
482
+ * carry one.
483
+ *
484
+ * Both notices render one `<raw token> -> <anchored path or "dropped">` pair
485
+ * per entry, under the same twelve-entry cap the replacement notice uses.
486
+ */
487
+ function renderParentTokens(tokens: ReadonlyArray<DispatchInferredParentToken>): string {
488
+ return renderOmittedPaths(tokens.map((entry) => `${entry.token} -> ${entry.resolved ?? "dropped"}`));
489
+ }
490
+
491
+ /** Render the named diagnostic for prose tokens whose leading "../" run was reinterpreted. */
492
+ export function inferredScopeParentTokenDiagnostic(scope: DispatchPathScope): string | null {
493
+ const tokens = scope.parentTokens;
494
+ if (tokens.length === 0) return null;
495
+ return `legacy_scope_inferred: prose inference resolved path tokens carrying a leading '../' run against the dispatch root ${renderParentTokens(
496
+ tokens,
497
+ )}; an anchored token selects project rules without expanding worker authority and a dropped one took no part in scope`;
498
+ }
499
+
500
+ /** Render the interactive warning for prose tokens whose leading "../" run was reinterpreted. */
501
+ export function inferredScopeParentTokenNotice(scope: DispatchPathScope): InferredScopeParentTokenNotice | null {
502
+ const tokens = scope.parentTokens;
503
+ if (tokens.length === 0) return null;
504
+ return {
505
+ code: "legacy_scope_inferred",
506
+ level: "warning",
507
+ // Every entry names the raw prose token, the one spelling both outcomes
508
+ // share; the message carries what each one resolved to.
509
+ paths: tokens.map((entry) => ({
510
+ path: entry.token,
511
+ policy: "working-context",
512
+ provenance: "inferred",
513
+ source: entry.source,
514
+ confidence: "low",
515
+ })),
516
+ message: `[dispatch scope] prose inference resolved path tokens carrying a leading '../' run against the dispatch root: ${renderParentTokens(
517
+ tokens,
518
+ )}. An anchored token selects project rules without expanding worker authority; a dropped one took no part in scope.`,
519
+ };
520
+ }
@@ -51,9 +51,6 @@ export const RUN_EVENT_JOURNAL_FILE = "events.ndjson";
51
51
  export const RUN_EVENT_JOURNAL_CAP_BYTES = 2 * 1024 * 1024;
52
52
  /** Pending bytes that trigger a flush of droppable lines. */
53
53
  export const RUN_EVENT_JOURNAL_FLUSH_BYTES = 8 * 1024;
54
- /** Per-process env override, resolved ahead of settings (see runEventJournalEnabled). */
55
- export const RUN_EVENT_JOURNAL_ENV_VAR = "CLIO_CODER_RUN_JOURNAL";
56
-
57
54
  interface JournalLineBase {
58
55
  seq: number;
59
56
  at: string;
@@ -119,7 +116,7 @@ export interface RunEventJournal extends RunEventJournalSink {
119
116
  let configuredEnabled: boolean | undefined;
120
117
 
121
118
  /**
122
- * Install the `panes.journal` setting. Called from the composition root beside
119
+ * Install the `fleet.history.journal` setting. Called from the composition root beside
123
120
  * `configureGuardrails` so the journal never reads settings.yaml itself; a
124
121
  * settings read on the dispatch event path would be both a cost and a throw
125
122
  * site (readSettings rejects an invalid file).
@@ -128,17 +125,9 @@ export function configureRunEventJournal(enabled: boolean | undefined): void {
128
125
  configuredEnabled = enabled;
129
126
  }
130
127
 
131
- function parseEnvFlag(raw: string | undefined): boolean | undefined {
132
- if (raw === undefined) return undefined;
133
- const normalized = raw.trim().toLowerCase();
134
- if (normalized === "1" || normalized === "true" || normalized === "on") return true;
135
- if (normalized === "0" || normalized === "false" || normalized === "off") return false;
136
- return undefined;
137
- }
138
-
139
- /** env override > configured settings > on. */
140
- function runEventJournalEnabled(env: NodeJS.ProcessEnv = process.env): boolean {
141
- return parseEnvFlag(env[RUN_EVENT_JOURNAL_ENV_VAR]) ?? configuredEnabled ?? true;
128
+ /** Effective settings projection, then the shipped default. */
129
+ function runEventJournalEnabled(): boolean {
130
+ return configuredEnabled ?? true;
142
131
  }
143
132
 
144
133
  // ---------------------------------------------------------------------------
@@ -6,8 +6,8 @@
6
6
  * receipts/<runId>.json per-run RunReceipt
7
7
  *
8
8
  * The ledger holds an in-memory mirror of runs.json. `create()` and `update()`
9
- * mutate memory only; `persist()` writes the bounded ring (default 1000, env
10
- * override `CLIO_CODER_MAX_DISPATCH_RUNS`) atomically via engine.atomicWrite.
9
+ * mutate memory only; `persist()` writes the settings-bounded ring (default
10
+ * 1000) atomically via engine.atomicWrite.
11
11
  *
12
12
  * No worker spawning, no domain wire-up, no SafeEventBus emission yet. Those
13
13
  * land in P6S3 and P6S5. This slice is a pure persistence primitive.
@@ -159,7 +159,6 @@ function readRuns(): RunEnvelope[] {
159
159
 
160
160
  function resolveMaxRuns(opt?: number | undefined): number {
161
161
  if (opt !== undefined && opt > 0) return Math.floor(opt);
162
- // env (CLIO_CODER_MAX_DISPATCH_RUNS) > settings guardrails > default; see core/guardrails.ts.
163
162
  return resolveGuardrail("maxDispatchRuns");
164
163
  }
165
164
 
@@ -10,9 +10,9 @@
10
10
  *
11
11
  * SSH tier invariants:
12
12
  * - The remote environment is a whitelist, never the orchestrator's
13
- * process.env. Remote workers default to CLIO_CODER_RESIDENCY=observe so a
14
- * worker on a node that serves models for the operator can never evict a
15
- * resident model.
13
+ * process.env. Remote workers default to a user-managed target lifecycle
14
+ * so a worker on a node that serves models for the operator can never
15
+ * evict a resident model.
16
16
  * - The orchestrator cwd is entered on the remote node (shared-filesystem
17
17
  * assumption; path parity is a doctor preflight, and placement refuses
18
18
  * nodes that have not passed it).
@@ -62,9 +62,9 @@ export interface SshNodeEndpoint {
62
62
  */
63
63
  clioCoderEntry?: string;
64
64
  /**
65
- * Residency posture exported to the remote worker. Defaults to "observe":
66
- * remote workers must never evict models resident on their node. "manage"
67
- * is an explicit per-node opt-in.
65
+ * Residency posture projected into the remote worker's target lifecycle.
66
+ * Defaults to "observe": remote workers must never evict models resident on
67
+ * their node. "manage" is an explicit per-node opt-in.
68
68
  */
69
69
  residency?: "observe" | "manage";
70
70
  connectTimeoutSec?: number;
@@ -99,14 +99,33 @@ const DEFAULT_REMOTE_CLIO_ENTRY = "clio-coder worker";
99
99
  * orchestrator-supplied credential.
100
100
  */
101
101
  function remoteEnvAssignments(node: SshNodeEndpoint): string {
102
- const residency = node.residency ?? "observe";
103
102
  // `$$` is the login shell's pid, and it leads the process group the remote
104
103
  // command runs in. `exec` replaces that shell in place, so the worker
105
104
  // inherits both the pid and the group leadership, and the value it announces
106
105
  // is the group an abort must signal.
107
106
  const labels = (node.labels ?? []).map((label) => label.trim()).filter((label) => label.length > 0);
108
107
  const labelAssignment = labels.length > 0 ? ` CLIO_CODER_WORKER_LABELS=${shellQuote(labels.join(","))}` : "";
109
- return `AI_AGENT=${AI_AGENT_NAME} CLIO_CODER_RESIDENCY=${residency} CLIO_CODER_WORKER_PGID=$$${labelAssignment}`;
108
+ return `AI_AGENT=${AI_AGENT_NAME} CLIO_CODER_WORKER_PGID=$$${labelAssignment}`;
109
+ }
110
+
111
+ type TargetLifecycle = NonNullable<WorkerSpec["target"]["lifecycle"]>;
112
+
113
+ export function resolveSshTargetLifecycle(
114
+ residency: SshNodeEndpoint["residency"],
115
+ targetLifecycle: WorkerSpec["target"]["lifecycle"],
116
+ ): TargetLifecycle {
117
+ if (targetLifecycle === "user-managed" || residency !== "manage") return "user-managed";
118
+ return "clio-coder-managed";
119
+ }
120
+
121
+ function workerSpecForSshNode(node: SshNodeEndpoint, spec: WorkerSpec): WorkerSpec {
122
+ return {
123
+ ...spec,
124
+ target: {
125
+ ...spec.target,
126
+ lifecycle: resolveSshTargetLifecycle(node.residency, spec.target.lifecycle),
127
+ },
128
+ };
110
129
  }
111
130
 
112
131
  function buildRemoteWorkerCommand(node: SshNodeEndpoint, cwd: string): string {
@@ -174,20 +193,25 @@ export function createSshWorkerTransport(node: SshNodeEndpoint, opts?: SshTransp
174
193
  // are the transport's own and compose with the caller's rather than
175
194
  // replacing them; every other option is forwarded as handed.
176
195
  const { cwd: _consumedCwd, onAnnounce, onForcedKill, ...forwarded } = spawnOpts ?? {};
177
- return spawnWorkerProcess(sshBinary, buildSshArgs(node, buildRemoteWorkerCommand(node, cwd)), spec, {
178
- ...(opts?.shutdownGraceMs !== undefined ? { shutdownGraceMs: opts.shutdownGraceMs } : {}),
179
- ...forwarded,
180
- env: process.env,
181
- onAnnounce: (attestation) => {
182
- remote.pid = attestation.pid;
183
- remote.processGroupId = attestation.processGroupId;
184
- onAnnounce?.(attestation);
185
- },
186
- onForcedKill: () => {
187
- killRemote();
188
- onForcedKill?.();
196
+ return spawnWorkerProcess(
197
+ sshBinary,
198
+ buildSshArgs(node, buildRemoteWorkerCommand(node, cwd)),
199
+ workerSpecForSshNode(node, spec),
200
+ {
201
+ ...(opts?.shutdownGraceMs !== undefined ? { shutdownGraceMs: opts.shutdownGraceMs } : {}),
202
+ ...forwarded,
203
+ env: process.env,
204
+ onAnnounce: (attestation) => {
205
+ remote.pid = attestation.pid;
206
+ remote.processGroupId = attestation.processGroupId;
207
+ onAnnounce?.(attestation);
208
+ },
209
+ onForcedKill: () => {
210
+ killRemote();
211
+ onForcedKill?.();
212
+ },
189
213
  },
190
- });
214
+ );
191
215
  },
192
216
  };
193
217
  }
@@ -584,7 +584,7 @@ export interface RunReceiptSafetySummary {
584
584
  * (reason code `guard_block`); a call that required permission and was denied
585
585
  * non-interactively is counted under `permissionRequested`, not `blocked`, so
586
586
  * scripts can tell "approval would have been needed" apart from a policy
587
- * block (see docs/safety-model.md). Such a call still appears in
587
+ * block (see docs/architecture/safety-model.md). Such a call still appears in
588
588
  * `blockedAttempts` because its outcome was blocked, so `decisions.blocked`
589
589
  * is not a proxy for the number of blocked attempts; use `blockedAttempts`
590
590
  * or the `toolStats`/`toolActivity` blocked counts for that.
@@ -712,14 +712,66 @@ export interface RunHostVerificationCheck {
712
712
  memo: boolean;
713
713
  outputTail: string;
714
714
  artifactPath?: string;
715
- /** Original evidence owner on a memo hit. */
715
+ /** Run that owns the evidence when it did not come from this run: a memo hit, or the batch member the shared check ran under. */
716
716
  evidenceRunId?: string;
717
717
  }
718
718
 
719
+ /**
720
+ * Why a batch-settled failing check was or was not charged to a run. It is a
721
+ * batch-wide fact and is sealed identically on every receipt in the batch; each
722
+ * receipt's own `status` is what that run is judged by.
723
+ */
724
+ export interface RunHostVerificationAttribution {
725
+ /** Declared check id that failed. */
726
+ check: string;
727
+ /**
728
+ * Absolute repository paths the check's own output named, capped at 32. The
729
+ * paths that decided the charge come first so a truncated list still contains
730
+ * the evidence behind the verdict; each group is sorted.
731
+ */
732
+ implicated: string[];
733
+ /** Run ids the failure is charged to, sorted; empty when every named path belongs to a run that did not declare the check. */
734
+ charged: string[];
735
+ /**
736
+ * The weakest evidence behind the charge set, never the strongest, so the
737
+ * record cannot claim a certainty it does not have.
738
+ *
739
+ * `write_roots`: every charged run has an implicated path inside its own
740
+ * declared write roots. `attributed_elsewhere`: nothing is charged because
741
+ * every implicated path falls inside the write roots of a live batch member
742
+ * that did not declare this check. `unattributable`: the charge is not backed
743
+ * by per-run path evidence, which covers a failure that named no path, one
744
+ * that named only paths no member claims, and one charged to a run that
745
+ * declared no write roots at all. The first two of those charge every run that
746
+ * declared the check: a real failure with no owner is charged to everyone
747
+ * rather than excused for everyone.
748
+ */
749
+ basis: "write_roots" | "attributed_elsewhere" | "unattributable";
750
+ }
751
+
719
752
  export interface RunHostVerification {
720
- status: "verified" | "rejected" | "skipped";
753
+ /**
754
+ * `verified` states that every declared check passed, which is the claim
755
+ * `trust-status.ts:619` turns into "validated by host-verification".
756
+ * `not_implicated` is the batch-settled exculpation: a declared check failed
757
+ * for the batch and this run's `checks` carries its non-zero exit code, but
758
+ * the failure was charged elsewhere, so no validator speaks for this run.
759
+ */
760
+ status: "verified" | "rejected" | "skipped" | "not_implicated";
721
761
  reason?: string;
722
762
  checks: RunHostVerificationCheck[];
763
+ /**
764
+ * How the declared checks were run. Absent means the single-run strategy every
765
+ * receipt carried before batch settlement existed: the checks ran for this run
766
+ * alone, straight after it finished. `batch-settled` means they ran once for
767
+ * the whole parallel batch after every live member had finished. The field is
768
+ * omitted rather than stamped `"single"` so a single-task receipt digests
769
+ * exactly as it did before (`receipt-integrity.ts:145-147` is the same
770
+ * reasoning applied one field over).
771
+ */
772
+ strategy?: "batch-settled";
773
+ /** Per-failing-check attribution for a batch-settled run; absent when nothing failed. */
774
+ attribution?: RunHostVerificationAttribution[];
723
775
  }
724
776
 
725
777
  export interface RunReceipt {
@@ -11,6 +11,11 @@ import { parseEvalVerdictEnvelopeV1 } from "../schema/verdict.js";
11
11
  import { evalRoot } from "../store.js";
12
12
  import { redactArtifactForStorage } from "./redact.js";
13
13
 
14
+ // This is the documented location (docs/architecture/artifact-versions.md's
15
+ // Eval Artifact row): <dataDir>/evals/<evalId>.json, flat. The legacy version-1
16
+ // shape skills-eval writes lives at evalRoot()/skills-eval/ instead
17
+ // (store.ts's evalArtifactPath) so the two writers can never resolve to the
18
+ // same file for the same id.
14
19
  function evalArtifactPathV4(dataDir: string, evalId: string): string {
15
20
  assertSafeId(evalId, "eval");
16
21
  return join(evalRoot(dataDir), `${evalId}.json`);
@@ -60,9 +60,16 @@ export function evalRoot(dataDir: string): string {
60
60
  return join(dataDir, "evals");
61
61
  }
62
62
 
63
+ /**
64
+ * `skills-eval` is the only writer of this legacy version-1 shape; it nests
65
+ * under its own subdirectory so a legacy id that collides with a `clio-coder
66
+ * eval` run's version-4 id (evalArtifactPathV4, artifacts/store.ts) cannot
67
+ * clobber that artifact, and so `eval inventory`'s top-level readdir of
68
+ * evalRoot() never trips over a shape it does not parse.
69
+ */
63
70
  export function evalArtifactPath(dataDir: string, evalId: string): string {
64
71
  assertSafeId(evalId, "eval");
65
- return join(evalRoot(dataDir), `${evalId}.json`);
72
+ return join(evalRoot(dataDir), "skills-eval", `${evalId}.json`);
66
73
  }
67
74
 
68
75
  /**