@iowarp/clio-coder 0.3.8 → 0.4.0

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 (552) hide show
  1. package/CHANGELOG.md +102 -0
  2. package/NOTICE +33 -0
  3. package/README.md +12 -3
  4. package/dist/{acp-U67UHUK2.js → acp-G5WJBNCT.js} +13 -12
  5. package/dist/{agents-YU6SGALZ.js → agents-FMV2Q5G4.js} +41 -36
  6. package/dist/assets/codewiki.json +1 -1
  7. package/dist/{auth-5ZPJOIVG.js → auth-3IDSJEIK.js} +18 -18
  8. package/dist/{builtins-C6JMZVV6.js → builtins-XCZWXSC7.js} +5 -5
  9. package/dist/{chunk-IFBNV6H6.js → chunk-2ANTL7MR.js} +3 -3
  10. package/dist/{chunk-5FR74PWO.js → chunk-2JDWVJND.js} +2 -2
  11. package/dist/{chunk-XWSF374K.js → chunk-2OQE55CK.js} +3 -3
  12. package/dist/{chunk-5H3GB5BO.js → chunk-32KWKNSF.js} +8 -384
  13. package/dist/{chunk-KTYTFRMB.js → chunk-36EJLSQQ.js} +34 -36
  14. package/dist/{chunk-FHJEP5SW.js → chunk-3BT2XMV4.js} +19 -13
  15. package/dist/chunk-3DPEIQKN.js +113 -0
  16. package/dist/{chunk-GU2UIAFZ.js → chunk-3URVFKWK.js} +7 -7
  17. package/dist/{chunk-WEH5XRJQ.js → chunk-3XML7CDN.js} +3 -3
  18. package/dist/chunk-42FMPA75.js +101 -0
  19. package/dist/{chunk-A2NJGIB3.js → chunk-5LXZXPKX.js} +2 -2
  20. package/dist/{chunk-VCBR6CU7.js → chunk-5PSMVOLM.js} +2 -2
  21. package/dist/{chunk-NMPKI6XL.js → chunk-6DB53AJS.js} +203 -25
  22. package/dist/{chunk-3BINW3FP.js → chunk-76ONBSIA.js} +2 -2
  23. package/dist/{chunk-26LEYJZH.js → chunk-7MCTRUCE.js} +2 -2
  24. package/dist/{chunk-TYPGUK6W.js → chunk-AB44T6BB.js} +111 -5
  25. package/dist/{chunk-K4XHGFR5.js → chunk-B7OBL7PK.js} +317 -721
  26. package/dist/{chunk-B5CSFE7B.js → chunk-BBVJUZHB.js} +2 -2
  27. package/dist/{chunk-EQ63NRB7.js → chunk-BBVYXMFO.js} +2 -2
  28. package/dist/{chunk-ZVJ5BLO2.js → chunk-BKFJHQCA.js} +154 -16
  29. package/dist/chunk-BKFM6EJV.js +462 -0
  30. package/dist/chunk-BMS5RKQY.js +27 -0
  31. package/dist/{chunk-ZNLWCMVZ.js → chunk-BPKCPIL7.js} +2 -2
  32. package/dist/{chunk-TLQJPP24.js → chunk-BUMFYQFY.js} +1394 -1349
  33. package/dist/{chunk-BNAZZHFG.js → chunk-BYP5D4HI.js} +1 -1
  34. package/dist/chunk-C2LTL2W6.js +2447 -0
  35. package/dist/{chunk-ME6CCNFO.js → chunk-CODPRO7Q.js} +8 -8
  36. package/dist/{chunk-E77JEWSD.js → chunk-CTJ4RNAA.js} +7 -37
  37. package/dist/{chunk-ODFEOB4F.js → chunk-CY6FY24N.js} +26 -8
  38. package/dist/{chunk-7RFXX52T.js → chunk-DQITNCXG.js} +642 -172
  39. package/dist/{chunk-TTHACPOM.js → chunk-DYJP44XW.js} +578 -117
  40. package/dist/{chunk-2HFZQUHL.js → chunk-F4CKPOEQ.js} +18 -8
  41. package/dist/{chunk-DGSYXYMX.js → chunk-FEFIFZTL.js} +3 -3
  42. package/dist/{chunk-GWS3VEIW.js → chunk-FWDFM5ZU.js} +24 -3
  43. package/dist/{chunk-MV3K5QF2.js → chunk-GCSMB2KY.js} +2 -2
  44. package/dist/chunk-GKF55TAZ.js +391 -0
  45. package/dist/{chunk-VWZOAB7K.js → chunk-GR5G2PVF.js} +9 -8
  46. package/dist/{chunk-4DGYLA73.js → chunk-GXNLGKAB.js} +80 -9
  47. package/dist/chunk-HHV2GANA.js +88 -0
  48. package/dist/{chunk-IIZWH4XA.js → chunk-HI63TFOG.js} +5 -4
  49. package/dist/{chunk-WLFILSD5.js → chunk-HJJTYUHX.js} +113 -83
  50. package/dist/{chunk-TT36MB5S.js → chunk-HLW2MRKE.js} +3 -1
  51. package/dist/{chunk-PMDBGQSJ.js → chunk-HWHKMHUA.js} +7 -7
  52. package/dist/chunk-HZHHCK24.js +1631 -0
  53. package/dist/{chunk-WSB3FPX7.js → chunk-I5VEOC6I.js} +39 -143
  54. package/dist/chunk-IBEBSCYA.js +564 -0
  55. package/dist/chunk-IQ7KR472.js +362 -0
  56. package/dist/{chunk-A3WNZD3P.js → chunk-J4W7KFM7.js} +949 -972
  57. package/dist/{chunk-TB5666IT.js → chunk-JDG2WCRO.js} +5 -5
  58. package/dist/{chunk-N22QMJKY.js → chunk-K5C3NCBD.js} +4 -4
  59. package/dist/{chunk-CGKSTWHD.js → chunk-K6BSR66V.js} +2 -1
  60. package/dist/{chunk-5C3AQNDW.js → chunk-KFZI4NIL.js} +216 -38
  61. package/dist/chunk-KMVISBZR.js +132 -0
  62. package/dist/{chunk-WXY7KU3G.js → chunk-LDQ2ZF2M.js} +2 -2
  63. package/dist/{chunk-XN3L4EYL.js → chunk-LQ3DZAMX.js} +3 -3
  64. package/dist/{chunk-U6MBIEMB.js → chunk-LY4S7GJC.js} +173 -144
  65. package/dist/{chunk-4SPRNWDE.js → chunk-MLKNTWH2.js} +19 -19
  66. package/dist/{chunk-MVVUPGPW.js → chunk-MXHC5QYU.js} +6 -6
  67. package/dist/chunk-NEKRRTYW.js +56 -0
  68. package/dist/{chunk-SPULKLCF.js → chunk-NHCZP4K7.js} +3 -3
  69. package/dist/chunk-NHLBIGRH.js +1506 -0
  70. package/dist/chunk-NQQH3YT7.js +302 -0
  71. package/dist/chunk-NYS75XW5.js +15 -0
  72. package/dist/{chunk-GN57SG4G.js → chunk-O4XIVISU.js} +10 -8
  73. package/dist/{chunk-EMYUUSFG.js → chunk-O6TL7WWY.js} +6 -6
  74. package/dist/chunk-OQBA45DZ.js +97 -0
  75. package/dist/{chunk-LU7P4LHA.js → chunk-P3FOHJT4.js} +2 -2
  76. package/dist/chunk-PMZCIOCJ.js +25 -0
  77. package/dist/{chunk-I4HZDVNP.js → chunk-PQEFIJ36.js} +2 -2
  78. package/dist/{chunk-J3YUBZWY.js → chunk-QBJA7R7N.js} +62 -6
  79. package/dist/chunk-QDC3K2U3.js +262 -0
  80. package/dist/{chunk-2HEJ2F35.js → chunk-QLFS5GO2.js} +22 -10
  81. package/dist/{chunk-7RGZWPB6.js → chunk-QLL7ILRG.js} +95 -32
  82. package/dist/{chunk-YS5VLNH5.js → chunk-QREDIESB.js} +6 -6
  83. package/dist/chunk-QSNYB6ZV.js +195 -0
  84. package/dist/{chunk-GOXNB3AO.js → chunk-RAPCMZL4.js} +75 -4
  85. package/dist/chunk-RKKLTLYB.js +45 -0
  86. package/dist/{chunk-P43ETTHK.js → chunk-SJ5ZKQ4S.js} +2 -2
  87. package/dist/{chunk-GPIEI3LY.js → chunk-SP2RXXYO.js} +6 -54
  88. package/dist/chunk-SUCTJL45.js +45 -0
  89. package/dist/{chunk-DYIM5TJT.js → chunk-SUW5DORT.js} +263 -7
  90. package/dist/chunk-T56WDKA5.js +183 -0
  91. package/dist/chunk-TVHHYFHE.js +255 -0
  92. package/dist/{chunk-FJ3H4MN5.js → chunk-TZ3SGWZZ.js} +3 -3
  93. package/dist/{chunk-MXKJU4JB.js → chunk-U77AMWDL.js} +91 -10
  94. package/dist/{chunk-5DHKRSMQ.js → chunk-ULC6OTWO.js} +11 -7
  95. package/dist/{chunk-RWSI4YD7.js → chunk-UM7N4G5A.js} +33 -12
  96. package/dist/{chunk-FCSXB6T2.js → chunk-UOSL25KY.js} +14 -2
  97. package/dist/{chunk-IGWKHNIQ.js → chunk-UXMFQ54G.js} +44 -37
  98. package/dist/{chunk-HFSBBKSQ.js → chunk-V5DHCITQ.js} +171 -3
  99. package/dist/{chunk-5WIGXA4T.js → chunk-VAZSBTKF.js} +111 -4
  100. package/dist/{chunk-VHN4MY6O.js → chunk-VEO4AP2K.js} +2 -2
  101. package/dist/{chunk-IJ7RPIYJ.js → chunk-VFA6GDY5.js} +65 -4
  102. package/dist/{chunk-PT7HYKEM.js → chunk-VO2LKSTM.js} +2 -2
  103. package/dist/chunk-VO67MWHC.js +75 -0
  104. package/dist/{chunk-XK56QHLX.js → chunk-VPKWYKEY.js} +19 -5
  105. package/dist/{chunk-TANS5ZJS.js → chunk-VYMXRQI6.js} +36 -22
  106. package/dist/{chunk-WWCZ5F23.js → chunk-W5VSYASO.js} +77 -16
  107. package/dist/{chunk-WNIJTQQK.js → chunk-WZR7K7ZX.js} +72 -116
  108. package/dist/{chunk-5Q2VVUKB.js → chunk-X3YGUTOB.js} +4 -4
  109. package/dist/chunk-X75E3D2N.js +686 -0
  110. package/dist/{chunk-VAWNZU7Z.js → chunk-YDFRH54B.js} +4 -4
  111. package/dist/chunk-YJX4SHTD.js +40 -0
  112. package/dist/{chunk-ZI647VB5.js → chunk-YPI3QQCF.js} +2 -2
  113. package/dist/chunk-Z2RR6MAK.js +127 -0
  114. package/dist/{chunk-FBVTI2TJ.js → chunk-Z4TXYIEG.js} +12 -131
  115. package/dist/cli/index.js +47 -36
  116. package/dist/{clio-QVTYJ57A.js → clio-2JXHBBY5.js} +7 -7
  117. package/dist/{code-nav-FGGFIE7L.js → code-nav-3YYRMYNF.js} +8 -8
  118. package/dist/{compile-cache-CVJMMODC.js → compile-cache-7FPE6PS3.js} +3 -3
  119. package/dist/{components-ZFA3SAER.js → components-RYZV4JGP.js} +5 -5
  120. package/dist/{config-LW5IJFQN.js → config-QZPCMYSO.js} +99 -63
  121. package/dist/{configure-7XIZCOU4.js → configure-TEGEBYCA.js} +23 -22
  122. package/dist/{context-Y6Y7QPR6.js → context-AV7OEZ4D.js} +12 -12
  123. package/dist/{context-L3WL3X7K.js → context-E6H5RNMC.js} +56 -47
  124. package/dist/{context-N52ZA626.js → context-GSXUE4CT.js} +29 -27
  125. package/dist/{context-clear-MBQRLSDQ.js → context-clear-SHIBYK6T.js} +55 -46
  126. package/dist/{context-index-HVMFQHK3.js → context-index-HNG3MOME.js} +2 -2
  127. package/dist/{context-working-set-GS6DSO7F.js → context-working-set-5ZGKPGZQ.js} +13 -13
  128. package/dist/{dispatch-runner-22ZCNOM3.js → dispatch-runner-EFMJT4LD.js} +93 -64
  129. package/dist/{docs-7LQ23DLM.js → docs-23KQS3XK.js} +5 -5
  130. package/dist/doctor-QOA5FNY5.js +313 -0
  131. package/dist/{eval-BEC2WHDA.js → eval-TFBYQH4H.js} +2032 -156
  132. package/dist/eval-inventory-SXH7PDKX.js +316 -0
  133. package/dist/{evidence-REJUMSKM.js → evidence-ERGESKGN.js} +203 -48
  134. package/dist/{evolve-PY5ZBA5K.js → evolve-VDXTSYCJ.js} +52 -43
  135. package/dist/{extensions-HVKU65YU.js → extensions-7BGBHN57.js} +13 -7
  136. package/dist/{fleet-7WZEWRFA.js → fleet-2RRVDF2V.js} +228 -108
  137. package/dist/{fleet-commands-UVHWM76J.js → fleet-commands-VJ726XIA.js} +11 -11
  138. package/dist/fleet-decisions-EPAPM3XJ.js +157 -0
  139. package/dist/{fleet-graph-6ULH7PES.js → fleet-graph-JF5QOATM.js} +18 -15
  140. package/dist/fleet-inspect-VLY4S7QM.js +442 -0
  141. package/dist/{fleet-preflight-J53T6CCE.js → fleet-preflight-AIZUEJOY.js} +5 -5
  142. package/dist/{fleet-validate-72PC4SLA.js → fleet-validate-AJRPDMDV.js} +22 -19
  143. package/dist/fleet-verify-JFEL2L3H.js +175 -0
  144. package/dist/fleet-view-ZCON35AG.js +102 -0
  145. package/dist/{init-OG3TPGQG.js → init-DN2WWLFE.js} +72 -62
  146. package/dist/install-XGLBQY5E.js +13 -0
  147. package/dist/interop-OZBKXAYL.js +114 -0
  148. package/dist/{library-CNTMPLRF.js → library-YWZG7IMW.js} +21 -18
  149. package/dist/{memory-6IS7F275.js → memory-I4C4HMLW.js} +54 -45
  150. package/dist/{models-ENRJDA5W.js → models-CEYXJBO6.js} +33 -30
  151. package/dist/{monitor-XLDVO7TN.js → monitor-NZ6GCI3P.js} +59 -52
  152. package/dist/{orchestrator-6KSPYRHA.js → orchestrator-GCGQ4N5I.js} +7827 -7328
  153. package/dist/panes-HMABYVO4.js +58 -0
  154. package/dist/panes-KY6W3V2E.js +103 -0
  155. package/dist/{paths-DBXMZMDU.js → paths-II4K7DNR.js} +5 -5
  156. package/dist/{reset-RZ4ER727.js → reset-DQ6FGCSH.js} +13 -11
  157. package/dist/resources-BB3MVJMD.js +111 -0
  158. package/dist/{run-Y2CNK5RU.js → run-H2GQDUER.js} +119 -87
  159. package/dist/{share-A55GYP6Z.js → share-GTJN6A5O.js} +20 -17
  160. package/dist/{skills-ALC5J6AT.js → skills-L55TEW6R.js} +33 -24
  161. package/dist/{skills-eval-JPBEBYQU.js → skills-eval-XVXPH2JI.js} +67 -56
  162. package/dist/skills-inventory-S4MXPJFV.js +126 -0
  163. package/dist/slash-commands-ZSGASKJC.js +77 -0
  164. package/dist/{steer-GGWFUJUD.js → steer-RZGSCY4R.js} +4 -4
  165. package/dist/{support-MIETYA5E.js → support-PKEUNNQL.js} +6 -6
  166. package/dist/{targets-VGNXIR3S.js → targets-NCPZ644J.js} +68 -40
  167. package/dist/{terminal-lease-WOBR64YA.js → terminal-lease-44SV3YCN.js} +6 -4
  168. package/dist/tools-DAF3DI3C.js +27 -0
  169. package/dist/{trace-PNCASAXC.js → trace-FYVW2MQA.js} +207 -10
  170. package/dist/tui-primitives-2AKXQNZK.js +13 -0
  171. package/dist/{uninstall-ZJF5H5ZN.js → uninstall-DW2PNOIC.js} +5 -5
  172. package/dist/{upgrade-FUSUAGHR.js → upgrade-3XPP6OQL.js} +27 -24
  173. package/dist/{usage-N4MKVHKD.js → usage-3NLHGTU2.js} +114 -62
  174. package/dist/{verifiers-YAWOJ3H2.js → verifiers-SSQONKRT.js} +172 -13
  175. package/dist/{verify-LTDHYBGY.js → verify-3U6J7FZI.js} +10 -10
  176. package/dist/{web-fetch-2YHJ3KTG.js → web-fetch-S7RR6GZ7.js} +3 -3
  177. package/dist/{wiki-generate-6M7GHTBJ.js → wiki-generate-CEHYGPGQ.js} +75 -65
  178. package/dist/with-panes-MKB46MPQ.js +782 -0
  179. package/dist/worker/entry.js +106 -75
  180. package/docs/README.md +3 -2
  181. package/docs/acp.md +24 -3
  182. package/docs/alcf-provider.md +1 -1
  183. package/docs/architecture.md +2 -2
  184. package/docs/artifact-versions.md +9 -1
  185. package/docs/built-in-agents.md +1 -1
  186. package/docs/capacity-and-scheduling.md +62 -3
  187. package/docs/commands-and-modes.md +31 -2
  188. package/docs/configuration-and-targets.md +69 -12
  189. package/docs/context-engine.md +63 -4
  190. package/docs/development-pipeline.md +19 -0
  191. package/docs/dispatch-typed-intent.md +385 -0
  192. package/docs/documentation-coverage.md +5 -5
  193. package/docs/documentation-guide.md +1 -1
  194. package/docs/environment-variables.md +3 -0
  195. package/docs/eval-runner.md +262 -11
  196. package/docs/evals-internal.md +72 -2
  197. package/docs/evidence-and-memory.md +12 -11
  198. package/docs/evolution.md +1 -1
  199. package/docs/exit-codes-and-output.md +1 -1
  200. package/docs/extensions-and-sharing.md +27 -1
  201. package/docs/fleet-dispatch.md +25 -4
  202. package/docs/installation-and-lifecycle.md +15 -2
  203. package/docs/middleware-and-components.md +1 -1
  204. package/docs/model-catalog.md +10 -1
  205. package/docs/observability.md +55 -4
  206. package/docs/proactive-memory.md +127 -14
  207. package/docs/prompt-envelope-and-tools.md +19 -1
  208. package/docs/provider-adapter-cookbook.md +1 -1
  209. package/docs/release-cut-checklist.md +19 -3
  210. package/docs/safety-model.md +2 -2
  211. package/docs/scientific-validation.md +3 -3
  212. package/docs/session-lifecycle.md +1 -1
  213. package/docs/skills-marketplace.md +1 -1
  214. package/docs/tool-usage.md +18 -8
  215. package/docs/trace-store.md +1 -1
  216. package/docs/troubleshooting.md +88 -1
  217. package/docs/tui-design.md +1 -1
  218. package/docs/worker-dispatch-mechanics.md +1 -1
  219. package/package.json +5 -2
  220. package/src/cli/acp.ts +6 -2
  221. package/src/cli/agents.ts +1 -1
  222. package/src/cli/argv.ts +25 -0
  223. package/src/cli/config-inspect.ts +33 -6
  224. package/src/cli/config.ts +1 -1
  225. package/src/cli/configure.ts +23 -21
  226. package/src/cli/doctor-panes.ts +124 -0
  227. package/src/cli/doctor-state-size.ts +82 -0
  228. package/src/cli/doctor-toolchain.ts +57 -0
  229. package/src/cli/doctor.ts +22 -1
  230. package/src/cli/eval-inventory.ts +436 -0
  231. package/src/cli/eval.ts +93 -16
  232. package/src/cli/evidence-detail.ts +88 -0
  233. package/src/cli/evidence-inventory.ts +183 -0
  234. package/src/cli/evidence.ts +30 -5
  235. package/src/cli/extensions.ts +5 -1
  236. package/src/cli/fleet-decisions.ts +69 -0
  237. package/src/cli/fleet-inspect.ts +334 -0
  238. package/src/cli/fleet-verify.ts +133 -0
  239. package/src/cli/fleet-view.ts +810 -0
  240. package/src/cli/fleet.ts +179 -39
  241. package/src/cli/index.ts +14 -2
  242. package/src/cli/interop-inspect.ts +128 -0
  243. package/src/cli/interop.ts +34 -0
  244. package/src/cli/panes.ts +35 -0
  245. package/src/cli/reset.ts +5 -2
  246. package/src/cli/run.ts +58 -0
  247. package/src/cli/skills-inventory.ts +185 -0
  248. package/src/cli/skills.ts +16 -13
  249. package/src/cli/targets.ts +44 -13
  250. package/src/cli/tools.ts +321 -0
  251. package/src/cli/trace-inspect.ts +252 -0
  252. package/src/cli/trace.ts +85 -5
  253. package/src/cli/usage.ts +63 -14
  254. package/src/cli/verifiers-inspect.ts +347 -0
  255. package/src/cli/verifiers.ts +9 -0
  256. package/src/core/bus-events.ts +33 -1
  257. package/src/core/cache-telemetry.ts +42 -0
  258. package/src/core/config.ts +67 -0
  259. package/src/core/defaults.ts +124 -8
  260. package/src/core/endpoint-key.ts +27 -0
  261. package/src/core/residency-target-key.ts +25 -0
  262. package/src/core/response-schema.ts +80 -6
  263. package/src/core/theme-token-hex.ts +43 -0
  264. package/src/core/tool-names.ts +2 -1
  265. package/src/core/xdg.ts +1 -1
  266. package/src/domains/agents/fleets/build-review.md +0 -3
  267. package/src/domains/agents/fleets/build-test.md +0 -3
  268. package/src/domains/agents/result-contract-filesystem.ts +32 -0
  269. package/src/domains/agents/result-contract.ts +164 -35
  270. package/src/domains/config/classify.ts +6 -0
  271. package/src/domains/context/codewiki/coordinator.ts +12 -4
  272. package/src/domains/dispatch/admission-error.ts +9 -0
  273. package/src/domains/dispatch/admission.ts +52 -14
  274. package/src/domains/dispatch/capacity-lease.ts +118 -9
  275. package/src/domains/dispatch/contract.ts +11 -0
  276. package/src/domains/dispatch/council-topology.ts +398 -0
  277. package/src/domains/dispatch/execution-plan.ts +44 -4
  278. package/src/domains/dispatch/extension.ts +378 -82
  279. package/src/domains/dispatch/fleet-node-prompt.ts +62 -0
  280. package/src/domains/dispatch/fleet-plan.ts +7 -2
  281. package/src/domains/dispatch/fleet-run.ts +87 -4
  282. package/src/domains/dispatch/gate-decisions.ts +11 -1
  283. package/src/domains/dispatch/gate-role-prompts.ts +9 -0
  284. package/src/domains/dispatch/gate-topology.ts +289 -0
  285. package/src/domains/dispatch/heartbeat.ts +32 -8
  286. package/src/domains/dispatch/index.ts +22 -0
  287. package/src/domains/dispatch/intent-compatibility.ts +330 -0
  288. package/src/domains/dispatch/intent.ts +85 -1
  289. package/src/domains/dispatch/orphan-recovery.ts +5 -0
  290. package/src/domains/dispatch/reservation-store.ts +139 -11
  291. package/src/domains/dispatch/run-event-journal-bridge.ts +149 -0
  292. package/src/domains/dispatch/run-event-journal.ts +598 -0
  293. package/src/domains/dispatch/state.ts +49 -1
  294. package/src/domains/dispatch/types.ts +13 -0
  295. package/src/domains/dispatch/validation.ts +33 -8
  296. package/src/domains/dispatch/worker-spawn.ts +25 -11
  297. package/src/domains/dispatch/write-boundary-enforcer.ts +20 -3
  298. package/src/domains/dispatch/write-boundary.ts +62 -1
  299. package/src/domains/eval/artifacts/store.ts +62 -0
  300. package/src/domains/eval/compare/behavioral.ts +224 -0
  301. package/src/domains/eval/compare/compare.ts +342 -2
  302. package/src/domains/eval/compare/envelope.ts +128 -0
  303. package/src/domains/eval/compare/gates.ts +24 -6
  304. package/src/domains/eval/compare/thresholds.ts +30 -3
  305. package/src/domains/eval/execution-provenance.ts +240 -0
  306. package/src/domains/eval/inventory.ts +113 -0
  307. package/src/domains/eval/metrics/aggregate.ts +136 -0
  308. package/src/domains/eval/metrics/call-ledger-stream.ts +112 -0
  309. package/src/domains/eval/metrics/tracked.ts +413 -0
  310. package/src/domains/eval/provenance.ts +117 -0
  311. package/src/domains/eval/reports/comparison.ts +128 -0
  312. package/src/domains/eval/reports/junit.ts +17 -3
  313. package/src/domains/eval/reports/markdown.ts +3 -3
  314. package/src/domains/eval/reports/text.ts +14 -0
  315. package/src/domains/eval/run-compare.ts +20 -0
  316. package/src/domains/eval/runners/clio-run.ts +127 -0
  317. package/src/domains/eval/runners/external-command.ts +28 -3
  318. package/src/domains/eval/schema/adapter.ts +111 -0
  319. package/src/domains/eval/schema/artifact.ts +20 -0
  320. package/src/domains/eval/schema/behavioral-metrics.ts +204 -0
  321. package/src/domains/eval/schema/behavioral.ts +520 -0
  322. package/src/domains/eval/schema/execution-envelope.ts +194 -0
  323. package/src/domains/eval/schema/serving.ts +105 -0
  324. package/src/domains/eval/schema/suite.ts +38 -8
  325. package/src/domains/eval/schema/validate.ts +58 -3
  326. package/src/domains/eval/schema/verdict.ts +237 -0
  327. package/src/domains/eval/suites/resolve.ts +2 -0
  328. package/src/domains/eval/suites/run.ts +264 -33
  329. package/src/domains/eval/verifiers/command.ts +2 -1
  330. package/src/domains/eval/workspaces/temp-copy.ts +145 -13
  331. package/src/domains/evidence/build.ts +2 -13
  332. package/src/domains/evidence/eval.ts +2 -12
  333. package/src/domains/evidence/findings-markdown.ts +33 -0
  334. package/src/domains/evidence/run-trust.ts +7 -113
  335. package/src/domains/evidence/store.ts +6 -0
  336. package/src/domains/evidence/trust-projection.ts +2 -2
  337. package/src/domains/extensions/compatibility.ts +285 -0
  338. package/src/domains/extensions/discovery.ts +38 -3
  339. package/src/domains/extensions/resources.ts +1 -1
  340. package/src/domains/extensions/state.ts +12 -3
  341. package/src/domains/extensions/types.ts +2 -0
  342. package/src/domains/lifecycle/doctor.ts +69 -1
  343. package/src/domains/memory/index.ts +14 -1
  344. package/src/domains/memory/task-bank-promotion.ts +64 -0
  345. package/src/domains/memory/task-memory-policy.ts +82 -17
  346. package/src/domains/memory/task-memory-spend.ts +131 -0
  347. package/src/domains/memory/task-memory-status.ts +7 -0
  348. package/src/domains/memory/task-memory-telemetry.ts +3 -0
  349. package/src/domains/middleware/index.ts +1 -0
  350. package/src/domains/middleware/memory-intervention.ts +97 -21
  351. package/src/domains/middleware/memory-step-endpoint.ts +71 -0
  352. package/src/domains/mux/contract.ts +434 -0
  353. package/src/domains/mux/detect.ts +158 -0
  354. package/src/domains/mux/extension.ts +47 -0
  355. package/src/domains/mux/index.ts +96 -0
  356. package/src/domains/mux/manifest.ts +6 -0
  357. package/src/domains/mux/operations.ts +164 -0
  358. package/src/domains/mux/pane-registry.ts +90 -0
  359. package/src/domains/mux/protocol.ts +49 -0
  360. package/src/domains/mux/socket-client.ts +816 -0
  361. package/src/domains/mux/types.ts +222 -0
  362. package/src/domains/mux/viewer-command.ts +59 -0
  363. package/src/domains/mux/yazi/assets/init.lua +2 -0
  364. package/src/domains/mux/yazi/assets/plugins/git.yazi/LICENSE +21 -0
  365. package/src/domains/mux/yazi/assets/plugins/git.yazi/README.md +78 -0
  366. package/src/domains/mux/yazi/assets/plugins/git.yazi/main.lua +255 -0
  367. package/src/domains/mux/yazi/assets/plugins/git.yazi/types.lua +12 -0
  368. package/src/domains/mux/yazi/assets/yazi.toml +17 -0
  369. package/src/domains/mux/yazi/event-stream.ts +180 -0
  370. package/src/domains/mux/yazi/profile.ts +299 -0
  371. package/src/domains/mux/yazi/session.ts +228 -0
  372. package/src/domains/mux/yazi/theme.ts +30 -0
  373. package/src/domains/observability/background-memory-usage.ts +140 -0
  374. package/src/domains/observability/cost.ts +22 -1
  375. package/src/domains/observability/index.ts +9 -0
  376. package/src/domains/observability/out-of-turn-usage.ts +51 -2
  377. package/src/domains/observability/trace-store.ts +234 -2
  378. package/src/domains/prompts/compiler.ts +100 -13
  379. package/src/domains/providers/endpoint-capacity.ts +228 -0
  380. package/src/domains/providers/endpoint-slots-store.ts +189 -0
  381. package/src/domains/providers/extension.ts +20 -3
  382. package/src/domains/providers/index.ts +32 -0
  383. package/src/domains/providers/model-runtime-capabilities.ts +32 -0
  384. package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +243 -1
  385. package/src/domains/providers/runtime-resolution.ts +8 -1
  386. package/src/domains/providers/runtimes/boot-manifest.ts +1 -0
  387. package/src/domains/providers/runtimes/builtins.ts +2 -0
  388. package/src/domains/providers/runtimes/common/probe-helpers.ts +31 -9
  389. package/src/domains/providers/runtimes/local-native/llamacpp-anthropic.ts +1 -1
  390. package/src/domains/providers/runtimes/local-native/llamacpp-completion.ts +1 -1
  391. package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +1 -1
  392. package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +1 -1
  393. package/src/domains/providers/runtimes/local-native/llamacpp.ts +4 -1
  394. package/src/domains/providers/runtimes/local-native/lmstudio.ts +4 -1
  395. package/src/domains/providers/runtimes/local-native/ollama-native.ts +6 -1
  396. package/src/domains/providers/runtimes/protocol/litellm.ts +375 -0
  397. package/src/domains/providers/support.ts +1 -0
  398. package/src/domains/providers/target-model-cache.ts +124 -0
  399. package/src/domains/providers/types/capability-flags.ts +2 -0
  400. package/src/domains/providers/types/target-descriptor.ts +2 -0
  401. package/src/domains/resources/index.ts +3 -0
  402. package/src/domains/resources/prompts/loader.ts +95 -33
  403. package/src/domains/resources/skills/loader.ts +33 -0
  404. package/src/domains/safety/action-classifier.ts +6 -0
  405. package/src/domains/safety/call-target.ts +52 -0
  406. package/src/domains/safety/run-effects.ts +35 -4
  407. package/src/domains/session/context-accounting.ts +52 -1
  408. package/src/domains/session/context-ledger.ts +37 -13
  409. package/src/domains/session/index.ts +6 -0
  410. package/src/domains/session/prompt-cache.ts +140 -0
  411. package/src/domains/session/prompt-manifest.ts +42 -0
  412. package/src/domains/toolchain/archive.ts +175 -0
  413. package/src/domains/toolchain/contract.ts +28 -0
  414. package/src/domains/toolchain/extension.ts +47 -0
  415. package/src/domains/toolchain/index.ts +39 -0
  416. package/src/domains/toolchain/install.ts +327 -0
  417. package/src/domains/toolchain/manifest.ts +8 -0
  418. package/src/domains/toolchain/paths.ts +34 -0
  419. package/src/domains/toolchain/registry.ts +265 -0
  420. package/src/domains/toolchain/remove.ts +218 -0
  421. package/src/domains/toolchain/resolve.ts +182 -0
  422. package/src/domains/toolchain/types.ts +113 -0
  423. package/src/domains/toolchain/version.ts +88 -0
  424. package/src/engine/acp/adapter.ts +18 -3
  425. package/src/engine/acp/server.ts +413 -70
  426. package/src/engine/acp/types.ts +19 -1
  427. package/src/engine/ai.ts +35 -0
  428. package/src/engine/apis/llamacpp-residency.ts +55 -3
  429. package/src/engine/apis/lmstudio.ts +25 -5
  430. package/src/engine/apis/ollama-native.ts +2 -1
  431. package/src/engine/apis/openai-completions.ts +80 -17
  432. package/src/engine/apis/residency-lock.ts +3 -1
  433. package/src/engine/apis/residency.ts +34 -1
  434. package/src/engine/claude/sdk-module.ts +98 -0
  435. package/src/engine/claude/sdk-runtime.ts +19 -11
  436. package/src/engine/provider-payload.ts +29 -1
  437. package/src/engine/tui-primitives.ts +21 -0
  438. package/src/engine/tui.ts +1 -0
  439. package/src/engine/worker-runtime.ts +2 -13
  440. package/src/entry/boot-options.ts +2 -0
  441. package/src/entry/orchestrator.ts +279 -35
  442. package/src/entry/panes-activation.ts +31 -0
  443. package/src/entry/with-panes.ts +20 -0
  444. package/src/interactive/chat-loop-messages.ts +26 -7
  445. package/src/interactive/chat-loop.ts +318 -41
  446. package/src/interactive/chat-panel.ts +62 -8
  447. package/src/interactive/clio-editor.ts +45 -8
  448. package/src/interactive/context-activity.ts +5 -1
  449. package/src/interactive/context-meter.ts +1 -1
  450. package/src/interactive/context-overlay.ts +41 -10
  451. package/src/interactive/cost-overlay.ts +66 -6
  452. package/src/interactive/council-grid.ts +1 -3
  453. package/src/interactive/council.ts +11 -0
  454. package/src/interactive/dispatch-board.ts +102 -20
  455. package/src/interactive/fleet-run-preview.ts +41 -15
  456. package/src/interactive/handoff-round.ts +41 -2
  457. package/src/interactive/interactive-application.ts +177 -7
  458. package/src/interactive/interactive-input-runtime.ts +15 -0
  459. package/src/interactive/interactive-presentation.ts +4 -0
  460. package/src/interactive/interactive-shell.ts +20 -17
  461. package/src/interactive/interactive-slash-runtime.ts +63 -10
  462. package/src/interactive/memory-overlay.ts +9 -0
  463. package/src/interactive/modal-marker.ts +170 -0
  464. package/src/interactive/mutation-preview.ts +295 -0
  465. package/src/interactive/mux-bridge.ts +214 -0
  466. package/src/interactive/overlay-frame.ts +58 -2
  467. package/src/interactive/overlay-general-openers.ts +17 -0
  468. package/src/interactive/overlay-key-routing.ts +52 -3
  469. package/src/interactive/overlay-lifecycle.ts +56 -7
  470. package/src/interactive/overlay-model-selectors.ts +40 -3
  471. package/src/interactive/overlay-permission-lifecycle.ts +112 -24
  472. package/src/interactive/overlay-session-lifecycle.ts +73 -9
  473. package/src/interactive/overlay-transitions.ts +18 -4
  474. package/src/interactive/overlays/agents.ts +1 -0
  475. package/src/interactive/overlays/ask-user.ts +227 -49
  476. package/src/interactive/overlays/auth-dialog.ts +1 -0
  477. package/src/interactive/overlays/context-reset.ts +1 -0
  478. package/src/interactive/overlays/cwd-fallback.ts +1 -0
  479. package/src/interactive/overlays/decisions.ts +11 -11
  480. package/src/interactive/overlays/extensions.ts +1 -0
  481. package/src/interactive/overlays/fleet-run-approval.ts +1 -0
  482. package/src/interactive/overlays/handoff-review.ts +1 -0
  483. package/src/interactive/overlays/help-reference.ts +6 -0
  484. package/src/interactive/overlays/interop.ts +1 -0
  485. package/src/interactive/overlays/library-install-confirm.ts +1 -0
  486. package/src/interactive/overlays/library-tabs.ts +28 -0
  487. package/src/interactive/overlays/list-overlay.ts +10 -1
  488. package/src/interactive/overlays/message-picker.ts +1 -0
  489. package/src/interactive/overlays/model-scope.ts +86 -0
  490. package/src/interactive/overlays/model-selector.ts +1 -0
  491. package/src/interactive/overlays/prompts.ts +12 -1
  492. package/src/interactive/overlays/session-selector.ts +1 -0
  493. package/src/interactive/overlays/settings-sections.ts +30 -0
  494. package/src/interactive/overlays/settings.ts +614 -45
  495. package/src/interactive/overlays/side-question.ts +1 -0
  496. package/src/interactive/overlays/skills-hub.ts +3 -11
  497. package/src/interactive/overlays/tree-selector.ts +1 -0
  498. package/src/interactive/pane-policy.ts +46 -0
  499. package/src/interactive/panes-runtime.ts +292 -0
  500. package/src/interactive/permission-hint.ts +34 -2
  501. package/src/interactive/permission-overlay.ts +159 -9
  502. package/src/interactive/prewarm.ts +197 -0
  503. package/src/interactive/render-trace.ts +162 -15
  504. package/src/interactive/renderers/compaction-summary.ts +29 -0
  505. package/src/interactive/renderers/tool-execution.ts +4 -0
  506. package/src/interactive/renderers/worker-entry.ts +122 -14
  507. package/src/interactive/side-question.ts +58 -1
  508. package/src/interactive/slash-commands.ts +251 -15
  509. package/src/interactive/status/controller.ts +11 -0
  510. package/src/interactive/status/state-machine.ts +54 -2
  511. package/src/interactive/status/types.ts +7 -0
  512. package/src/interactive/tasks-overlay.ts +1 -0
  513. package/src/interactive/terminal-lease.ts +2 -0
  514. package/src/interactive/theme/tokens.ts +3 -14
  515. package/src/interactive/turn-context.ts +346 -33
  516. package/src/interactive/turn-persistence.ts +14 -4
  517. package/src/interactive/turn-prewarm.ts +364 -0
  518. package/src/interactive/turn-queues.ts +7 -4
  519. package/src/interactive/turn-runtime.ts +8 -1
  520. package/src/interactive/turn-state.ts +23 -0
  521. package/src/interactive/view/artifacts.ts +109 -1
  522. package/src/interactive/view/view-overlay.ts +29 -3
  523. package/src/interactive/watch-pane.ts +152 -0
  524. package/src/interactive/worker-progress.ts +7 -1
  525. package/src/interactive/worker-receipts.ts +19 -1
  526. package/src/interactive/worker-stream.ts +5 -0
  527. package/src/interactive/yazi-bridge.ts +444 -0
  528. package/src/tools/ask-user.ts +43 -2
  529. package/src/tools/bootstrap.ts +26 -2
  530. package/src/tools/builtin-tool-catalog.ts +15 -0
  531. package/src/tools/compete-worktrees.ts +83 -2
  532. package/src/tools/core-bootstrap.ts +2 -1
  533. package/src/tools/dispatch-admission.ts +14 -3
  534. package/src/tools/dispatch-arguments.ts +20 -20
  535. package/src/tools/dispatch-plan.ts +17 -9
  536. package/src/tools/dispatch-run-events.ts +134 -19
  537. package/src/tools/dispatch-runner.ts +29 -7
  538. package/src/tools/dispatch-scout.ts +1 -1
  539. package/src/tools/dispatch-types.ts +15 -3
  540. package/src/tools/dispatch.ts +1 -1
  541. package/src/tools/executables.ts +17 -14
  542. package/src/tools/observation.ts +54 -4
  543. package/src/tools/panes-surface.ts +38 -0
  544. package/src/tools/panes.ts +112 -0
  545. package/src/tools/policy.ts +10 -1
  546. package/src/tools/presentation.ts +1 -0
  547. package/src/tools/registry.ts +16 -0
  548. package/dist/chunk-AOCYTWAV.js +0 -449
  549. package/dist/chunk-HLE42MG7.js +0 -37
  550. package/dist/chunk-HWUFFB6L.js +0 -83
  551. package/dist/chunk-JOZYP4GM.js +0 -279
  552. package/dist/doctor-M7YEDGAE.js +0 -91
