@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
@@ -7,7 +7,7 @@
7
7
  */
8
8
 
9
9
  import { createHash } from "node:crypto";
10
- import { mkdirSync } from "node:fs";
10
+ import { mkdirSync, statSync } from "node:fs";
11
11
  import { createRequire } from "node:module";
12
12
  import { hostname } from "node:os";
13
13
  import { dirname, join } from "node:path";
@@ -27,6 +27,32 @@ export const TRACE_DATABASE_FILE = "trace.sqlite";
27
27
  export const TRACE_EVENT_POLL_LIMIT = 500;
28
28
  export const TRACE_PAYLOAD_LIMIT_BYTES = 16 * 1024;
29
29
  export const TRACE_WRITE_QUEUE_LIMIT = 2048;
30
+ export const TRACE_RETENTION_DAYS_ENV = "CLIO_CODER_TRACE_RETENTION_DAYS";
31
+ export const TRACE_MAX_BYTES_ENV = "CLIO_CODER_TRACE_MAX_BYTES";
32
+
33
+ export interface TraceRetentionPolicy {
34
+ maxAgeDays: number;
35
+ maxBytes: number;
36
+ }
37
+
38
+ export interface TracePruneResult {
39
+ runsRemoved: number;
40
+ rowsRemoved: number;
41
+ bytesBefore: number;
42
+ bytesAfter: number;
43
+ bytesRemoved: number;
44
+ vacuumed: boolean;
45
+ protectedRuns: number;
46
+ }
47
+
48
+ /** Thirty days or 128 MiB, whichever limit the mirror reaches first. */
49
+ export const DEFAULT_TRACE_RETENTION_POLICY: Readonly<TraceRetentionPolicy> = Object.freeze({
50
+ maxAgeDays: 30,
51
+ maxBytes: 128 * 1024 * 1024,
52
+ });
53
+
54
+ const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
55
+ const VACUUM_RECLAIMABLE_FRACTION = 0.2;
30
56
 
31
57
  type DatabaseSyncConstructor = typeof import("node:sqlite").DatabaseSync;
32
58
  let sqliteConstructor: DatabaseSyncConstructor | null = null;
@@ -110,6 +136,40 @@ export function traceDatabasePath(stateDir: string): string {
110
136
  return join(stateDir, TRACE_DATABASE_FILE);
111
137
  }
112
138
 
