@iowarp/clio-coder 0.3.7 → 0.3.9

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 (400) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/README.md +13 -4
  3. package/dist/{acp-SK4MD6MM.js → acp-7LOELQFP.js} +13 -13
  4. package/dist/{agents-2FN2K6ME.js → agents-FIBG2SHA.js} +41 -37
  5. package/dist/assets/codewiki.json +1 -1
  6. package/dist/{auth-QIYZWM5I.js → auth-OI4LIH2I.js} +31 -24
  7. package/dist/builtins-AD25UL3C.js +17 -0
  8. package/dist/{chunk-5FR74PWO.js → chunk-2JDWVJND.js} +2 -2
  9. package/dist/chunk-3DPEIQKN.js +113 -0
  10. package/dist/{chunk-EOOQZZDE.js → chunk-3DUR4WUA.js} +19 -19
  11. package/dist/{chunk-WHJYKASB.js → chunk-3MRC2YSQ.js} +2 -2
  12. package/dist/{chunk-EBEFWSGL.js → chunk-3UUY7R3Z.js} +14 -10
  13. package/dist/{chunk-LADCF22A.js → chunk-3V5AYSEQ.js} +113 -54
  14. package/dist/{chunk-BMWK7ZIZ.js → chunk-465CC7FK.js} +16 -13
  15. package/dist/{chunk-5WIGXA4T.js → chunk-47CMYGET.js} +111 -4
  16. package/dist/{chunk-CEYBNUGC.js → chunk-4H6ULJ3H.js} +378 -36
  17. package/dist/{chunk-YTYFXUI3.js → chunk-4LJX2PUC.js} +9 -9
  18. package/dist/{chunk-DOOEX22V.js → chunk-56KB5IJP.js} +5 -5
  19. package/dist/{chunk-SPULKLCF.js → chunk-5DQRIYDZ.js} +2 -2
  20. package/dist/{chunk-TSHXZTOQ.js → chunk-5HFBWUMU.js} +23 -11
  21. package/dist/{chunk-5UJ6ECTS.js → chunk-5PVQ4SRS.js} +80 -8
  22. package/dist/{chunk-ZWLZP4ZT.js → chunk-5QKCQQ3E.js} +359 -17
  23. package/dist/{chunk-6M7VS3J3.js → chunk-5T7RBWN2.js} +111 -5
  24. package/dist/chunk-774ILSRL.js +172 -0
  25. package/dist/chunk-7C6RYZGQ.js +391 -0
  26. package/dist/{chunk-GH5622CP.js → chunk-A2NJGIB3.js} +2 -2
  27. package/dist/{chunk-C4JBQ5SR.js → chunk-AD7Y7STJ.js} +6 -6
  28. package/dist/{chunk-GEYXPTRF.js → chunk-AEYBF3TB.js} +33 -12
  29. package/dist/{chunk-2SFS6XQE.js → chunk-AMKHQW3C.js} +3 -2
  30. package/dist/{chunk-D4MDIG46.js → chunk-B5CSFE7B.js} +7 -7
  31. package/dist/{chunk-MXI6J5JF.js → chunk-B5XRQOLB.js} +10 -10
  32. package/dist/{chunk-X2KV5FXT.js → chunk-BVDVID7E.js} +2 -2
  33. package/dist/{chunk-JNXPYBB4.js → chunk-CA42X6KT.js} +3 -3
  34. package/dist/{chunk-VREKEFLL.js → chunk-D73KXYPF.js} +3 -3
  35. package/dist/{chunk-JTSEDYVQ.js → chunk-DG4M6ZUE.js} +7 -7
  36. package/dist/{chunk-DQA7QLMD.js → chunk-EBOC7MT3.js} +10 -25
  37. package/dist/{chunk-KZ2H5X4G.js → chunk-ECUO3KDP.js} +129 -14
  38. package/dist/{chunk-JRIO5UD2.js → chunk-EQ63NRB7.js} +5 -5
  39. package/dist/{chunk-YD734TPH.js → chunk-FALJGAWU.js} +2 -2
  40. package/dist/{chunk-GWS3VEIW.js → chunk-FWDFM5ZU.js} +24 -3
  41. package/dist/{chunk-XEGB6BCN.js → chunk-GAYUJ7LE.js} +68 -14
  42. package/dist/{chunk-UND3GU2L.js → chunk-H7IXIC72.js} +2 -2
  43. package/dist/{chunk-IR4CFBFN.js → chunk-HAY4ZE2P.js} +12 -12
  44. package/dist/{chunk-UVDSQ6LW.js → chunk-HCBCAYZU.js} +74 -147
  45. package/dist/{chunk-4DWFMQDR.js → chunk-HJB5IUKP.js} +89 -145
  46. package/dist/{chunk-M4AKACEO.js → chunk-HKO36JWF.js} +33 -5
  47. package/dist/{chunk-KCMKRQX4.js → chunk-HPCTNZM2.js} +45 -82
  48. package/dist/{chunk-465YSENW.js → chunk-IFBNV6H6.js} +3 -3
  49. package/dist/{chunk-FJ3H4MN5.js → chunk-IHKBWSXF.js} +2 -2
  50. package/dist/chunk-JEQQR47K.js +3025 -0
  51. package/dist/{chunk-FO5ZOVUY.js → chunk-KV2AOLDF.js} +27 -7
  52. package/dist/chunk-LU7P4LHA.js +33 -0
  53. package/dist/{chunk-6TUKSZVF.js → chunk-LXPJXFM5.js} +11 -11
  54. package/dist/{chunk-VQNODYQ4.js → chunk-MIX5N5AC.js} +488 -3668
  55. package/dist/chunk-MLOK6ZOS.js +2888 -0
  56. package/dist/{chunk-ZZMN5OM4.js → chunk-MV2VUEJC.js} +2 -2
  57. package/dist/{chunk-MVVUPGPW.js → chunk-MXHC5QYU.js} +6 -6
  58. package/dist/{chunk-OBMAI2DP.js → chunk-N3PBVRTZ.js} +12 -388
  59. package/dist/{chunk-WJHBC77E.js → chunk-N5XKWMDW.js} +17 -7
  60. package/dist/{chunk-5C3AQNDW.js → chunk-NNNWO6F2.js} +124 -36
  61. package/dist/{chunk-UFQ3F4FW.js → chunk-NQ6UCCOD.js} +4 -4
  62. package/dist/chunk-NUGM5KR6.js +165 -0
  63. package/dist/{chunk-DMD2AGVS.js → chunk-NZU6YDNV.js} +20 -18
  64. package/dist/{chunk-WHGPSPT5.js → chunk-O6I4CIEU.js} +151 -13
  65. package/dist/{chunk-XN3L4EYL.js → chunk-OEDBCISO.js} +2 -2
  66. package/dist/{chunk-PD3MESLB.js → chunk-P3JGPQFL.js} +4 -4
  67. package/dist/{chunk-UHXRNZ2J.js → chunk-PNY46YEY.js} +23 -6
  68. package/dist/{chunk-THKY7CD7.js → chunk-PZ4I4JE2.js} +134 -29
  69. package/dist/{chunk-SROCI7ZU.js → chunk-QQ7EKM72.js} +5 -5
  70. package/dist/{chunk-QCTRSGHQ.js → chunk-R7LNVMCS.js} +91 -53
  71. package/dist/{chunk-GOXNB3AO.js → chunk-RAPCMZL4.js} +75 -4
  72. package/dist/chunk-RKKLTLYB.js +45 -0
  73. package/dist/{chunk-OB5HIGJY.js → chunk-RKRLDWD3.js} +4 -1
  74. package/dist/{chunk-DJNLUABN.js → chunk-S4COXYBG.js} +588 -32
  75. package/dist/{chunk-3HAPLH5M.js → chunk-T3Z6VAAF.js} +172 -11
  76. package/dist/{chunk-FOT2FX5J.js → chunk-TD7UE2L5.js} +12 -10
  77. package/dist/{chunk-UUANF5CR.js → chunk-TEO2TLVN.js} +856 -967
  78. package/dist/{chunk-FCSXB6T2.js → chunk-UOSL25KY.js} +14 -2
  79. package/dist/{chunk-EELBMBT6.js → chunk-VKBMFOYV.js} +74 -15
  80. package/dist/chunk-VO2LKSTM.js +165 -0
  81. package/dist/{chunk-5C77SEEY.js → chunk-VPTUJU4P.js} +3 -3
  82. package/dist/{chunk-WEH5XRJQ.js → chunk-WIE7ZOSW.js} +2 -2
  83. package/dist/{chunk-J7PIKKWC.js → chunk-WXCJ7VME.js} +8 -8
  84. package/dist/{chunk-4DGYLA73.js → chunk-XDOQXGFO.js} +22 -7
  85. package/dist/{chunk-PPAMZ32Z.js → chunk-XK56QHLX.js} +6 -1
  86. package/dist/{chunk-AB4XIIVB.js → chunk-YKOFT37S.js} +6 -6
  87. package/dist/chunk-YSEHGPCT.js +127 -0
  88. package/dist/{chunk-HFSBBKSQ.js → chunk-YW7UVM5V.js} +138 -3
  89. package/dist/cli/index.js +32 -32
  90. package/dist/{clio-WBVQEBKO.js → clio-LT5V7SSZ.js} +9 -9
  91. package/dist/{code-nav-FGGFIE7L.js → code-nav-LMW275PA.js} +5 -5
  92. package/dist/codewiki/build-worker.js +4 -4
  93. package/dist/{components-F7OEATSO.js → components-ZFA3SAER.js} +8 -8
  94. package/dist/{config-TRBL3RCF.js → config-RXS5T3JT.js} +98 -65
  95. package/dist/{configure-OLCVPHNM.js → configure-2WYWSCSD.js} +26 -22
  96. package/dist/{context-MJIJ6GOX.js → context-I3BTOTCS.js} +12 -12
  97. package/dist/{context-XEWE3MOJ.js → context-MVOORGMF.js} +54 -47
  98. package/dist/{context-WFPKQSM6.js → context-PALKKQYL.js} +28 -28
  99. package/dist/{context-clear-KNOS2JPB.js → context-clear-N2WOYZ2K.js} +53 -46
  100. package/dist/{context-index-SSR5ECNE.js → context-index-HNG3MOME.js} +6 -6
  101. package/dist/{context-working-set-EUXAZI6N.js → context-working-set-MIEVECVZ.js} +17 -18
  102. package/dist/{dispatch-runner-B7MTOVKL.js → dispatch-runner-VVA4SRRH.js} +90 -61
  103. package/dist/{docs-FLJTIDSE.js → docs-7LQ23DLM.js} +8 -8
  104. package/dist/doctor-TWBWFK5V.js +165 -0
  105. package/dist/eval-IJ5VEZDJ.js +4483 -0
  106. package/dist/{evidence-JZNBUOQZ.js → evidence-L5APPXNV.js} +68 -61
  107. package/dist/{evolve-FJVC4KKI.js → evolve-RGNKFJ52.js} +47 -40
  108. package/dist/{extensions-IQL36S7K.js → extensions-7WYWUX5A.js} +13 -7
  109. package/dist/{fleet-BDKYJFCP.js → fleet-6CNVBZZP.js} +113 -76
  110. package/dist/{fleet-commands-ZFIWZSB3.js → fleet-commands-L2SXSYEI.js} +10 -10
  111. package/dist/{fleet-graph-Y6HPXIVF.js → fleet-graph-2J3OOIPO.js} +17 -15
  112. package/dist/{fleet-preflight-BHSNPBMH.js → fleet-preflight-CZRJ4JP5.js} +5 -6
  113. package/dist/{fleet-validate-BIYREGIK.js → fleet-validate-C5RI6DP7.js} +20 -19
  114. package/dist/{init-LQUB5COQ.js → init-VBN2ACVA.js} +70 -63
  115. package/dist/{library-NJAHIGG4.js → library-JHGUMLY2.js} +22 -20
  116. package/dist/{memory-OG6HOYKM.js → memory-K4OQIYWG.js} +49 -42
  117. package/dist/{models-5ZG5XY7J.js → models-2NCZUWDD.js} +35 -29
  118. package/dist/{monitor-TJ7AMTGB.js → monitor-MMVTJABD.js} +64 -45
  119. package/dist/{orchestrator-WZYB54DM.js → orchestrator-ZKBPCHW6.js} +1971 -520
  120. package/dist/{paths-XUC7GS6E.js → paths-DBXMZMDU.js} +5 -5
  121. package/dist/registry-LG64LTF4.js +11 -0
  122. package/dist/{reset-PXQT45IY.js → reset-DD5JGOY3.js} +11 -11
  123. package/dist/{run-FQ74YF62.js → run-QEGNX7FL.js} +89 -83
  124. package/dist/{share-FW7SVCL3.js → share-JKD3BQMW.js} +20 -18
  125. package/dist/{skills-7E7IRB3R.js → skills-LMQIKDOZ.js} +23 -21
  126. package/dist/{skills-eval-LI75W6OK.js → skills-eval-I7X2774U.js} +59 -52
  127. package/dist/{steer-GGWFUJUD.js → steer-CF5TDANS.js} +3 -3
  128. package/dist/support-I7LOJLIF.js +38 -0
  129. package/dist/{targets-4CIFKCTW.js → targets-RUSR6B5Z.js} +77 -42
  130. package/dist/{terminal-lease-WUZY7ZV5.js → terminal-lease-QYVORFR4.js} +6 -4
  131. package/dist/{trace-PNCASAXC.js → trace-ODOQIVIW.js} +61 -6
  132. package/dist/{uninstall-7FV7IP4E.js → uninstall-ZJF5H5ZN.js} +8 -8
  133. package/dist/{upgrade-K2HVIVMQ.js → upgrade-XANW3FXB.js} +29 -26
  134. package/dist/{usage-GTZELZQX.js → usage-4H7ZRXQT.js} +110 -61
  135. package/dist/{verifiers-RLAHT27O.js → verifiers-UZXNBZEB.js} +13 -13
  136. package/dist/{verify-BX3BRKH5.js → verify-BVKWTNDL.js} +9 -9
  137. package/dist/{wiki-generate-ASIFASCN.js → wiki-generate-MY7WV2QI.js} +76 -69
  138. package/dist/worker/entry.js +69 -66
  139. package/docs/alcf-provider.md +1 -1
  140. package/docs/architecture.md +1 -1
  141. package/docs/artifact-versions.md +11 -5
  142. package/docs/built-in-agents.md +1 -1
  143. package/docs/capacity-and-scheduling.md +23 -2
  144. package/docs/commands-and-modes.md +2 -2
  145. package/docs/configuration-and-targets.md +37 -5
  146. package/docs/context-engine.md +63 -4
  147. package/docs/documentation-coverage.md +3 -3
  148. package/docs/documentation-guide.md +1 -1
  149. package/docs/environment-variables.md +2 -0
  150. package/docs/eval-runner.md +262 -11
  151. package/docs/evals-internal.md +72 -2
  152. package/docs/evidence-and-memory.md +77 -12
  153. package/docs/evolution.md +1 -1
  154. package/docs/extensions-and-sharing.md +3 -1
  155. package/docs/fleet-dispatch.md +34 -9
  156. package/docs/glossary.md +21 -1
  157. package/docs/installation-and-lifecycle.md +1 -1
  158. package/docs/middleware-and-components.md +1 -1
  159. package/docs/model-catalog.md +1 -1
  160. package/docs/observability.md +54 -3
  161. package/docs/proactive-memory.md +127 -14
  162. package/docs/prompt-envelope-and-tools.md +22 -2
  163. package/docs/provider-adapter-cookbook.md +1 -1
  164. package/docs/release-cut-checklist.md +60 -41
  165. package/docs/safety-model.md +1 -1
  166. package/docs/scientific-validation.md +1 -1
  167. package/docs/skills-marketplace.md +1 -1
  168. package/docs/tool-usage.md +1 -1
  169. package/docs/trace-store.md +1 -1
  170. package/docs/troubleshooting.md +87 -0
  171. package/docs/tui-design.md +1 -1
  172. package/docs/worker-dispatch-mechanics.md +1 -1
  173. package/package.json +2 -2
  174. package/src/cli/agents.ts +1 -1
  175. package/src/cli/argv.ts +5 -0
  176. package/src/cli/config-inspect.ts +33 -6
  177. package/src/cli/config.ts +1 -1
  178. package/src/cli/configure.ts +107 -23
  179. package/src/cli/doctor-state-size.ts +82 -0
  180. package/src/cli/doctor.ts +7 -1
  181. package/src/cli/eval.ts +80 -16
  182. package/src/cli/evidence.ts +30 -25
  183. package/src/cli/extensions.ts +5 -1
  184. package/src/cli/fleet-preflight.ts +2 -12
  185. package/src/cli/fleet.ts +32 -3
  186. package/src/cli/shared.ts +1 -0
  187. package/src/cli/targets.ts +45 -11
  188. package/src/cli/trace.ts +63 -4
  189. package/src/cli/usage.ts +63 -14
  190. package/src/cli/validate-model.ts +60 -5
  191. package/src/core/bus-events.ts +54 -1
  192. package/src/core/cache-telemetry.ts +42 -0
  193. package/src/core/commit-attribution.ts +4 -4
  194. package/src/core/config.ts +18 -0
  195. package/src/core/defaults.ts +36 -6
  196. package/src/core/endpoint-key.ts +27 -0
  197. package/src/core/path-boundary.ts +100 -0
  198. package/src/core/residency-target-key.ts +25 -0
  199. package/src/core/response-schema.ts +36 -2
  200. package/src/domains/agents/extension.ts +2 -11
  201. package/src/domains/agents/fleet-contract.ts +30 -12
  202. package/src/domains/agents/recipe.ts +7 -1
  203. package/src/domains/agents/registry.ts +73 -5
  204. package/src/domains/agents/result-contract.ts +128 -17
  205. package/src/domains/agents/write-boundary.ts +15 -50
  206. package/src/domains/config/classify.ts +3 -0
  207. package/src/domains/context/codewiki/coordinator.ts +12 -4
  208. package/src/domains/context/project-rules.ts +51 -1
  209. package/src/domains/dispatch/admission.ts +40 -3
  210. package/src/domains/dispatch/assignment-reconcile.ts +22 -5
  211. package/src/domains/dispatch/assignment-store.ts +151 -14
  212. package/src/domains/dispatch/capacity-lease.ts +98 -9
  213. package/src/domains/dispatch/contract.ts +26 -1
  214. package/src/domains/dispatch/delegation-plan.ts +2 -5
  215. package/src/domains/dispatch/execution-plan.ts +44 -4
  216. package/src/domains/dispatch/execution-role.ts +9 -1
  217. package/src/domains/dispatch/extension.ts +309 -96
  218. package/src/domains/dispatch/fleet-run.ts +78 -4
  219. package/src/domains/dispatch/gate-role-prompts.ts +38 -0
  220. package/src/domains/dispatch/heartbeat.ts +32 -8
  221. package/src/domains/dispatch/index.ts +6 -1
  222. package/src/domains/dispatch/intent-requirements.ts +40 -0
  223. package/src/domains/dispatch/intent.ts +84 -8
  224. package/src/domains/dispatch/orphan-recovery.ts +5 -0
  225. package/src/domains/dispatch/path-scope.ts +370 -0
  226. package/src/domains/dispatch/receipt-integrity.ts +2 -1
  227. package/src/domains/dispatch/reservation-store.ts +116 -8
  228. package/src/domains/dispatch/state.ts +4 -0
  229. package/src/domains/dispatch/types.ts +14 -7
  230. package/src/domains/dispatch/validation.ts +6 -3
  231. package/src/domains/dispatch/worker-spawn.ts +25 -11
  232. package/src/domains/dispatch/write-boundary-enforcer.ts +62 -0
  233. package/src/domains/dispatch/write-boundary.ts +262 -22
  234. package/src/domains/eval/artifacts/store.ts +62 -0
  235. package/src/domains/eval/compare/behavioral.ts +224 -0
  236. package/src/domains/eval/compare/compare.ts +355 -2
  237. package/src/domains/eval/compare/envelope.ts +128 -0
  238. package/src/domains/eval/compare/gates.ts +24 -6
  239. package/src/domains/eval/compare/thresholds.ts +30 -3
  240. package/src/domains/eval/execution-provenance.ts +240 -0
  241. package/src/domains/eval/metrics/aggregate.ts +136 -0
  242. package/src/domains/eval/metrics/call-ledger-stream.ts +112 -0
  243. package/src/domains/eval/metrics/evidence.ts +79 -2
  244. package/src/domains/eval/metrics/tracked.ts +413 -0
  245. package/src/domains/eval/provenance.ts +117 -0
  246. package/src/domains/eval/reports/comparison.ts +128 -0
  247. package/src/domains/eval/reports/junit.ts +17 -3
  248. package/src/domains/eval/reports/markdown.ts +3 -3
  249. package/src/domains/eval/reports/text.ts +14 -0
  250. package/src/domains/eval/run-compare.ts +20 -0
  251. package/src/domains/eval/runners/clio-run.ts +139 -2
  252. package/src/domains/eval/runners/external-command.ts +28 -3
  253. package/src/domains/eval/schema/adapter.ts +111 -0
  254. package/src/domains/eval/schema/artifact.ts +20 -0
  255. package/src/domains/eval/schema/behavioral-metrics.ts +204 -0
  256. package/src/domains/eval/schema/behavioral.ts +520 -0
  257. package/src/domains/eval/schema/execution-envelope.ts +194 -0
  258. package/src/domains/eval/schema/serving.ts +74 -0
  259. package/src/domains/eval/schema/suite.ts +38 -8
  260. package/src/domains/eval/schema/validate.ts +58 -3
  261. package/src/domains/eval/schema/verdict.ts +237 -0
  262. package/src/domains/eval/suites/resolve.ts +2 -0
  263. package/src/domains/eval/suites/run.ts +264 -33
  264. package/src/domains/eval/verifiers/command.ts +2 -1
  265. package/src/domains/eval/workspaces/temp-copy.ts +145 -13
  266. package/src/domains/evidence/build.ts +68 -21
  267. package/src/domains/evidence/eval.ts +2 -12
  268. package/src/domains/evidence/findings-markdown.ts +33 -0
  269. package/src/domains/evidence/index.ts +21 -0
  270. package/src/domains/evidence/provenance.ts +46 -11
  271. package/src/domains/evidence/run-trust.ts +7 -113
  272. package/src/domains/evidence/trust-projection.ts +274 -0
  273. package/src/domains/evidence/trust-status.ts +145 -17
  274. package/src/domains/evidence/types.ts +4 -0
  275. package/src/domains/extensions/compatibility.ts +285 -0
  276. package/src/domains/extensions/discovery.ts +126 -4
  277. package/src/domains/extensions/resources.ts +21 -9
  278. package/src/domains/extensions/state.ts +18 -5
  279. package/src/domains/extensions/types.ts +6 -1
  280. package/src/domains/lifecycle/doctor.ts +209 -2
  281. package/src/domains/memory/index.ts +14 -0
  282. package/src/domains/memory/task-bank-promotion.ts +64 -0
  283. package/src/domains/memory/task-memory-policy.ts +77 -8
  284. package/src/domains/memory/task-memory-spend.ts +131 -0
  285. package/src/domains/memory/task-memory-status.ts +7 -0
  286. package/src/domains/memory/task-memory-telemetry.ts +2 -0
  287. package/src/domains/middleware/index.ts +1 -0
  288. package/src/domains/middleware/memory-intervention.ts +69 -5
  289. package/src/domains/middleware/memory-step-endpoint.ts +71 -0
  290. package/src/domains/observability/background-memory-usage.ts +140 -0
  291. package/src/domains/observability/cost.ts +1 -1
  292. package/src/domains/observability/index.ts +7 -0
  293. package/src/domains/observability/out-of-turn-usage.ts +51 -2
  294. package/src/domains/observability/trace-store.ts +192 -2
  295. package/src/domains/prompts/compiler.ts +100 -13
  296. package/src/domains/prompts/contract.ts +3 -5
  297. package/src/domains/providers/endpoint-capacity.ts +96 -0
  298. package/src/domains/providers/extension.ts +30 -2
  299. package/src/domains/providers/index.ts +10 -0
  300. package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +243 -1
  301. package/src/domains/providers/runtime-resolution.ts +8 -1
  302. package/src/domains/providers/runtimes/common/probe-helpers.ts +31 -9
  303. package/src/domains/providers/runtimes/local-native/llamacpp-anthropic.ts +1 -1
  304. package/src/domains/providers/runtimes/local-native/llamacpp-completion.ts +1 -1
  305. package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +1 -1
  306. package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +1 -1
  307. package/src/domains/providers/runtimes/local-native/llamacpp.ts +4 -1
  308. package/src/domains/providers/runtimes/local-native/lmstudio.ts +4 -1
  309. package/src/domains/providers/runtimes/local-native/ollama-native.ts +6 -1
  310. package/src/domains/providers/types/capability-flags.ts +2 -0
  311. package/src/domains/providers/types/target-descriptor.ts +2 -0
  312. package/src/domains/resources/common-loader.ts +3 -0
  313. package/src/domains/resources/prompts/loader.ts +184 -17
  314. package/src/domains/safety/call-target.ts +52 -0
  315. package/src/domains/safety/policy-engine.ts +5 -5
  316. package/src/domains/safety/run-effects.ts +96 -2
  317. package/src/domains/safety/scope.ts +7 -12
  318. package/src/domains/session/context-accounting.ts +52 -1
  319. package/src/domains/session/context-ledger.ts +37 -13
  320. package/src/domains/session/index.ts +6 -0
  321. package/src/domains/session/prompt-cache.ts +140 -0
  322. package/src/domains/session/prompt-manifest.ts +42 -0
  323. package/src/engine/acp/adapter.ts +18 -3
  324. package/src/engine/acp/server.ts +4 -1
  325. package/src/engine/ai.ts +35 -0
  326. package/src/engine/apis/llamacpp-residency.ts +55 -3
  327. package/src/engine/apis/lmstudio.ts +25 -5
  328. package/src/engine/apis/ollama-native.ts +2 -1
  329. package/src/engine/apis/openai-completions.ts +80 -17
  330. package/src/engine/apis/residency-lock.ts +3 -1
  331. package/src/engine/apis/residency.ts +34 -1
  332. package/src/engine/prompt-templates.ts +18 -1
  333. package/src/engine/provider-payload.ts +29 -1
  334. package/src/engine/worker-runtime.ts +6 -3
  335. package/src/entry/orchestrator.ts +176 -30
  336. package/src/interactive/chat-loop-messages.ts +26 -7
  337. package/src/interactive/chat-loop.ts +318 -41
  338. package/src/interactive/chat-panel.ts +62 -8
  339. package/src/interactive/clio-editor.ts +45 -8
  340. package/src/interactive/context-activity.ts +5 -1
  341. package/src/interactive/context-meter.ts +1 -1
  342. package/src/interactive/context-overlay.ts +40 -10
  343. package/src/interactive/cost-overlay.ts +64 -6
  344. package/src/interactive/dispatch-board.ts +127 -5
  345. package/src/interactive/fleet-run-preview.ts +41 -15
  346. package/src/interactive/handoff-round.ts +41 -2
  347. package/src/interactive/interactive-application.ts +24 -1
  348. package/src/interactive/interactive-event-projection.ts +14 -0
  349. package/src/interactive/interactive-input-runtime.ts +8 -0
  350. package/src/interactive/interactive-presentation.ts +4 -0
  351. package/src/interactive/interactive-shell.ts +20 -17
  352. package/src/interactive/interactive-slash-runtime.ts +27 -4
  353. package/src/interactive/memory-overlay.ts +8 -0
  354. package/src/interactive/mutation-preview.ts +295 -0
  355. package/src/interactive/overlay-general-openers.ts +16 -0
  356. package/src/interactive/overlay-key-routing.ts +38 -0
  357. package/src/interactive/overlay-lifecycle.ts +38 -5
  358. package/src/interactive/overlay-permission-lifecycle.ts +22 -2
  359. package/src/interactive/overlay-session-lifecycle.ts +73 -9
  360. package/src/interactive/overlays/ask-user.ts +91 -19
  361. package/src/interactive/overlays/help-reference.ts +4 -0
  362. package/src/interactive/overlays/prompts.ts +11 -1
  363. package/src/interactive/overlays/settings.ts +176 -48
  364. package/src/interactive/permission-hint.ts +34 -2
  365. package/src/interactive/permission-overlay.ts +159 -9
  366. package/src/interactive/prewarm.ts +197 -0
  367. package/src/interactive/render-trace.ts +162 -15
  368. package/src/interactive/renderers/tool-execution.ts +4 -0
  369. package/src/interactive/side-question.ts +58 -1
  370. package/src/interactive/slash-commands.ts +7 -2
  371. package/src/interactive/status/controller.ts +11 -0
  372. package/src/interactive/status/state-machine.ts +54 -2
  373. package/src/interactive/status/types.ts +7 -0
  374. package/src/interactive/terminal-lease.ts +2 -0
  375. package/src/interactive/turn-context.ts +299 -31
  376. package/src/interactive/turn-persistence.ts +14 -4
  377. package/src/interactive/turn-prewarm.ts +364 -0
  378. package/src/interactive/turn-queues.ts +7 -4
  379. package/src/interactive/turn-runtime.ts +8 -1
  380. package/src/interactive/turn-state.ts +23 -0
  381. package/src/interactive/view/artifacts.ts +42 -9
  382. package/src/interactive/view/view-overlay.ts +43 -6
  383. package/src/interactive/worker-receipts.ts +14 -2
  384. package/src/interactive/worker-stream.ts +8 -0
  385. package/src/tools/ask-user.ts +43 -2
  386. package/src/tools/dispatch-admission.ts +12 -13
  387. package/src/tools/dispatch-arguments.ts +27 -0
  388. package/src/tools/dispatch-plan.ts +46 -9
  389. package/src/tools/dispatch-runner.ts +48 -13
  390. package/src/tools/dispatch-scout.ts +1 -1
  391. package/src/tools/monitor.ts +13 -0
  392. package/src/tools/registry.ts +16 -0
  393. package/src/tools/worker-evidence.ts +19 -13
  394. package/src/worker/spec-contract.ts +2 -1
  395. package/dist/chunk-AOCYTWAV.js +0 -449
  396. package/dist/chunk-HWUFFB6L.js +0 -83
  397. package/dist/chunk-R346GLFC.js +0 -31
  398. package/dist/chunk-ZGH7FGS5.js +0 -1079
  399. package/dist/doctor-RN4YKO2X.js +0 -87
  400. package/dist/eval-RUBJVSNQ.js +0 -2557