@@ -105,6 +105,15 @@ export interface ResultContractFilesystem {
105
105
  * calling an unreadable path fabricated.
106
106
  */
107
107
  pathExists?(path: string): boolean;
108
+ /**
109
+ * Whether this location is a directory. Optional for the same reason as
110
+ * `pathExists`: a contract that only needs a file's bytes never asks. A
111
+ * Scout citation does, because a survey task cites directories, and a
112
+ * directory has no bytes to read and no line to ground. Absent means the
113
+ * distinction is unobservable here, so an unreadable location stays
114
+ * unreadable rather than being assumed to be a directory.
115
+ */
116
+ isDirectory?(path: string): boolean;
108
117
  }
109
118
 
110
119
  /**
@@ -792,6 +801,41 @@ function parseChecks(value: unknown): VerifierCheck[] | null {
792
801
 
793
802
  type ScoutCitationEvidence = ScoutCitation & { contentDigest: string };
794
803
 
804
+ /**
805
+ * Where a citation lands relative to the workspace root, after the written form
806
+ * is normalized away.
807
+ *
808
+ * A model writes the same location six ways: `src`, `./src`, `src/`, `./src/`,
809
+ * and for the root itself `.` or `./`. `path.resolve` collapses every one of
810
+ * them, so the containment question is answered on the resolved pair and never
811
+ * on the string the model typed.
812
+ *
813
+ * The root is the case that broke. `path.relative(cwd, cwd)` is the empty
814
+ * string, and the check read empty as "not inside", which is exactly backwards:
815
+ * the workspace root is the one path guaranteed to be contained. A
816
+ * directory-survey Scout cites `.` because that is what it surveyed, and four
817
+ * runs died `result_contract_exhausted` on evidence that never left the
818
+ * workspace. Containment is unchanged for a real escape, which still resolves
819
+ * to a `..` segment or an absolute path outside the root.
820
+ */
821
+ function citationWithinWorkspace(cwd: string, citedPath: string): boolean {
822
+ const relative = path.relative(cwd, citedPath);
823
+ if (relative === "") return true;
824
+ return !(relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative));
825
+ }
826
+
827
+ /**
828
+ * A directory citation carries no bytes and no line, so its evidence digest is
829
+ * bound to the location instead. Prefixed so it can never collide with the
830
+ * content digest of a file that happens to hold the same text.
831
+ */
832
+ function directoryCitationDigest(cwd: string, citedPath: string): string {
833
+ const relative = path.relative(cwd, citedPath);
834
+ return createHash("sha256")
835
+ .update(`directory:${relative === "" ? "." : relative}`, "utf8")
836
+ .digest("hex");
837
+ }
838
+
795
839
  /** One citation against the workspace and, where known, against this run's own reads. */