139
+ /** Resolve the two operator-configurable retention bounds. */
140
+ export function resolveTraceRetentionPolicy(
141
+ overrides: Partial<TraceRetentionPolicy> = {},
142
+ environment: NodeJS.ProcessEnv = process.env,
143
+ ): TraceRetentionPolicy {
144
+ const maxAgeDays =
145
+ overrides.maxAgeDays ??
146
+ parsePositiveRetentionNumber(environment[TRACE_RETENTION_DAYS_ENV], TRACE_RETENTION_DAYS_ENV, 1);
147
+ const maxBytes =
148
+ overrides.maxBytes ??
149
+ parsePositiveRetentionNumber(environment[TRACE_MAX_BYTES_ENV], TRACE_MAX_BYTES_ENV, 1024 * 1024);
150
+ return {
151
+ maxAgeDays: requirePositiveRetentionNumber(maxAgeDays, TRACE_RETENTION_DAYS_ENV, 1),
152
+ maxBytes: requirePositiveRetentionNumber(maxBytes, TRACE_MAX_BYTES_ENV, 1024 * 1024),
153
+ };
154
+ }
155
+
156
+ function parsePositiveRetentionNumber(raw: string | undefined, name: string, fallback: number): number {
157
+ if (raw === undefined || raw.trim().length === 0) {
158
+ return name === TRACE_RETENTION_DAYS_ENV
159
+ ? DEFAULT_TRACE_RETENTION_POLICY.maxAgeDays
160
+ : DEFAULT_TRACE_RETENTION_POLICY.maxBytes;
161
+ }
162
+ const value = Number(raw);
163
+ return requirePositiveRetentionNumber(value, name, fallback);
164
+ }
165
+
166
+ function requirePositiveRetentionNumber(value: number, name: string, minimum: number): number {
167
+ if (!Number.isSafeInteger(value) || value < minimum) {
168
+ throw new Error(`${name} must be an integer of at least ${minimum}`);
169
+ }
170
+ return value;
171
+ }
172
+
113
173
  export class TraceSchemaVersionError extends Error {
114
174
  constructor(readonly found: number | null) {
115
175
  super(
@@ -494,8 +554,13 @@ function reconcileAbandonedRuns(db: DatabaseSync): void {
494
554
 
495
555
  export class TraceStore {
496
556
  readonly db: DatabaseSync;
557
+ private readonly retention: TraceRetentionPolicy;
497
558
 
498
- constructor(readonly path: string) {
559
+ constructor(
560
+ readonly path: string,
561
+ options: { retention?: Partial<TraceRetentionPolicy> } = {},
562
+ ) {
563
+ this.retention = resolveTraceRetentionPolicy(options.retention);
499
564
  mkdirSync(dirname(path), { recursive: true });
500
565
  this.db = new (databaseSyncConstructor())(path);
501
566
  applyConnectionPragmas(this.db);
@@ -523,6 +588,86 @@ export class TraceStore {
523
588
  }
524
589
  }
525
590
 
591
+ /**
592
+ * Remove whole terminal runs, including all of their dependent rows.
593
+ *
594
+ * Age pruning runs first. If the allocated database is still above the byte
595
+ * limit, the oldest remaining terminal runs are removed until the live page
596
+ * set fits or only queued/running runs remain. A live run is never a candidate.
597
+ */
598
+ prune(policy: Partial<TraceRetentionPolicy> = this.retention, now = new Date().toISOString()): TracePruneResult {
599
+ const resolved = resolveTraceRetentionPolicy(policy);
600
+ const nowMs = Date.parse(now);
601
+ if (!Number.isFinite(nowMs)) throw new Error(`trace prune time is invalid: ${now}`);
602
+ const bytesBefore = traceDatabaseFootprintBytes(this.path);
603
+ let rowsRemoved = 0;
604
+ let runsRemoved = 0;
605
+ const removed = new Set<string>();
606
+ const cutoff = new Date(Math.max(0, nowMs - resolved.maxAgeDays * MILLISECONDS_PER_DAY)).toISOString();
607
+
608
+ const ageCandidates = this.db
609
+ .prepare(
610
+ "SELECT run_id FROM runs WHERE status IN ('success','fail') AND ended_at IS NOT NULL AND ended_at < ? ORDER BY ended_at, started_at, run_id",
611
+ )
612
+ .all(cutoff) as { run_id: string }[];
613
+ if (ageCandidates.length > 0) {
614
+ this.transaction(() => {
615
+ for (const candidate of ageCandidates) {
616
+ rowsRemoved += deleteTraceRun(this.db, candidate.run_id);
617
+ runsRemoved += 1;
618
+ removed.add(candidate.run_id);
619
+ }
620
+ });
621
+ }
622
+
623
+ let pages = tracePageStats(this.db);
624
+ if (pages.usedBytes > resolved.maxBytes) {
625
+ const sizeCandidates = this.db
626
+ .prepare(
627
+ "SELECT run_id FROM runs WHERE status IN ('success','fail') AND ended_at IS NOT NULL ORDER BY ended_at, started_at, run_id",
628
+ )
629
+ .all() as { run_id: string }[];
630
+ this.transaction(() => {
631
+ for (const candidate of sizeCandidates) {
632
+ if (pages.usedBytes <= resolved.maxBytes) break;
633
+ if (removed.has(candidate.run_id)) continue;
634
+ rowsRemoved += deleteTraceRun(this.db, candidate.run_id);
635
+ runsRemoved += 1;
636
+ removed.add(candidate.run_id);
637
+ pages = tracePageStats(this.db);
638
+ }
639
+ });
640
+ }
641
+
642
+ pages = tracePageStats(this.db);
643
+ const reclaimableFraction = pages.pageCount === 0 ? 0 : pages.freePages / pages.pageCount;
644
+ const sizeNeedsReclaim = pages.allocatedBytes > resolved.maxBytes && pages.freePages > 0;
645
+ const vacuumed =
646
+ rowsRemoved > 0 && pages.freePages > 0 && (reclaimableFraction >= VACUUM_RECLAIMABLE_FRACTION || sizeNeedsReclaim);
647
+ if (vacuumed) {
648
+ this.db.exec("VACUUM");
649
+ this.db.prepare("PRAGMA wal_checkpoint(TRUNCATE)").get();
650
+ }
651
+
652
+ const protectedRuns = Number(
653
+ (
654
+ this.db.prepare("SELECT COUNT(*) AS count FROM runs WHERE status IN ('queued','running')").get() as {
655
+ count: number | bigint;
656
+ }
657
+ ).count,
658
+ );
659
+ const bytesAfter = traceDatabaseFootprintBytes(this.path);
660
+ return {
661
+ runsRemoved,
662
+ rowsRemoved,
663
+ bytesBefore,
664
+ bytesAfter,
665
+ bytesRemoved: Math.max(0, bytesBefore - bytesAfter),
666
+ vacuumed,
667
+ protectedRuns,
668
+ };
669
+ }
670
+
526
671
  upsertRun(input: DispatchEnqueuedPayload, at = new Date().toISOString()): void {
527
672
  this.transaction(() => {
528
673
  this.db
@@ -859,6 +1004,7 @@ export class TraceStore {
859
1004
  startedAt: at,
860
1005
  });
861
1006
  });
1007
+ this.prune(this.retention, at);
862
1008
  }
863
1009
 
864
1010
  /**
@@ -971,7 +1117,51 @@ export class TraceStore {
971
1117
  startedAt: input.at,
972
1118
  });
973
1119
  });
1120
+ this.prune(this.retention, input.at);
1121
+ }
1122
+ }
1123
+
1124
+ interface TracePageStats {
1125
+ pageCount: number;
1126
+ freePages: number;
1127
+ allocatedBytes: number;
1128
+ usedBytes: number;
1129
+ }
1130
+
1131
+ function tracePageStats(db: DatabaseSync): TracePageStats {
1132
+ const pageSize = Number((db.prepare("PRAGMA page_size").get() as { page_size: number | bigint }).page_size);
1133
+ const pageCount = Number((db.prepare("PRAGMA page_count").get() as { page_count: number | bigint }).page_count);
1134
+ const freePages = Number(
1135
+ (db.prepare("PRAGMA freelist_count").get() as { freelist_count: number | bigint }).freelist_count,
1136
+ );
1137
+ return {
1138
+ pageCount,
1139
+ freePages,
1140
+ allocatedBytes: pageCount * pageSize,
1141
+ usedBytes: Math.max(0, pageCount - freePages) * pageSize,
1142
+ };
1143
+ }
1144
+
1145
+ function deleteTraceRun(db: DatabaseSync, runId: string): number {
1146
+ let rows = 0;
1147
+ for (const table of ["events", "envelopes", "gate_results", "agent_sessions", "processes", "phases", "runs"]) {
1148
+ const result = db.prepare(`DELETE FROM ${table} WHERE run_id=?`).run(runId);
1149
+ rows += Number(result.changes);
1150
+ }
1151
+ return rows;
1152
+ }
1153
+
1154
+ function traceDatabaseFootprintBytes(path: string): number {
1155
+ let total = 0;
1156
+ for (const candidate of [path, `${path}-wal`, `${path}-shm`]) {
1157
+ try {
1158
+ total += statSync(candidate).size;
1159
+ } catch (error) {
1160
+ const code = typeof error === "object" && error !== null && "code" in error ? String(error.code) : "";
1161
+ if (code !== "ENOENT") throw error;
1162
+ }
974
1163
  }
1164
+ return total;
975
1165
  }
976
1166
 
977
1167
  export class TraceReader {
@@ -48,12 +48,22 @@ export interface SessionPromptInputs {
48
48
  memorySection?: string;
49
49
  }
50
50
 
51
+ /**
52
+ * Which section order `compile()` lays down. `volatility` is the product
53
+ * order; `legacy-0.3.8` reproduces the order shipped before issue #249 and
54
+ * exists so a test can prove the change is a pure permutation. Nothing in
55
+ * `src/` may pass `legacy-0.3.8`; the boundary is the test suite.
56
+ */
57
+ export type SessionPromptSectionOrder = "volatility" | "legacy-0.3.8";
58
+
51
59
  export interface CompileInputs {
52
60
  identity: string;
53
61
  operatingContract: string;
54
62
  safety: string;
55
63
  sessionInputs: SessionPromptInputs;
56
64
  additionalFragments?: ReadonlyArray<RenderedPromptFragment>;
65
+ /** Test-only escape hatch; see `SessionPromptSectionOrder`. Defaults to `volatility`. */
66
+ sectionOrder?: SessionPromptSectionOrder;
57
67
  }
58
68
 
59
69
  /** Stable inputs for one mediated fleet worker's canonical system prompt. */
@@ -439,21 +449,93 @@ function renderProjectBlock(contextFiles: string | undefined): string {
439
449
  return trimmedFiles.length === 0 ? "" : `# Project\n\n${trimmedFiles}`;
440
450
  }
441
451
 
442
- function renderMemoryBlock(memorySection: string | undefined): string {
452
+ /**
453
+ * The rendered memory section already opens with its own `# Memory` heading
454
+ * (`domains/memory/prompt-section.ts`), so prepending one unconditionally put
455
+ * the header in the prompt twice. Callers that pass a bare body still get a
456
+ * header; callers that pass a rendered section keep the one they wrote.
457
+ *
458
+ * `legacyDuplicateHeader` reproduces the 0.3.8 behavior and is reachable only
459
+ * through `sectionOrder: "legacy-0.3.8"`, so the permutation test compares
460
+ * against the whole prompt 0.3.8 emitted rather than a half-corrected one.
461
+ */
462
+ function renderMemoryBlock(memorySection: string | undefined, legacyDuplicateHeader = false): string {
443
463
  const trimmed = memorySection?.trim() ?? "";
444
- return trimmed.length === 0 ? "" : `# Memory\n\n${trimmed}`;
464
+ if (trimmed.length === 0) return "";
465
+ if (legacyDuplicateHeader) return `# Memory\n\n${trimmed}`;
466
+ return /^#\s+Memory\s*$/.test(trimmed.split("\n", 1)[0] ?? "") ? trimmed : `# Memory\n\n${trimmed}`;
445
467
  }
446
468
 
447
469
  function estimatePromptTokens(text: string): number {
448
470
  return ceilChars(text.trim().length);
449
471
  }
450
472
 
473
+ /**
474
+ * The session prompt's section order, stable prefix first (issue #249).
475
+ *
476
+ * The rule, and it is the only rule: a section goes as late as its
477
+ * volatility, and anything that reads a clock, a probe, or a mutable store
478
+ * goes after everything that does not. Every backend Clio targets caches by
479
+ * exact prefix and re-prefills from the earliest changed byte, so a section
480
+ * that can change between two turns must not sit ahead of sections that
481
+ * cannot. That is why `runtime` is last of the compiled sections: its
482
+ * `Context window: N` moves when the backend reloads a model or a
483
+ * co-residency clamp lands, and before this order a single changed digit
484
+ * re-prefilled the tool contract, the roster, the hints, memory, and the
485
+ * project context behind it. `memory` sits just ahead of it because an
486
+ * approved memory record rewrites that section mid-session, and
487
+ * `project-context` is stable for the session's lifetime.
488
+ *
489
+ * The tail fragments (`workspace-root`, `clio-repo-awareness`,
490
+ * `project-rules`, `operator-profile`) are appended after this list in their
491
+ * own order: path-scoped project rules grow mid-session by design, which is
492
+ * exactly why they belong at the very end.
493
+ *
494
+ * Moving an entry here is a deliberate cache decision. `tests/contracts/
495
+ * prompt-prefix-layout.test.ts` pins this list so the move has to be made on
496
+ * purpose.
497
+ */
498
+ export const SESSION_PROMPT_SECTION_ORDER: ReadonlyArray<string> = [
499
+ "identity",
500
+ "operating-contract",
501
+ "delegation",
502
+ "skills",
503
+ "safety",
504
+ "tool-contract",
505
+ "fleet",
506
+ "retrieval-hints",
507
+ "project-context",
508
+ "memory",
509
+ "runtime",
510
+ ];
511
+
512
+ /**
513
+ * The order shipped through 0.3.8, kept only so a test can prove the new order
514
+ * is a permutation of it rather than a rewrite. Never reachable from `src/`.
515
+ */
516
+ export const LEGACY_SESSION_PROMPT_SECTION_ORDER: ReadonlyArray<string> = [
517
+ "identity",
518
+ "operating-contract",
519
+ "delegation",
520
+ "skills",
521
+ "safety",
522
+ "runtime",
523
+ "tool-contract",
524
+ "fleet",
525
+ "retrieval-hints",
526
+ "memory",
527
+ "project-context",
528
+ ];
529
+
451
530
  /**
452
531
  * Compile the session system prompt. Identity and the operating contract
453
532
  * render verbatim from disk fragments; safety renders a one-line directive
454
533
  * plus the safety fragment body; everything else renders inline from typed
455
534
  * SessionPromptInputs. Output is one string, one sha256, one token estimate,
456
535
  * and a flat section breakdown for the /context overlay.
536
+ *
537
+ * Sections are laid down in `SESSION_PROMPT_SECTION_ORDER`, whose doc comment
538
+ * states the volatility rule that fixes it.
457
539
  */
458
540
  export function compile(table: FragmentTable, inputs: CompileInputs): CompiledSessionPrompt {
459
541
  const identity = lookupFragment(table, inputs.identity, "identity");
@@ -493,17 +575,22 @@ export function compile(table: FragmentTable, inputs: CompileInputs): CompiledSe
493
575
  const delegation = sessionCanDispatch(session) ? table.byId.get("operating.delegation") : undefined;
494
576
  const skills = sessionHasContext(session) ? table.byId.get("operating.skills") : undefined;
495
577
 
496
- push("identity", identityBody);
497
- push("operating-contract", operatingContract.body);
498
- if (delegation) push("delegation", delegation.body);
499
- if (skills) push("skills", skills.body);
500
- push("safety", renderSafetySection(safety, autonomyLevel));
501
- push("runtime", renderRuntimeBlock(session));
502
- push("tool-contract", renderToolContractBlock(session));
503
- push("fleet", renderFleetBlock(session));
504
- push("retrieval-hints", renderRetrievalHintsBlock(session));
505
- push("memory", renderMemoryBlock(session.memorySection));
506
- push("project-context", renderProjectBlock(session.contextFiles));
578
+ const legacy = inputs.sectionOrder === "legacy-0.3.8";
579
+ const rendered = new Map<string, string>([
580
+ ["identity", identityBody],
581
+ ["operating-contract", operatingContract.body],
582
+ ["delegation", delegation?.body ?? ""],
583
+ ["skills", skills?.body ?? ""],
584
+ ["safety", renderSafetySection(safety, autonomyLevel)],
585
+ ["runtime", renderRuntimeBlock(session)],
586
+ ["tool-contract", renderToolContractBlock(session)],
587
+ ["fleet", renderFleetBlock(session)],
588
+ ["retrieval-hints", renderRetrievalHintsBlock(session)],
589
+ ["memory", renderMemoryBlock(session.memorySection, legacy)],
590
+ ["project-context", renderProjectBlock(session.contextFiles)],
591
+ ]);
592
+ const order = legacy ? LEGACY_SESSION_PROMPT_SECTION_ORDER : SESSION_PROMPT_SECTION_ORDER;
593
+ for (const id of order) push(id, rendered.get(id) ?? "");
507
594
  for (const fragment of inputs.additionalFragments ?? []) {
508
595
  push(fragment.id, fragment.body);
509
596
  }
@@ -15,11 +15,9 @@ export interface CompileWorkerPromptInput extends WorkerPromptInputs {
15
15
  /** Working directory the rule loader and repo-awareness checks run against; defaults to `process.cwd()`. */
16
16
  cwd?: string;
17
17
  /**
18
- * Best-effort paths this worker's run actually touches (from `writeRoots`
19
- * and path-like tokens in the task/briefing text), used the same way the
20
- * session's `workingContextPaths` selects path-scoped project rules. There
21
- * is no structured path field on the model-facing dispatch tool, so this is
22
- * inference, not a guarantee: a rule can be missed, never fabricated.
18
+ * Canonical paths for this worker's declared intent. Legacy requests without
19
+ * intent retain path-like task and briefing inference. The prompt compiler
20
+ * consumes the resolved set without deriving another one.
23
21
  */
24
22
  workingContextPaths?: ReadonlyArray<string>;
25
23
  }
@@ -0,0 +1,96 @@
1
+ import { canonicalEndpointUrl } from "../../core/endpoint-key.js";
2
+ import type { TargetStatus } from "./contract.js";
3
+ import type { TargetDescriptor } from "./types/target-descriptor.js";
4
+
5
+ export type EndpointCapacitySource = "override" | "discovered" | "local-native-default";
6
+
7
+ export interface EndpointCapacity {
8
+ key: string;
9
+ label: string;
10
+ limit: number;
11
+ source: EndpointCapacitySource;
12
+ }
13
+
14
+ /** Runtime ids whose request schedulers are intentionally not modeled as fixed local slots. */
15
+ const UNBOUNDED_LOCAL_NATIVE_RUNTIMES = new Set(["vllm", "sglang"]);
16
+
17
+ /**
18
+ * Canonical identity of the inference scheduler behind a configured target.
19
+ * Scheme, normalized host and port, and normalized base path participate. DNS
20
+ * aliases do not collapse because Clio cannot prove they reach the same server.
21
+ */
22
+ export function canonicalEndpointKey(value: TargetDescriptor | string): string | null {
23
+ return canonicalEndpointUrl(typeof value === "string" ? value : value.url);
24
+ }
25
+
26
+ /** Compact operator-facing identity. A non-root base path remains visible. */
27
+ export function endpointLabel(endpointKey: string): string {
28
+ try {
29
+ const url = new URL(endpointKey);
30
+ return `${url.host}${url.pathname === "/" ? "" : url.pathname}`;
31
+ } catch {
32
+ return endpointKey;
33
+ }
34
+ }
35
+
36
+ function positiveInteger(value: unknown): number | undefined {
37
+ return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : undefined;
38
+ }
39
+
40
+ /** Resolve the endpoint bound from configuration, cached discovery, or the local-native fallback. */
41
+ export function endpointCapacityForStatus(status: TargetStatus): EndpointCapacity | null {
42
+ const key = canonicalEndpointKey(status.target);
43
+ if (key === null) return null;
44
+ const override = positiveInteger(status.target.maxConcurrentRequests);
45
+ if (override !== undefined) return { key, label: endpointLabel(key), limit: override, source: "override" };
46
+ const discovered = positiveInteger(status.probeCapabilities?.parallelSlots);
47
+ if (discovered !== undefined) return { key, label: endpointLabel(key), limit: discovered, source: "discovered" };
48
+ if (status.runtime?.tier !== "local-native" || UNBOUNDED_LOCAL_NATIVE_RUNTIMES.has(status.runtime.id)) return null;
49
+ return { key, label: endpointLabel(key), limit: 1, source: "local-native-default" };
50
+ }
51
+
52
+ function sourceRank(source: EndpointCapacitySource): number {
53
+ return source === "override" ? 2 : source === "discovered" ? 1 : 0;
54
+ }
55
+
56
+ /** Resolve one conservative limit per scheduler, preferring an explicit override. */
57
+ export function endpointCapacitiesForStatuses(
58
+ statuses: ReadonlyArray<TargetStatus>,
59
+ ): Readonly<Record<string, EndpointCapacity>> {
60
+ const capacities: Record<string, EndpointCapacity> = {};
61
+ for (const status of statuses) {
62
+ const candidate = endpointCapacityForStatus(status);
63
+ if (candidate === null) continue;
64
+ const current = capacities[candidate.key];
65
+ if (
66
+ current === undefined ||
67
+ sourceRank(candidate.source) > sourceRank(current.source) ||
68
+ (sourceRank(candidate.source) === sourceRank(current.source) && candidate.limit < current.limit)
69
+ ) {
70
+ capacities[candidate.key] = candidate;
71
+ }
72
+ }
73
+ return capacities;
74
+ }
75
+
76
+ /**
77
+ * The orchestrator's own request lives only in this process. It deliberately
78
+ * never enters dispatch-admission.json because process exit releases it.
79
+ */
80
+ const foregroundStreams = new Map<string, number>();
81
+
82
+ export function registerForegroundStream(endpointKey: string): () => void {
83
+ foregroundStreams.set(endpointKey, (foregroundStreams.get(endpointKey) ?? 0) + 1);
84
+ let held = true;
85
+ return () => {
86
+ if (!held) return;
87
+ held = false;
88
+ const next = (foregroundStreams.get(endpointKey) ?? 1) - 1;
89
+ if (next <= 0) foregroundStreams.delete(endpointKey);
90
+ else foregroundStreams.set(endpointKey, next);
91
+ };
92
+ }
93
+
94
+ export function foregroundStreamUsage(): Readonly<Record<string, number>> {
95
+ return Object.fromEntries(foregroundStreams);
96
+ }
@@ -16,6 +16,7 @@ import { probeCapabilitiesForModel } from "./model-capabilities.js";
16
16
  import { loadPluginRuntimes } from "./plugins.js";
17
17
  import { getRuntimeRegistry } from "./registry.js";
18
18
  import { registerBuiltinRuntimes } from "./runtimes/builtins.js";
19
+ import { listKnownModelsForRuntime } from "./support.js";
19
20
  import type { CapabilityFlags } from "./types/capability-flags.js";
20
21
  import { EMPTY_CAPABILITIES } from "./types/capability-flags.js";
21
22
  import {
@@ -204,6 +205,32 @@ export function mergeProbeResult(
204
205
  return merge;
205
206
  }
206
207
 
208
+ /**
209
+ * Whether a reachable target can serve the model it is configured to serve by
210
+ * default. Reachability alone was the whole of `health`, so a target whose
211
+ * `defaultModel` the server had never heard of printed `healthy` until the
212
+ * first turn. This is judged only from a live list on a runtime with no static
213
+ * catalog: the catalog is the authority for cloud runtimes, and a cached or
214
+ * descriptor-supplied list says nothing about the server in front of us.
215
+ * Returns the reason when the default is not served, null when it is or when
216
+ * there is no live evidence either way.
217
+ */
218
+ export function unservedDefaultModelReason(
219
+ desc: Pick<RuntimeDescriptor, "id">,
220
+ target: Pick<TargetDescriptor, "defaultModel">,
221
+ merge: Pick<ProbeMerge, "discoveredModels" | "discoveredModelsSource" | "discoveredModelStates">,
222
+ ): string | null {
223
+ const model = target.defaultModel;
224
+ if (!model) return null;
225
+ if (merge.discoveredModelsSource !== "probe" || merge.discoveredModels.length === 0) return null;
226
+ if (listKnownModelsForRuntime(desc.id).length > 0) return null;
227
+ if (merge.discoveredModels.includes(model)) return null;
228
+ // LM Studio lists a loaded model under its instance id and keeps the model
229
+ // key in the state map; the request path resolves either.
230
+ if (merge.discoveredModelStates && model in merge.discoveredModelStates) return null;
231
+ return `default model '${model}' is not advertised by the target`;
232
+ }
233
+
207
234
  export function createProvidersBundle(context: DomainContext): DomainBundle<ProvidersContract> {
208
235
  const registry = getRuntimeRegistry();
209
236
  const authStore = openAuthStorage();
@@ -292,13 +319,14 @@ export function createProvidersBundle(context: DomainContext): DomainBundle<Prov
292
319
  const merge = mergeProbeResult(desc, target, probe, previous);
293
320
  const { capabilities, contextWindowProvenance } = capabilitiesFor(desc, target, merge, kb);
294
321
  const healthy = probe !== null ? probe.ok : null;
322
+ const unservedDefault = probe?.ok ? unservedDefaultModelReason(desc, target, merge) : null;
295
323
  const health: TargetHealth =
296
324
  probe === null
297
325
  ? (previous?.health ?? emptyHealth())
298
326
  : {
299
- status: healthy ? "healthy" : "down",
327
+ status: healthy ? (unservedDefault === null ? "healthy" : "degraded") : "down",
300
328
  lastCheckAt: new Date().toISOString(),
301
- lastError: probe.error ?? null,
329
+ lastError: probe.error ?? unservedDefault,
302
330
  latencyMs: probe.latencyMs ?? null,
303
331
  };
304
332
  const available = availability.available && (probe === null || probe.ok);
@@ -27,6 +27,16 @@ export {
27
27
  export { AGENT_ROLE_TOOLS_REQUIRED_REASON, mergeCapabilities, supportsAgentRoleTools } from "./capabilities.js";
28
28
  export type { ProvidersContract, TargetHealth, TargetStatus } from "./contract.js";
29
29
  export { isDispatchEligibleRuntime, isOrchestratorEligibleRuntime, isTargetEligibleRuntime } from "./eligibility.js";
30
+ export {
31
+ canonicalEndpointKey,
32
+ type EndpointCapacity,
33
+ type EndpointCapacitySource,
34
+ endpointCapacitiesForStatuses,
35
+ endpointCapacityForStatus,
36
+ endpointLabel,
37
+ foregroundStreamUsage,
38
+ registerForegroundStream,
39
+ } from "./endpoint-capacity.js";
30
40
  export { ProvidersManifest } from "./manifest.js";
31
41
  export type { ModelCapabilityPatchTarget } from "./model-capabilities.js";
32
42
  export { applyModelCapabilityPatch, resolveModelCapabilities } from "./model-capabilities.js";