@@ -24,6 +24,12 @@ import {
24
24
  type RunStatus,
25
25
  runKindSupportsLiveSteering,
26
26
  } from "../domains/dispatch/types.js";
27
+ import { describeWriteBoundaryAttributionDowngrade } from "../domains/dispatch/write-boundary.js";
28
+ import {
29
+ summarizeTrustStatus,
30
+ type TrustSummaryProjection,
31
+ type TrustVerdict,
32
+ } from "../domains/evidence/trust-projection.js";
27
33
  import {
28
34
  COST_NOT_MEASURED,
29
35
  costAggregateForAmount,
@@ -31,7 +37,7 @@ import {
31
37
  type ObservabilityNotice,
32
38
  type ObservabilitySnapshot,
33
39
  } from "../domains/observability/index.js";
34
- import type { CostProvenance } from "../domains/providers/index.js";
40
+ import { type CostProvenance, foregroundStreamUsage } from "../domains/providers/index.js";
35
41
  import { sanitizeCallTargetText } from "../domains/safety/call-target.js";
36
42
  import { type Component, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "../engine/tui.js";
37
43
  import { formatWorkerContextMeter } from "./context-meter.js";
@@ -83,6 +89,12 @@ export interface DispatchSteerAcknowledgement {
83
89
  chars: number;
84
90
  }
85
91
 
92
+ export interface DispatchWriteRecordDowngrade {
93
+ reason: "opaque_tool_succeeded";
94
+ tool: string;
95
+ toolCallId: string;
96
+ }
97
+
86
98
  export interface DispatchBoardRow {
87
99
  runId: string;
88
100
  agentId: string;
@@ -92,6 +104,8 @@ export interface DispatchBoardRow {
92
104
  runtimeId: string;
93
105
  targetId: string;
94
106
  wireModelId: string;
107
+ /** Canonical inference scheduler and its independent request-slot bound. */
108
+ endpoint?: { key: string; label: string; limit: number };
95
109
  /** Sanitized, one-line summary of the task assigned to this run. */
96
110
  taskSummary?: string;
97
111
  /** Immutable budget admission provenance for this run. */
@@ -113,6 +127,13 @@ export interface DispatchBoardRow {
113
127
  council?: { group: string; label: string; color?: string; round: number };
114
128
  /** Orchestrator-executed declared verification status. */
115
129
  hostVerification?: "verified" | "rejected" | "skipped";
130
+ /**
131
+ * The canonical trust projection of the sealed receipt, read back from
132
+ * disk and authenticated against the ledger row. Absent while the run is
133
+ * live or when the receipt could not be read back, so the card never
134
+ * implies a verdict the terminal bus event cannot carry.
135
+ */
136
+ trust?: TrustSummaryProjection;
116
137
  /** Dead-node failover hops recorded on this run's chain. */
117
138
  rerouteCount?: number;
118
139
  /** Assignment retry attempts observed on the assignment event stream. */
@@ -144,6 +165,8 @@ export interface DispatchBoardRow {
144
165
  retry?: DispatchRetryPresentation;
145
166
  /** Most recent worker delivery acknowledgement for an operator steer. */
146
167
  steerAcknowledgement?: DispatchSteerAcknowledgement;
168
+ /** First successful opaque call that opened this run's write record. */
169
+ writeRecordDowngrade?: DispatchWriteRecordDowngrade;
147
170
  /**
148
171
  * Where this run sits in a fleet plan: the wave the step was scheduled in
149
172
  * and the step id it executes. Present only for runs a fleet plan
@@ -586,11 +609,29 @@ function progressAnswerLines(
586
609
  return body.map((row, index) => `${index === 0 ? cardKvKey(theme, "answer") : " ".repeat(gutter)}${row}`);
587
610
  }
588
611
 
612
+ /** Keep the canonical tier and every summary clause visible by wrapping the value under its card key. */
613
+ function trustCardLines(theme: ClioTheme, row: DispatchBoardRow, contentWidth: number): string[] {
614
+ const gutter = CARD_KV_KEY_WIDTH + 1;
615
+ const valueWidth = Math.max(1, contentWidth - gutter);
616
+ const trust =
617
+ row.trust === undefined
618
+ ? theme.fg("dim", isTerminalStatus(row.status) ? "receipt not read back" : "not sealed yet")
619
+ : theme.fg(
620
+ trustVerdictToken(row.trust.verdict),
621
+ `${trustVerdictGlyph(row.trust.verdict)} ${row.trust.verdict}; ${row.trust.text}`,
622
+ );
623
+ const host =
624
+ row.hostVerification === undefined ? "" : ` · ${theme.fg("muted", `host checks ${row.hostVerification}`)}`;
625
+ return wrapTextWithAnsi(`${trust}${host}`, valueWidth).map(
626
+ (line, index) => `${index === 0 ? cardKvKey(theme, "trust") : " ".repeat(gutter)}${line}`,
627
+ );
628
+ }
629
+
589
630
  export function renderDispatchCard(
590
631
  row: DispatchBoardRow,
591
632
  width: number,
592
633
  evidence?: RunEvidencePresentation,
593
- options: { selected?: boolean; expanded?: boolean } = {},
634
+ options: { selected?: boolean; expanded?: boolean; endpointActive?: number } = {},
594
635
  ): string[] {
595
636
  const theme = clioTheme();
596
637
  const contentWidth = Math.max(0, width - 4);
@@ -641,6 +682,9 @@ export function renderDispatchCard(
641
682
  const statusUnits = [
642
683
  statusStr,
643
684
  theme.fg("muted", `node ${row.node ?? "local"}`),
685
+ ...(row.endpoint !== undefined
686
+ ? [theme.fg("info", `slots ${options.endpointActive ?? 0}/${row.endpoint.limit} ${row.endpoint.label}`)]
687
+ : []),
644
688
  ...(row.gate !== undefined ? [theme.fg("info", `gate ${row.gate.role} c${row.gate.cycle}`)] : []),
645
689
  ...(row.rerouteCount !== undefined && row.rerouteCount > 0
646
690
  ? [theme.fg("warning", `rerouted x${row.rerouteCount}`)]
@@ -651,7 +695,6 @@ export function renderDispatchCard(
651
695
  `${theme.fg("dim", "ttft")} ${theme.fg("muted", ttft)}`,
652
696
  `${theme.fg("dim", "cost")} ${theme.fg("muted", cost)}`,
653
697
  ];
654
- const hostVerification = theme.fg("info", `host_verification=${row.hostVerification ?? "not_requested"}`);
655
698
  const contextUnit = formatWorkerContextMeter(row.lastContextTokens ?? 0, row.contextWindow, theme);
656
699
  // The phase column: a fleet step says which wave it belongs to and which
657
700
  // step it is; every other run leaves the cell empty rather than inventing a
@@ -670,7 +713,7 @@ export function renderDispatchCard(
670
713
  ? [truncateToWidth(`${cardKvKey(theme, "task")}${theme.fg("muted", row.taskSummary)}`, contentWidth, "…", false)]
671
714
  : []),
672
715
  cardUnitsLine(theme, "status", statusUnits, contentWidth),
673
- cardUnitsLine(theme, "evidence", [hostVerification], contentWidth),
716
+ ...trustCardLines(theme, row, contentWidth),
674
717
  ...(row.budget !== undefined
675
718
  ? [
676
719
  truncateToWidth(
@@ -731,6 +774,16 @@ export function renderDispatchCard(
731
774
  ),
732
775
  );
733
776
  }
777
+ if (row.writeRecordDowngrade) {
778
+ const warning = describeWriteBoundaryAttributionDowngrade({
779
+ ...row.writeRecordDowngrade,
780
+ runId: row.runId,
781
+ stepId: row.phase?.stepId ?? null,
782
+ });
783
+ bodyLines.push(
784
+ ...wrapTextWithAnsi(`${cardKvKey(theme, "record")}${theme.fg("warning", `open: ${warning}`)}`, contentWidth),
785
+ );
786
+ }
734
787
  // The proof row is present only when the observability projection knows an
735
788
  // evidence state for this run; an unknown/none state adds no line, so cards
736
789
  // without evidence keep their existing three-line body.
@@ -949,6 +1002,16 @@ export function formatDispatchBoardLines(
949
1002
  });
950
1003
  }
951
1004
 
1005
+ const endpointActive: Record<string, number> = { ...foregroundStreamUsage() };
1006
+ for (const row of rows) {
1007
+ if (
1008
+ row.endpoint !== undefined &&
1009
+ (row.status === "running" || row.status === "stale" || row.status === "enqueued" || row.status === "cancelling")
1010
+ ) {
1011
+ endpointActive[row.endpoint.key] = (endpointActive[row.endpoint.key] ?? 0) + 1;
1012
+ }
1013
+ }
1014
+
952
1015
  // A council is one question asked of several members, so its rows render as
953
1016
  // one card holding the whole group rather than as unrelated neighbours.
954
1017
  const cards = dispatchBoardItems(rows, selectedRunId).map((item) =>
@@ -957,6 +1020,7 @@ export function formatDispatchBoardLines(
957
1020
  : renderDispatchCard(item.row, width, deriveRunEvidenceState(observability, item.row.runId), {
958
1021
  selected: item.row.runId === selectedRunId,
959
1022
  expanded: detailExpanded && item.row.runId === selectedRunId,
1023
+ ...(item.row.endpoint !== undefined ? { endpointActive: endpointActive[item.row.endpoint.key] ?? 0 } : {}),
960
1024
  }),
961
1025
  );
962
1026
  const body: string[] = [];
@@ -1135,6 +1199,15 @@ function parseGateBadge(value: unknown): { role: string; cycle: number } | undef
1135
1199
  return { role: record.role, cycle };
1136
1200
  }
1137
1201
 
1202
+ function parseEndpointCapacity(value: unknown): DispatchBoardRow["endpoint"] | undefined {
1203
+ if (typeof value !== "object" || value === null) return undefined;
1204
+ const record = value as { key?: unknown; label?: unknown; limit?: unknown };
1205
+ const key = parseNonEmptyString(record.key);
1206
+ const label = parseNonEmptyString(record.label);
1207
+ const limit = parsePositiveInt(record.limit);
1208
+ return key === undefined || label === undefined || limit === undefined ? undefined : { key, label, limit };
1209
+ }
1210
+
1138
1211
  function parseCouncilBadge(value: unknown): DispatchBoardRow["council"] | undefined {
1139
1212
  if (typeof value !== "object" || value === null) return undefined;
1140
1213
  const record = value as { group?: unknown; label?: unknown; color?: unknown; round?: unknown };
@@ -1160,6 +1233,33 @@ function parseOptionalDetail(value: unknown): string | null {
1160
1233
  return detail.length > 0 ? detail : null;
1161
1234
  }
1162
1235
 
1236
+ /** Only an authenticated independent pass earns the success token; sealed alone is never green. */
1237
+ function trustVerdictToken(verdict: TrustVerdict): ClioToken {
1238
+ switch (verdict) {
1239
+ case "reviewed":
1240
+ return "success";
1241
+ case "grounded":
1242
+ return "info";
1243
+ case "unverified":
1244
+ return "muted";
1245
+ case "compromised":
1246
+ return "error";
1247
+ default:
1248
+ return "dim";
1249
+ }
1250
+ }
1251
+
1252
+ function trustVerdictGlyph(verdict: TrustVerdict): string {
1253
+ switch (verdict) {
1254
+ case "reviewed":
1255
+ return GLYPH.ok;
1256
+ case "compromised":
1257
+ return GLYPH.error;
1258
+ default:
1259
+ return "◇";
1260
+ }
1261
+ }
1262
+
1163
1263
  function terminalDetail(row: DispatchBoardRow): string | null {
1164
1264
  if (row.status !== "failed" && row.status !== "dead" && row.status !== "aborted") return null;
1165
1265
  return parseOptionalDetail(row.outcomeDetail);
@@ -1304,6 +1404,7 @@ function toRow(entry: DispatchBoardEntry, now: number): DispatchBoardRow {
1304
1404
  runtimeId: entry.runtimeId,
1305
1405
  targetId: entry.targetId,
1306
1406
  wireModelId: entry.wireModelId,
1407
+ ...(entry.endpoint !== undefined ? { endpoint: { ...entry.endpoint } } : {}),
1307
1408
  ...(entry.taskSummary !== undefined ? { taskSummary: entry.taskSummary } : {}),
1308
1409
  ...(entry.budget !== undefined ? { budget: entry.budget } : {}),
1309
1410
  status: retry ? "retrying" : entry.status,
@@ -1319,6 +1420,7 @@ function toRow(entry: DispatchBoardEntry, now: number): DispatchBoardRow {
1319
1420
  ...(entry.gate !== undefined ? { gate: { ...entry.gate } } : {}),
1320
1421
  ...(entry.council !== undefined ? { council: { ...entry.council } } : {}),
1321
1422
  ...(entry.hostVerification !== undefined ? { hostVerification: entry.hostVerification } : {}),
1423
+ ...(entry.trust !== undefined ? { trust: entry.trust } : {}),
1322
1424
  ...(entry.rerouteCount !== undefined ? { rerouteCount: entry.rerouteCount } : {}),
1323
1425
  ...(entry.failoverHops !== undefined ? { failoverHops: entry.failoverHops } : {}),
1324
1426
  ...(entry.contextWindow !== undefined ? { contextWindow: entry.contextWindow } : {}),
@@ -1331,6 +1433,7 @@ function toRow(entry: DispatchBoardEntry, now: number): DispatchBoardRow {
1331
1433
  recentTools: progress.recentActions.map((action) => action.tool),
1332
1434
  ...(retry ? { retry: { ...retry } } : {}),
1333
1435
  ...(entry.steerAcknowledgement ? { steerAcknowledgement: { ...entry.steerAcknowledgement } } : {}),
1436
+ ...(entry.writeRecordDowngrade ? { writeRecordDowngrade: { ...entry.writeRecordDowngrade } } : {}),
1334
1437
  };
1335
1438
  }
1336
1439
 
@@ -1394,8 +1497,10 @@ export function createDispatchBoardStore(
1394
1497
  * before it publishes one, so this is the first moment the file exists.
1395
1498
  */
1396
1499
  const settleFromReceipt = (entry: DispatchBoardEntry): void => {
1397
- const text = readReceipt?.(entry.runId)?.text;
1500
+ const facts = readReceipt?.(entry.runId);
1501
+ const text = facts?.text;
1398
1502
  entry.progress.settle(typeof text === "string" && text.trim().length > 0 ? text : undefined);
1503
+ if (facts?.trust !== undefined) entry.trust = summarizeTrustStatus(facts.trust);
1399
1504
  };
1400
1505
 
1401
1506
  // Payloads arrive typed off the bus, but the board keeps its runtime
@@ -1411,6 +1516,7 @@ export function createDispatchBoardStore(
1411
1516
  const agentAudience = parseAgentAudience(raw.agentAudience, previous?.agentAudience);
1412
1517
  const requestOrigin = parseRequestOrigin(raw.requestOrigin, previous?.requestOrigin);
1413
1518
  const node = parseNonEmptyString(raw.node) ?? previous?.node;
1519
+ const endpoint = parseEndpointCapacity(raw.endpoint) ?? previous?.endpoint;
1414
1520
  const gate = parseGateBadge(raw.gate) ?? previous?.gate;
1415
1521
  const council = parseCouncilBadge(raw.council) ?? previous?.council;
1416
1522
  const rerouteCount = parsePositiveInt(raw.rerouteCount) ?? previous?.rerouteCount;
@@ -1427,6 +1533,7 @@ export function createDispatchBoardStore(
1427
1533
  runtimeId: parseText(raw.runtimeId, previous?.runtimeId ?? "-"),
1428
1534
  targetId: parseText(raw.targetId, previous?.targetId ?? "-"),
1429
1535
  wireModelId: parseText(raw.wireModelId, previous?.wireModelId ?? "-"),
1536
+ ...(endpoint !== undefined ? { endpoint } : {}),
1430
1537
  ...(taskSummary !== undefined ? { taskSummary } : {}),
1431
1538
  ...(budget !== undefined ? { budget } : {}),
1432
1539
  status,
@@ -1455,6 +1562,7 @@ export function createDispatchBoardStore(
1455
1562
  progress: previous?.progress ?? createWorkerProgressFold(),
1456
1563
  ...(previous?.retry ? { retry: { ...previous.retry } } : {}),
1457
1564
  ...(previous?.steerAcknowledgement ? { steerAcknowledgement: { ...previous.steerAcknowledgement } } : {}),
1565
+ ...(previous?.writeRecordDowngrade ? { writeRecordDowngrade: { ...previous.writeRecordDowngrade } } : {}),
1458
1566
  };
1459
1567
  entries.set(runId, entry);
1460
1568
  pruneEntries(entries, (evicted) => fleetPhases.delete(evicted));
@@ -1604,6 +1712,20 @@ export function createDispatchBoardStore(
1604
1712
  entry.ttftMs = Math.round(performance.now() - entry.startedAtClockMs);
1605
1713
  }
1606
1714
  }
1715
+ if (type === "clio_write_record_downgraded") {
1716
+ const rawPayload = (workerEvent as { payload?: unknown }).payload;
1717
+ const payload =
1718
+ typeof rawPayload === "object" && rawPayload !== null ? (rawPayload as Record<string, unknown>) : null;
1719
+ const tool = payload === null ? undefined : parseNonEmptyString(payload.tool);
1720
+ const toolCallId = payload === null ? undefined : parseNonEmptyString(payload.toolCallId);
1721
+ if (payload?.reason === "opaque_tool_succeeded" && tool !== undefined && toolCallId !== undefined) {
1722
+ entry.writeRecordDowngrade = {
1723
+ reason: "opaque_tool_succeeded",
1724
+ tool: sanitizeCallTargetText(tool),
1725
+ toolCallId: sanitizeCallTargetText(toolCallId),
1726
+ };
1727
+ }
1728
+ }
1607
1729
  // The one fold that reads worker prose and tool activity. Everything the
1608
1730
  // board says about what a worker is saying or touching comes from here,
1609
1731
  // so the board and the transcript block cannot tell two stories.
@@ -26,7 +26,11 @@ import {
26
26
  validateFleetGraph,
27
27
  } from "../domains/agents/index.js";
28
28
  import type { AgentSpec } from "../domains/agents/spec.js";
29
- import type { ExecutionPlan, ExecutionPlanStep } from "../domains/dispatch/execution-plan.js";
29
+ import {
30
+ bindExecutionPlanEndpoints,
31
+ type ExecutionPlan,
32
+ type ExecutionPlanStep,
33
+ } from "../domains/dispatch/execution-plan.js";
30
34
  import {
31
35
  type AgentRoleFactsResolver,
32
36
  requestExecutionRole,
@@ -40,6 +44,7 @@ export interface FleetRunPreviewRoute {
40
44
  targetId: string;
41
45
  wireModelId: string;
42
46
  nodeId: string;
47
+ endpoint?: { key: string; label: string; limit: number; foregroundHeld?: number };
43
48
  }
44
49
 
45
50
  export interface FleetRunPreviewStep {
@@ -207,6 +212,40 @@ export function compileFleetRunPreview(input: FleetRunPreviewInput): FleetRunPre
207
212
  diagnostics.push(describeError(error));
208
213
  return fail();
209
214
  }
215
+ const routes = new Map<string, FleetRunPreviewRoute>();
216
+ if (input.resolveRoute !== undefined) {
217
+ for (const step of plan.steps) {
218
+ if (step.kind === "code") continue;
219
+ try {
220
+ const route = input.resolveRoute({
221
+ stepId: step.id,
222
+ agentId: step.agentId,
223
+ task: step.task,
224
+ scope: step.scope,
225
+ ...(step.target !== undefined ? { target: step.target } : {}),
226
+ ...(step.profile !== undefined ? { profile: step.profile } : {}),
227
+ });
228
+ if (route !== null) routes.set(step.id, route);
229
+ } catch (error) {
230
+ diagnostics.push(`step '${step.id}' route preflight failed: ${describeError(error)}`);
231
+ }
232
+ }
233
+ plan = bindExecutionPlanEndpoints(
234
+ plan,
235
+ Object.fromEntries(
236
+ [...routes].map(([stepId, route]) => [
237
+ stepId,
238
+ route.endpoint === undefined
239
+ ? undefined
240
+ : {
241
+ key: route.endpoint.key,
242
+ limit: route.endpoint.limit,
243
+ ...(route.endpoint.foregroundHeld !== undefined ? { foregroundHeld: route.endpoint.foregroundHeld } : {}),
244
+ },
245
+ ]),
246
+ ),
247
+ );
248
+ }
210
249
 
211
250
  // A declared boundary is verified against the checkout, so the checkout has
212
251
  // to be one this can read. Refused here, before any dispatch, rather than
@@ -261,20 +300,7 @@ export function compileFleetRunPreview(input: FleetRunPreviewInput): FleetRunPre
261
300
  },
262
301
  ];
263
302
  }
264
- let route: FleetRunPreviewRoute | null = null;
265
- try {
266
- route =
267
- input.resolveRoute?.({
268
- stepId: step.id,
269
- agentId: step.agentId,
270
- task: step.task,
271
- scope: step.scope,
272
- ...(step.target !== undefined ? { target: step.target } : {}),
273
- ...(step.profile !== undefined ? { profile: step.profile } : {}),
274
- }) ?? null;
275
- } catch (error) {
276
- diagnostics.push(`step '${step.id}' route preflight failed: ${describeError(error)}`);
277
- }
303
+ const route = routes.get(step.id) ?? null;
278
304
  return [
279
305
  {
280
306
  ...base,
@@ -34,6 +34,22 @@ export const HANDOFF_SYSTEM_PROMPT = [
34
34
  /** A handoff record is a list of short entries, so the budget is modest. */
35
35
  export const HANDOFF_MAX_TOKENS = 4096;
36
36
 
37
+ /** The name the wire dialect gives the schema, where it takes one. */
38
+ export const HANDOFF_SCHEMA_NAME = "handoff_record";
39
+
40
+ /** Characters of the refused answer quoted back to the model in the repair round. */
41
+ export const HANDOFF_REPAIR_QUOTE_CHARS = 600;
42
+
43
+ /**
44
+ * What the first round returned and why the parser refused it. The repair round
45
+ * shows the model both, because "return one JSON object" repeated verbatim is
46
+ * the instruction it already failed (issue #223).
47
+ */
48
+ export interface HandoffRepairInput {
49
+ complaint: string;
50
+ previous: string;
51
+ }
52
+
37
53
  export interface HandoffRoundInput {
38
54
  model: EngineModel;
39
55
  /** Read-only. The round copies before appending its own message. */
@@ -42,15 +58,38 @@ export interface HandoffRoundInput {
42
58
  apiKey?: string;
43
59
  signal?: AbortSignal;
44
60
  maxTokens?: number;
61
+ /** Resolved runtime id, which decides whether the schema can be bound on the wire. */
62
+ runtimeId?: string;
63
+ /** Set on the second and last round, after the parser refused the first. */
64
+ repair?: HandoffRepairInput;
65
+ }
66
+
67
+ function repairText(goal: string, repair: HandoffRepairInput): string {
68
+ const quoted = repair.previous.slice(0, HANDOFF_REPAIR_QUOTE_CHARS);
69
+ return [
70
+ `The next session's goal is: ${goal}`,
71
+ "",
72
+ "Your previous answer could not be read as a handoff record.",
73
+ `The parser said: ${repair.complaint}`,
74
+ "This is what you returned, verbatim:",
75
+ "---",
76
+ quoted.length > 0 ? quoted : "(nothing)",
77
+ "---",
78
+ "Answer again with one JSON object matching the schema and nothing else.",
79
+ "No prose before it, no prose after it, no code fence.",
80
+ ].join("\n");
45
81
  }
46
82
 
47
83
  /** Run the round. Provider failures reject; the caller renders the reason. */
48
84
  export async function runHandoffRound(input: HandoffRoundInput): Promise<SideQuestionResult> {
49
- const { goal, ...rest } = input;
85
+ const { goal, repair, ...rest } = input;
50
86
  return runOutOfTurnRound({
51
87
  ...rest,
52
88
  maxTokens: input.maxTokens ?? HANDOFF_MAX_TOKENS,
53
89
  systemPrompt: HANDOFF_SYSTEM_PROMPT,
54
- userText: `The next session's goal is: ${goal}\n\nExtract the handoff record for that goal now.`,
90
+ responseSchema: { name: HANDOFF_SCHEMA_NAME, schema: HANDOFF_RESPONSE_SCHEMA },
91
+ userText: repair
92
+ ? repairText(goal, repair)
93
+ : `The next session's goal is: ${goal}\n\nExtract the handoff record for that goal now.`,
55
94
  });
56
95
  }
@@ -3,6 +3,7 @@ import type { ClioSettings } from "../core/config.js";
3
3
  import type { SafeEventBus } from "../core/event-bus.js";
4
4
  import { expandInlineFileReferencesAsync } from "../core/file-references.js";
5
5
  import type { PendingSkillRequest } from "../core/skill-activation.js";
6
+ import { clioStateDir } from "../core/xdg.js";
6
7
  import type { AgentsContract } from "../domains/agents/contract.js";
7
8
  import type { ClioKeybinding } from "../domains/config/keybindings.js";
8
9
  import type { ContextState } from "../domains/context/index.js";
@@ -41,6 +42,7 @@ import { createInteractiveSubscriptions } from "./interactive-subscriptions.js";
41
42
  import { createInteractiveTickers } from "./interactive-tickers.js";
42
43
  import { createOverlayLifecycle, type OverlayLifecycleController, type OverlayState } from "./overlay-lifecycle.js";
43
44
  import { interopOverlaySurface } from "./overlays/interop.js";
45
+ import { writeInputWedgeDump } from "./render-trace.js";
44
46
  import { settleChatBeforeSessionSwitch } from "./session-switch-settlement.js";
45
47
  import { createSessionTranscript } from "./session-transcript.js";
46
48
  import type {
@@ -429,6 +431,21 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
429
431
  });
430
432
  const { terminal, tui } = shell;
431
433
  const renderTrace = getActiveRenderTrace();
434
+ // SIGTERM is the kill an operator reaches for when a pane stops answering, so
435
+ // it is where the always-on input-wedge ring has to land (#224). It writes
436
+ // synchronously from its own listener rather than from a termination hook: a
437
+ // session wedged badly enough to be killed may never reach the coordinator's
438
+ // asynchronous drain, and this dump has to survive that.
439
+ const dumpInputWedgeOnTerminate = renderTrace
440
+ ? (): void => {
441
+ try {
442
+ writeInputWedgeDump(clioStateDir(), renderTrace.snapshotInputWedge());
443
+ } catch {
444
+ // Best effort. The process is ending either way.
445
+ }
446
+ }
447
+ : null;
448
+ if (dumpInputWedgeOnTerminate) process.on("SIGTERM", dumpInputWedgeOnTerminate);
432
449
  const visibleEventIngress = new WeakMap<
433
450
  object,
434
451
  { sequence: number; traceSequence: number; generation: number; ingressAt: number }
@@ -498,6 +515,11 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
498
515
  getLeaderArmed: () => leaderArmed,
499
516
  getShutdownArmed: () => shutdownArmed,
500
517
  isAwaitingApproval: () => overlayLifecycle?.getState() === "permission-confirm",
518
+ getPermissionInspection: () => {
519
+ if (overlayLifecycle === undefined || overlayLifecycle === null) return "none";
520
+ if (!overlayLifecycle.canInspectMutation()) return "none";
521
+ return overlayLifecycle.isInspectingMutation() ? "open" : "closed";
522
+ },
501
523
  resolveVisibleEventSequence: (event) => visibleEventIngress.get(event)?.traceSequence ?? null,
502
524
  resolveStreamIngress: (event) => visibleEventIngress.get(event) ?? null,
503
525
  commitFrame: (reason) => shell.commitCurrentFrame(reason === "teardown" ? 300 : 30_000),
@@ -618,7 +640,7 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
618
640
  chat: deps.chat,
619
641
  chatPanel: {
620
642
  appendReplayBlock: (...args) => chatRenderer.mutate(() => chatPanel.appendReplayBlock(...args), "slash-output"),
621
- appendUser: (text) => chatRenderer.mutate(() => chatPanel.appendUser(text), "user-submit"),
643
+ appendUser: (text, status) => chatRenderer.mutate(() => chatPanel.appendUser(text, status), "user-submit"),
622
644
  clearFoldOverrides: () => chatRenderer.mutate(() => chatPanel.clearFoldOverrides(), "output-detail"),
623
645
  },
624
646
  beforeSemanticSubmit: () => chatRenderer.flush(),
@@ -949,6 +971,7 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
949
971
  cancelParkedCalls: (reason) => deps.toolRegistry?.cancelParkedCalls(reason),
950
972
  onShutdown: async () => {
951
973
  try {
974
+ if (dumpInputWedgeOnTerminate) process.off("SIGTERM", dumpInputWedgeOnTerminate);
952
975
  await deps.onShutdown();
953
976
  } finally {
954
977
  if (lease) await lease.close();
@@ -3,6 +3,7 @@ import {
3
3
  type ConfigReloadFailedPayload,
4
4
  type ContextPrunedPayload,
5
5
  type ContextWarningPayload,
6
+ type DispatchScopeNoticePayload,
6
7
  type LoopBlockedPayload,
7
8
  type RuntimeNoticePayload,
8
9
  type ToolBudgetExceededPayload,
@@ -271,6 +272,19 @@ export function createInteractiveEventProjection(deps: InteractiveEventProjectio
271
272
  );
272
273
 
273
274
  remainingUnsubscribers.push(
275
+ deps.bus.on(BusChannels.DispatchScopeNotice, (payload) => {
276
+ const event = payload as DispatchScopeNoticePayload | null | undefined;
277
+ if (
278
+ !event ||
279
+ typeof event !== "object" ||
280
+ !["typed_scope_replaced_inferred_paths", "legacy_scope_inferred", "legacy_scope_empty"].includes(event.code) ||
281
+ typeof event.message !== "string"
282
+ ) {
283
+ return;
284
+ }
285
+ deps.appendTranscriptNotice("warn", event.message);
286
+ deps.requestRender();
287
+ }),
274
288
  deps.bus.on(BusChannels.LoopBlocked, (payload) => {
275
289
  const event = payload as LoopBlockedPayload | null | undefined;
276
290
  if (!event || typeof event !== "object" || typeof event.tool !== "string" || typeof event.repeatCount !== "number") {
@@ -60,6 +60,10 @@ export interface InteractiveInputRuntimeDeps {
60
60
  closeOverlay(): void;
61
61
  confirmPermission(): void;
62
62
  stopTurnFromPermission(): void;
63
+ canInspectMutation(): boolean;
64
+ isInspectingMutation(): boolean;
65
+ toggleMutationInspection(): void;
66
+ scrollMutationInspection(delta: number): void;
63
67
  cancelAskUser(): void;
64
68
  toggleFooterDashboardState(): void;
65
69
  toggleDispatchBoardOverlay(): void;
@@ -213,6 +217,10 @@ export function createInteractiveInputRuntime(deps: InteractiveInputRuntimeDeps)
213
217
  confirmPermission: () => deps.overlay.confirmPermission(),
214
218
  stopTurnFromPermission: () => deps.overlay.stopTurnFromPermission(),
215
219
  composerHasDraft: () => deps.editor.getText().length > 0,
220
+ canInspectMutation: () => deps.overlay.canInspectMutation(),
221
+ isInspectingMutation: () => deps.overlay.isInspectingMutation(),
222
+ toggleMutationInspection: () => deps.overlay.toggleMutationInspection(),
223
+ scrollMutationInspection: (delta) => deps.overlay.scrollMutationInspection(delta),
216
224
  editDraft: (data) => {
217
225
  deps.editor.handleInput?.(data);
218
226
  deps.requestRender();
@@ -99,6 +99,8 @@ export interface InteractivePresentationDeps {
99
99
  getShutdownArmed?: () => boolean;
100
100
  /** Whether a permission prompt owns the keyboard, for the composer's CONFIRM rail. */
101
101
  isAwaitingApproval?: () => boolean;
102
+ /** Whether that prompt has a mutation to inspect, and whether it is open (issue #254). */
103
+ getPermissionInspection?: () => import("./permission-hint.js").PermissionInspectionHint;
102
104
  getCwd?: () => string;
103
105
  resolveVisibleEventSequence?: (event: ChatLoopEvent) => number | null;
104
106
  resolveStreamIngress?: (
@@ -418,6 +420,8 @@ export function createInteractivePresentation(deps: InteractivePresentationDeps)
418
420
  },
419
421
  isStreaming: () => deps.chat.isStreaming(),
420
422
  ...(deps.isAwaitingApproval ? { isAwaitingApproval: deps.isAwaitingApproval } : {}),
423
+ ...(deps.getPermissionInspection ? { getPermissionInspection: deps.getPermissionInspection } : {}),
424
+ getTurnPreparation: () => deps.chat.turnPreparation().phase,
421
425
  willEnterSteer: (text) => willEnterSteerActiveWork(deps, text),
422
426
  getSubmitKeyLabel: () => formatKeyLabel(keybindings.getKeys("tui.input.submit")[0], "Enter"),
423
427
  getNewlineKeyLabel: () => formatKeyLabel(keybindings.getKeys("tui.input.newLine")[0], "Shift+Enter"),
@@ -158,9 +158,11 @@ export function createInteractiveShell<TTerminal extends Terminal, TTui extends
158
158
  }
159
159
 
160
160
  /**
161
- * Trace for the current process, created once when CLIO_CODER_RENDER_TRACE names a
162
- * file. The panel wires its render metrics into the same instance, so the
163
- * frame rows carry both the build cost and the write cost.
161
+ * Trace for the current process, created once per interactive shell. It writes
162
+ * a JSONL file when CLIO_CODER_RENDER_TRACE names one and otherwise keeps only
163
+ * its bounded input-wedge ring in memory. The panel wires its render metrics
164
+ * into the same instance, so the frame rows carry both the build cost and the
165
+ * write cost.
164
166
  */
165
167
  let activeRenderTrace: RenderTrace | null = null;
166
168
 
@@ -203,20 +205,21 @@ export function createProcessInteractiveShell(
203
205
  let restoreRoot: (() => void) | null = null;
204
206
  let backpressure: StdoutBackpressureGate | null = null;
205
207
  let observedBackpressure = false;
206
- if (tracePath) {
207
- let candidate: RenderTrace | null = null;
208
- try {
209
- candidate = createRenderTrace(tracePath);
210
- restoreStdout = traceProcessStdout(candidate);
211
- activeRenderTrace = candidate;
212
- } catch {
213
- // A diagnostics path must never prevent the interactive application from starting.
214
- restoreStdout?.();
215
- restoreStdout = null;
216
- void candidate?.close().catch(() => {});
217
- activeRenderTrace = null;
218
- }
219
- } else activeRenderTrace = null;
208
+ let candidate: RenderTrace | null = null;
209
+ try {
210
+ // A null path is the ring-only mode: no file, but the input-wedge ring still
211
+ // fills, because the operator who hits a wedge did not arm a trace before it
212
+ // happened (#224).
213
+ candidate = createRenderTrace(tracePath);
214
+ restoreStdout = traceProcessStdout(candidate);
215
+ activeRenderTrace = candidate;
216
+ } catch {
217
+ // A diagnostics path must never prevent the interactive application from starting.
218
+ restoreStdout?.();
219
+ restoreStdout = null;
220
+ void candidate?.close().catch(() => {});
221
+ activeRenderTrace = null;
222
+ }
220
223
  const trace = activeRenderTrace;
221
224
  if (trace && options.onFirstFrameCommit) trace.onFirstFrameCommit(options.onFirstFrameCommit);
222
225
  let firstFrameDelivered = false;