796
840
  function validateScoutCitation(
797
841
  input: ResultContractValidationInput,
@@ -799,10 +843,17 @@ function validateScoutCitation(
799
843
  ): { ok: true; evidence: ScoutCitationEvidence } | { ok: false; reason: string } {
800
844
  const cwd = path.resolve(input.cwd);
801
845
  const citedPath = path.resolve(cwd, citation.path);
802
- const relative = path.relative(cwd, citedPath);
803
- if (relative === "" || relative.startsWith(`..${path.sep}`) || relative === ".." || path.isAbsolute(relative)) {
846
+ if (!citationWithinWorkspace(cwd, citedPath)) {
804
847
  return { ok: false, reason: `Scout citation path escapes the workspace: ${citation.path}` };
805
848
  }
849
+ // A directory is a legal reconnaissance location. Existence is the whole
850
+ // check available: there is no content to digest, no line count to bound the
851
+ // cited line against, and no read span to ground it in, because a survey
852
+ // lists a directory rather than reading it. Requiring a live read here would
853
+ // reject the correct answer to every directory-survey task.
854
+ if (input.filesystem.isDirectory?.(citedPath) === true) {
855
+ return { ok: true, evidence: { ...citation, contentDigest: directoryCitationDigest(cwd, citedPath) } };
856
+ }
806
857
  const content = input.filesystem.readFile(citedPath);
807
858
  if (content === null) return { ok: false, reason: `Scout citation cannot be read: ${citation.path}` };
808
859
  const lineCount = content.split(/\r\n|\r|\n/u).length;
@@ -888,14 +939,57 @@ function groundDegradedScout(
888
939
 
889
940
  function validateVerifier(contract: ResultContract, output: string | null): ResultContractValidation {
890
941
  const parsed = parseJson(output);
891
- if (!parsed.ok) return failure(contract, "fail", parsed.reason);
942
+ if (!parsed.ok) return failure(contract, "fail", `Verifier result payload failed: ${parsed.reason}`);
892
943
  const value = parsed.value;
893
- if (!hasOnlyKeys(value, ["verdict", "checks"]) || (value.verdict !== "pass" && value.verdict !== "fail")) {
894
- return failure(contract, "fail", "Verifier result must carry pass or fail verdict and checks");
944
+ const unknown = Object.keys(value).filter((key) => key !== "verdict" && key !== "checks");
945
+ if (unknown.length > 0) {
946
+ return failure(
947
+ contract,
948
+ "fail",
949
+ `Verifier result field${unknown.length === 1 ? "" : "s"} ${unknown.join(", ")} ${unknown.length === 1 ? "is" : "are"} not legal; legal top-level fields are verdict and checks`,
950
+ );
895
951
  }
896
- const checks = parseChecks(value.checks);
897
- if (checks === null || (value.verdict === "pass") !== checks.every((check) => check.passed)) {
898
- return failure(contract, "fail", "Verifier verdict must agree with every typed check");
952
+ if (value.verdict !== "pass" && value.verdict !== "fail") {
953
+ return failure(contract, "fail", 'Verifier field "verdict" must be one of: pass | fail');
954
+ }
955
+ if (!Array.isArray(value.checks) || value.checks.length === 0) {
956
+ return failure(
957
+ contract,
958
+ "fail",
959
+ 'Verifier field "checks" must be a non-empty array of {name, passed, evidence}; each checks[].passed value must be one of: true | false',
960
+ );
961
+ }
962
+ const checks: VerifierCheck[] = [];
963
+ for (const [index, raw] of value.checks.entries()) {
964
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
965
+ return failure(contract, "fail", `Verifier field "checks[${index}]" must be an object`);
966
+ }
967
+ const check = raw as Record<string, unknown>;
968
+ const checkUnknown = Object.keys(check).filter((key) => key !== "name" && key !== "passed" && key !== "evidence");
969
+ if (checkUnknown.length > 0) {
970
+ return failure(
971
+ contract,
972
+ "fail",
973
+ `Verifier field "checks[${index}].${checkUnknown[0]}" is not legal; legal check fields are name, passed, and evidence`,
974
+ );
975
+ }
976
+ if (!string(check.name)) {
977
+ return failure(contract, "fail", `Verifier field "checks[${index}].name" must be a non-empty string`);
978
+ }
979
+ if (typeof check.passed !== "boolean") {
980
+ return failure(contract, "fail", `Verifier field "checks[${index}].passed" must be one of: true | false`);
981
+ }
982
+ if (!string(check.evidence)) {
983
+ return failure(contract, "fail", `Verifier field "checks[${index}].evidence" must be a non-empty string`);
984
+ }
985
+ checks.push({ name: check.name, passed: check.passed, evidence: check.evidence });
986
+ }
987
+ if ((value.verdict === "pass") !== checks.every((check) => check.passed)) {
988
+ return failure(
989
+ contract,
990
+ "fail",
991
+ 'Verifier field "verdict" must agree with every checks[].passed value; verdict legal values are pass | fail and checks[].passed legal values are true | false',
992
+ );
899
993
  }
900
994
  const verifier: VerifierResult = { verdict: value.verdict, checks };
901
995
  return success(contract, value.verdict, verifier, { verifier });
@@ -1086,23 +1180,39 @@ export function resultContractAuthorship(contract: ResultContract, output: strin
1086
1180
 
1087
1181
  function validateDebugger(contract: ResultContract, output: string | null): ResultContractValidation {
1088
1182
  const parsed = parseJson(output);
1089
- if (!parsed.ok) return failure(contract, "unmeasured", parsed.reason);
1183
+ if (!parsed.ok) return failure(contract, "unmeasured", `Debugger result payload failed: ${parsed.reason}`);
1090
1184
  const value = parsed.value;
1185
+ const unknown = Object.keys(value).filter(
1186
+ (key) => key !== "diagnosis" && key !== "reproduction" && key !== "evidence",
1187
+ );
1188
+ if (unknown.length > 0) {
1189
+ return failure(
1190
+ contract,
1191
+ "unmeasured",
1192
+ `Debugger result field${unknown.length === 1 ? "" : "s"} ${unknown.join(", ")} ${unknown.length === 1 ? "is" : "are"} not legal; legal top-level fields are diagnosis, reproduction, and evidence`,
1193
+ );
1194
+ }
1195
+ if (!string(value.diagnosis)) {
1196
+ return failure(contract, "unmeasured", 'Debugger field "diagnosis" must be a non-empty string');
1197
+ }
1091
1198
  if (
1092
- !hasOnlyKeys(value, ["diagnosis", "reproduction", "evidence"]) ||
1093
- !string(value.diagnosis) ||
1094
- (value.reproduction !== "reproduced" &&
1095
- value.reproduction !== "not-reproduced" &&
1096
- value.reproduction !== "unknown") ||
1097
- !Array.isArray(value.evidence) ||
1098
- value.evidence.some((entry) => !string(entry))
1199
+ value.reproduction !== "reproduced" &&
1200
+ value.reproduction !== "not-reproduced" &&
1201
+ value.reproduction !== "unknown"
1099
1202
  ) {
1100
1203
  return failure(
1101
1204
  contract,
1102
1205
  "unmeasured",
1103
- "Debugger result must carry diagnosis, reproduction status, and evidence without a verdict",
1206
+ 'Debugger field "reproduction" must be one of: reproduced | not-reproduced | unknown',
1104
1207
  );
1105
1208
  }
1209
+ if (!Array.isArray(value.evidence)) {
1210
+ return failure(contract, "unmeasured", 'Debugger field "evidence" must be an array of strings');
1211
+ }
1212
+ const malformedEvidence = value.evidence.findIndex((entry) => !string(entry));
1213
+ if (malformedEvidence >= 0) {
1214
+ return failure(contract, "unmeasured", `Debugger field "evidence[${malformedEvidence}]" must be a non-empty string`);
1215
+ }
1106
1216
  return success(contract, "unmeasured", value);
1107
1217
  }
1108
1218
 
@@ -1112,29 +1222,47 @@ function validateResearch(
1112
1222
  networkAllowed: boolean,
1113
1223
  ): ResultContractValidation {
1114
1224
  const parsed = parseJson(output);
1115
- if (!parsed.ok) return failure(contract, "unmeasured", parsed.reason);
1225
+ if (!parsed.ok) return failure(contract, "unmeasured", `Research result payload failed: ${parsed.reason}`);
1116
1226
  const value = parsed.value;
1117
- if (
1118
- !hasOnlyKeys(value, ["source", "findings"]) ||
1119
- (value.source !== "local" && value.source !== "external") ||
1120
- !Array.isArray(value.findings)
1121
- ) {
1227
+ const unknown = Object.keys(value).filter((key) => key !== "source" && key !== "findings");
1228
+ if (unknown.length > 0) {
1122
1229
  return failure(
1123
1230
  contract,
1124
1231
  "unmeasured",
1125
- "Research result must distinguish local or external sources and carry findings",
1232
+ `Research result field${unknown.length === 1 ? "" : "s"} ${unknown.join(", ")} ${unknown.length === 1 ? "is" : "are"} not legal; legal top-level fields are source and findings`,
1126
1233
  );
1127
1234
  }
1235
+ if (value.source !== "local" && value.source !== "external") {
1236
+ return failure(contract, "unmeasured", 'Research field "source" must be one of: local | external');
1237
+ }
1238
+ if (!Array.isArray(value.findings)) {
1239
+ return failure(contract, "unmeasured", 'Research field "findings" must be an array of {claim, evidence} objects');
1240
+ }
1128
1241
  if (value.source === "external" && !networkAllowed) {
1129
- return failure(contract, "unmeasured", "external research requires an allowed network posture");
1242
+ return failure(
1243
+ contract,
1244
+ "unmeasured",
1245
+ 'Research field "source" is external but the run has no allowed network posture; legal values are local | external, and use local for workspace-only evidence',
1246
+ );
1130
1247
  }
1131
- for (const finding of value.findings) {
1248
+ for (const [index, finding] of value.findings.entries()) {
1132
1249
  if (finding === null || typeof finding !== "object" || Array.isArray(finding)) {
1133
- return failure(contract, "unmeasured", "Research findings must be objects");
1250
+ return failure(contract, "unmeasured", `Research field "findings[${index}]" must be an object`);
1134
1251
  }
1135
1252
  const record = finding as Record<string, unknown>;
1136
- if (!hasOnlyKeys(record, ["claim", "evidence"]) || !string(record.claim) || !string(record.evidence)) {
1137
- return failure(contract, "unmeasured", "Research findings must carry claim and evidence");
1253
+ const findingUnknown = Object.keys(record).filter((key) => key !== "claim" && key !== "evidence");
1254
+ if (findingUnknown.length > 0) {
1255
+ return failure(
1256
+ contract,
1257
+ "unmeasured",
1258
+ `Research field "findings[${index}].${findingUnknown[0]}" is not legal; legal finding fields are claim and evidence`,
1259
+ );
1260
+ }
1261
+ if (!string(record.claim)) {
1262
+ return failure(contract, "unmeasured", `Research field "findings[${index}].claim" must be a non-empty string`);
1263
+ }
1264
+ if (!string(record.evidence)) {
1265
+ return failure(contract, "unmeasured", `Research field "findings[${index}].evidence" must be a non-empty string`);
1138
1266
  }
1139
1267
  }
1140
1268
  return success(contract, "unmeasured", value);
@@ -1415,10 +1543,11 @@ export const RESULT_CONTRACT_ANCHOR_LIMIT = 12;
1415
1543
 
1416
1544
  /**
1417
1545
  * The exact terminal shape each contract accepts, quoted to the model verbatim.
1418
- * This is the one place a contract's wire example is written; agent recipes and
1419
- * repair rounds both cite it, so a prompt cannot drift from its validator.
1546
+ * This is the one place a contract's wire example is written; agent recipes,
1547
+ * repair rounds, and a fleet node's own answer directive all cite it, so a
1548
+ * prompt cannot drift from its validator.
1420
1549
  */
1421
- function resultContractShape(contract: ResultContract): string {
1550
+ export function resultContractShape(contract: ResultContract): string {
1422
1551
  switch (contract.kind) {
1423
1552
  case "architect-plan":
1424
1553
  return `a plan artifact written to ${contract.path}, then optionally {"commitMessage":"...","summary":"..."} describing it`;
@@ -1428,15 +1557,15 @@ function resultContractShape(contract: ResultContract): string {
1428
1557
  // run already failed twice, so it is told the cheaper exit as well.
1429
1558
  return '{"findings":[{"claim":"what you observed","path":"src/file.ts","line":1}],"needsSplit":false,"proposedSubtasks":[]} or {"findings":[],"needsSplit":true,"proposedSubtasks":[{"id":"inspect","task":"Inspect the boundary","dependencies":[],"expectedResultContract":"scout-report","requestedAuthority":"read-only"}]} or, if you cannot produce a citation you are sure of, at least {"findings":[{"claim":"what you observed"}]}, which is accepted as an ungrounded lead rather than losing the run';
1430
1559
  case "verifier-report":
1431
- return '{"verdict":"pass","checks":[{"name":"npm run typecheck","passed":true,"evidence":"exit 0"}]}';
1560
+ return 'one of {"verdict":"pass","checks":[{"name":"npm run typecheck","passed":true,"evidence":"exit 0"}]} or {"verdict":"fail","checks":[{"name":"npm run typecheck","passed":false,"evidence":"exit 1"}]}; verdict legal values are pass | fail and checks[].passed legal values are true | false';
1432
1561
  case "council-report":
1433
1562
  return '{"members":[{"label":"alpha","runId":"run-1","round":1,"answer":"..."}],"synthesis":{"kind":"none"}}';
1434
1563
  case "council-ballot":
1435
1564
  return COUNCIL_BALLOT_SHAPE;
1436
1565
  case "debugger-report":
1437
- return '{"diagnosis":"...","reproduction":"reproduced","evidence":["..."]}';
1566
+ return 'one of {"diagnosis":"...","reproduction":"reproduced","evidence":["..."]}, {"diagnosis":"...","reproduction":"not-reproduced","evidence":["..."]}, or {"diagnosis":"...","reproduction":"unknown","evidence":["..."]}; reproduction legal values are reproduced | not-reproduced | unknown';
1438
1567
  case "research-report":
1439
- return '{"source":"local","findings":[{"claim":"...","evidence":"..."}]}';
1568
+ return 'one of {"source":"local","findings":[{"claim":"...","evidence":"..."}]} or {"source":"external","findings":[{"claim":"...","evidence":"..."}]}; source legal values are local | external';
1440
1569
  case "mutation-report":
1441
1570
  return '{"mutatedPaths":["src/file.ts"],"validations":[{"name":"npm test","passed":true,"evidence":"exit 0"}],"commitMessage":"optional: the commit message for this change","summary":"optional: one line"}';
1442
1571
  case "provenance-report":
@@ -28,6 +28,9 @@ const HOT_RELOAD_FIELDS = new Set<string>([
28
28
  "modelSelector",
29
29
  "terminal.smoothStreaming",
30
30
  "attribution.gitCommits",
31
+ // The bridge reads these on every explicit open; no mux re-detection is
32
+ // needed because the host capability rung remains `panes.enabled`.
33
+ "panes.yazi",
31
34
  // The watchdog registration reads its settings live on every trigger, so
32
35
  // enabling it, retargeting it, or changing its cadence takes effect on the
33
36
  // next turn boundary without a restart or a session-routing patch.
@@ -61,6 +64,9 @@ const NEXT_TURN_FIELDS = new Set<string>([
61
64
  "delegation",
62
65
  "compaction",
63
66
  "context",
67
+ // The pre-warm reads its setting when a trigger fires, and every trigger sits
68
+ // on a turn boundary, so a change takes effect before the next turn runs.
69
+ "prewarm",
64
70
  "retry",
65
71
  ]);
66
72
 
@@ -140,8 +140,16 @@ export function coordinateCodewikiWrite(
140
140
  options: CodewikiCoordinateOptions = {},
141
141
  ): Promise<CodewikiCoordinatedResult | null> {
142
142
  const workspace = resolve(cwd);
143
- return enqueueWorkspace(workspace, () =>
144
- withStateFileLock(codewikiPath(workspace), async () => {
143
+ return enqueueWorkspace(workspace, () => {
144
+ // Taking the lease creates the lock's parent, so a project that was never
145
+ // indexed gained an empty `.clio-coder/` from every successful write: the
146
+ // incremental refresh is contractually a no-op there, and it was
147
+ // materializing state before it could say so (issue #248). The check runs
148
+ // inside the queue, so a writer that built the codewiki ahead of this task
149
+ // has already finished and this one sees it. The recheck under the lock
150
+ // stays, and is what still decides the race.
151
+ if (options.requireExisting && !existsSync(codewikiPath(workspace))) return Promise.resolve(null);
152
+ return withStateFileLock(codewikiPath(workspace), async () => {
145
153
  if (options.requireExisting && !existsSync(codewikiPath(workspace))) return null;
146
154
  const current = options.readCurrent?.(workspace) ?? readCodewiki(workspace);
147
155
  const request = await select(current, workspace);
@@ -152,8 +160,8 @@ export function coordinateCodewikiWrite(
152
160
  if (wrote) writeCodewiki(workspace, worker.codewiki);
153
161
  await options.afterCommit?.(worker, workspace);
154
162
  return { codewiki: !worker.changed && current ? current : worker.codewiki, worker, wrote };
155
- }),
156
- );
163
+ });
164
+ });
157
165
  }
158
166
 
159
167
  /** Serialize a non-build artifact transaction such as reset with every writer. */
@@ -0,0 +1,9 @@
1
+ /** A queued assignment was intentionally canceled before it acquired capacity. */
2
+ export class AdmissionCanceledError extends Error {
3
+ readonly code = "admission_canceled" as const;
4
+
5
+ constructor(message = "dispatch: admission canceled before a capacity slot opened") {
6
+ super(message);
7
+ this.name = "AdmissionCanceledError";
8
+ }
9
+ }
@@ -1,12 +1,16 @@
1
1
  import { randomBytes } from "node:crypto";
2
+ import { endpointLabel } from "../providers/endpoint-capacity.js";
2
3
  import type { ActionClass } from "../safety/action-classifier.js";
3
4
  import type { ScopeSpec } from "../safety/scope.js";
5
+ import { AdmissionCanceledError } from "./admission-error.js";
4
6
  import { createAdmissionQueue } from "./admission-queue.js";
5
7
  import {
6
8
  acquireCapacityLease,
7
9
  type CapacityLease,
8
10
  type CapacityLimits,
9
11
  capacityLeaseUsage,
12
+ describeEndpointCapacityHolders,
13
+ type EndpointCapacityHolders,
10
14
  heartbeatCapacityLease,
11
15
  releaseCapacityLease,
12
16
  renameCapacityLeaseAssignment,
@@ -41,6 +45,7 @@ export interface CapacityAdmissionController {
41
45
  admit(input: {
42
46
  assignmentId: string;
43
47
  nodeId: string;
48
+ endpointKey?: string;
44
49
  deadlineAt: number;
45
50
  priority?: number;
46
51
  planId?: string;
@@ -105,13 +110,36 @@ const PUMP_MAX_MS = 500;
105
110
  function describeAdmissionFailure(input: {
106
111
  state: "canceled" | "timed_out";
107
112
  nodeId: string;
113
+ endpointKey?: string;
108
114
  waitedMs: number;
109
115
  overdueAtQueueMs: number;
110
116
  queueDepth: number;
111
117
  limits: CapacityLimits;
112
- usage: { global: number; nodes: Readonly<Record<string, number>> };
118
+ usage: {
119
+ global: number;
120
+ nodes: Readonly<Record<string, number>>;
121
+ endpoints: Readonly<Record<string, number>>;
122
+ endpointHolders?: Readonly<Record<string, EndpointCapacityHolders>>;
123
+ };
113
124
  }): string {
114
125
  if (input.state === "canceled") return "dispatch: admission canceled before a capacity slot opened";
126
+ if (input.endpointKey !== undefined) {
127
+ const endpointLimit = input.limits.endpoints[input.endpointKey];
128
+ const endpointActive = input.usage.endpoints[input.endpointKey] ?? 0;
129
+ if (endpointLimit !== undefined && endpointActive >= endpointLimit) {
130
+ const holders = input.usage.endpointHolders?.[input.endpointKey];
131
+ const occupancy =
132
+ holders === undefined
133
+ ? "the supplied capacity snapshot does not attribute the occupied slots"
134
+ : describeEndpointCapacityHolders(holders);
135
+ const queued = input.queueDepth > 0 ? `, ${input.queueDepth} more queued` : "";
136
+ return [
137
+ `dispatch: admission timed out after ${Math.round(input.waitedMs)}ms waiting for an endpoint slot`,
138
+ ` on '${endpointLabel(input.endpointKey)}' (${endpointActive}/${endpointLimit} slots${queued}): ${occupancy}.`,
139
+ " Wait for the running request to settle or dispatch this work again.",
140
+ ].join("");
141
+ }
142
+ }
115
143
  const nodeLimit = input.limits.nodes[input.nodeId];
116
144
  const nodeActive = input.usage.nodes[input.nodeId] ?? 0;
117
145
  const where =
@@ -142,7 +170,12 @@ function describeAdmissionFailure(input: {
142
170
  export function createCapacityAdmissionController(options: {
143
171
  limits: () => CapacityLimits;
144
172
  /** Live lease counts for the timeout message; defaults to the durable state file. */
145
- usage?: () => { global: number; nodes: Readonly<Record<string, number>> };
173
+ usage?: () => {
174
+ global: number;
175
+ nodes: Readonly<Record<string, number>>;
176
+ endpoints: Readonly<Record<string, number>>;
177
+ endpointHolders?: Readonly<Record<string, EndpointCapacityHolders>>;
178
+ };
146
179
  now?: () => number;
147
180
  maxQueueSize?: number;
148
181
  queueCeilingMs?: number;
@@ -175,7 +208,9 @@ export function createCapacityAdmissionController(options: {
175
208
  admittedLease = request.value();
176
209
  return true;
177
210
  } catch (error) {
178
- // Capacity is a wait, not a failure. Anything else fails the request.
211
+ // Saturation at any capacity dimension is transient and keeps its
212
+ // assignment in the one bounded admission queue. Unavailable capacity,
213
+ // draining, corrupt state, and every other error still fail immediately.
179
214
  if (error instanceof Error && /capacity reached/.test(error.message)) return false;
180
215
  queue.fail(request.requestId, error instanceof Error ? error : new Error(String(error)));
181
216
  return false;
@@ -229,12 +264,14 @@ export function createCapacityAdmissionController(options: {
229
264
  memberId: input.reservation.memberId,
230
265
  assignmentId: input.assignmentId,
231
266
  nodeId: input.nodeId,
267
+ ...(input.endpointKey !== undefined ? { endpointKey: input.endpointKey } : {}),
232
268
  limits: options.limits(),
233
269
  nowMs: now(),
234
270
  })
235
271
  : acquireCapacityLease({
236
272
  assignmentId: input.assignmentId,
237
273
  nodeId: input.nodeId,
274
+ ...(input.endpointKey !== undefined ? { endpointKey: input.endpointKey } : {}),
238
275
  limits: options.limits(),
239
276
  nowMs: now(),
240
277
  }),
@@ -242,17 +279,18 @@ export function createCapacityAdmissionController(options: {
242
279
  pumpNow();
243
280
  const outcome = await outcomePromise;
244
281
  if (outcome.state !== "admitted") {
245
- throw new Error(
246
- describeAdmissionFailure({
247
- state: outcome.state,
248
- nodeId: input.nodeId,
249
- waitedMs: now() - queuedAt,
250
- overdueAtQueueMs: queuedAt - input.deadlineAt,
251
- queueDepth: queue.size(),
252
- limits: options.limits(),
253
- usage: options.usage?.() ?? capacityLeaseUsage({ nowMs: now() }),
254
- }),
255
- );
282
+ const detail = describeAdmissionFailure({
283
+ state: outcome.state,
284
+ nodeId: input.nodeId,
285
+ ...(input.endpointKey !== undefined ? { endpointKey: input.endpointKey } : {}),
286
+ waitedMs: now() - queuedAt,
287
+ overdueAtQueueMs: queuedAt - input.deadlineAt,
288
+ queueDepth: queue.size(),
289
+ limits: options.limits(),
290
+ usage: options.usage?.() ?? capacityLeaseUsage({ nowMs: now() }),
291
+ });
292
+ if (outcome.state === "canceled") throw new AdmissionCanceledError(detail);
293
+ throw new Error(detail);
256
294
  }
257
295
  const lease = acquired.get(input.assignmentId);
258
296
  if (!lease) throw new Error("dispatch: admitted request has no capacity lease");