@iowarp/clio-coder 0.3.9 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (416) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/NOTICE +33 -0
  3. package/README.md +7 -2
  4. package/dist/{acp-7LOELQFP.js → acp-G5WJBNCT.js} +13 -12
  5. package/dist/{agents-FIBG2SHA.js → agents-FMV2Q5G4.js} +39 -36
  6. package/dist/assets/codewiki.json +1 -1
  7. package/dist/{auth-OI4LIH2I.js → auth-3IDSJEIK.js} +16 -15
  8. package/dist/{builtins-AD25UL3C.js → builtins-XCZWXSC7.js} +3 -3
  9. package/dist/{chunk-IFBNV6H6.js → chunk-2ANTL7MR.js} +3 -3
  10. package/dist/{chunk-56KB5IJP.js → chunk-2OQE55CK.js} +3 -3
  11. package/dist/{chunk-N3PBVRTZ.js → chunk-32KWKNSF.js} +9 -7
  12. package/dist/{chunk-VKBMFOYV.js → chunk-36EJLSQQ.js} +23 -27
  13. package/dist/{chunk-465CC7FK.js → chunk-3BT2XMV4.js} +16 -13
  14. package/dist/{chunk-NQ6UCCOD.js → chunk-3URVFKWK.js} +7 -7
  15. package/dist/{chunk-WIE7ZOSW.js → chunk-3XML7CDN.js} +2 -2
  16. package/dist/chunk-42FMPA75.js +101 -0
  17. package/dist/{chunk-A2NJGIB3.js → chunk-5LXZXPKX.js} +2 -2
  18. package/dist/{chunk-HAY4ZE2P.js → chunk-5PSMVOLM.js} +2 -2
  19. package/dist/{chunk-JEQQR47K.js → chunk-6DB53AJS.js} +168 -9
  20. package/dist/{chunk-KV2AOLDF.js → chunk-76ONBSIA.js} +5 -25
  21. package/dist/{chunk-FALJGAWU.js → chunk-7MCTRUCE.js} +2 -2
  22. package/dist/{chunk-5T7RBWN2.js → chunk-AB44T6BB.js} +5 -5
  23. package/dist/chunk-B7OBL7PK.js +1405 -0
  24. package/dist/{chunk-B5CSFE7B.js → chunk-BBVJUZHB.js} +2 -2
  25. package/dist/{chunk-EQ63NRB7.js → chunk-BBVYXMFO.js} +2 -2
  26. package/dist/{chunk-O6I4CIEU.js → chunk-BKFJHQCA.js} +6 -6
  27. package/dist/chunk-BKFM6EJV.js +462 -0
  28. package/dist/chunk-BMS5RKQY.js +27 -0
  29. package/dist/{chunk-MV2VUEJC.js → chunk-BPKCPIL7.js} +2 -2
  30. package/dist/{chunk-TEO2TLVN.js → chunk-BUMFYQFY.js} +964 -1120
  31. package/dist/{chunk-BNAZZHFG.js → chunk-BYP5D4HI.js} +1 -1
  32. package/dist/chunk-C2LTL2W6.js +2447 -0
  33. package/dist/{chunk-EBOC7MT3.js → chunk-CODPRO7Q.js} +8 -8
  34. package/dist/{chunk-HPCTNZM2.js → chunk-CTJ4RNAA.js} +4 -4
  35. package/dist/{chunk-ODFEOB4F.js → chunk-CY6FY24N.js} +26 -8
  36. package/dist/{chunk-MIX5N5AC.js → chunk-DQITNCXG.js} +394 -154
  37. package/dist/{chunk-S4COXYBG.js → chunk-DYJP44XW.js} +129 -106
  38. package/dist/{chunk-N5XKWMDW.js → chunk-F4CKPOEQ.js} +6 -6
  39. package/dist/{chunk-AMKHQW3C.js → chunk-FEFIFZTL.js} +3 -3
  40. package/dist/{chunk-MV3K5QF2.js → chunk-GCSMB2KY.js} +2 -2
  41. package/dist/{chunk-7C6RYZGQ.js → chunk-GKF55TAZ.js} +3 -3
  42. package/dist/{chunk-B5XRQOLB.js → chunk-GR5G2PVF.js} +9 -8
  43. package/dist/{chunk-XDOQXGFO.js → chunk-GXNLGKAB.js} +64 -8
  44. package/dist/chunk-HHV2GANA.js +88 -0
  45. package/dist/{chunk-774ILSRL.js → chunk-HI63TFOG.js} +4 -3
  46. package/dist/{chunk-R7LNVMCS.js → chunk-HJJTYUHX.js} +64 -72
  47. package/dist/{chunk-RKRLDWD3.js → chunk-HLW2MRKE.js} +1 -1
  48. package/dist/{chunk-CA42X6KT.js → chunk-HWHKMHUA.js} +6 -6
  49. package/dist/chunk-HZHHCK24.js +1631 -0
  50. package/dist/{chunk-HJB5IUKP.js → chunk-I5VEOC6I.js} +12 -12
  51. package/dist/chunk-IBEBSCYA.js +564 -0
  52. package/dist/chunk-IQ7KR472.js +362 -0
  53. package/dist/{chunk-4H6ULJ3H.js → chunk-J4W7KFM7.js} +921 -990
  54. package/dist/{chunk-4LJX2PUC.js → chunk-JDG2WCRO.js} +5 -5
  55. package/dist/{chunk-NZU6YDNV.js → chunk-K5C3NCBD.js} +4 -4
  56. package/dist/{chunk-CGKSTWHD.js → chunk-K6BSR66V.js} +2 -1
  57. package/dist/{chunk-NNNWO6F2.js → chunk-KFZI4NIL.js} +93 -3
  58. package/dist/chunk-KMVISBZR.js +132 -0
  59. package/dist/{chunk-BVDVID7E.js → chunk-LDQ2ZF2M.js} +2 -2
  60. package/dist/{chunk-OEDBCISO.js → chunk-LQ3DZAMX.js} +2 -2
  61. package/dist/{chunk-PZ4I4JE2.js → chunk-LY4S7GJC.js} +124 -116
  62. package/dist/{chunk-3DUR4WUA.js → chunk-MLKNTWH2.js} +19 -19
  63. package/dist/chunk-NEKRRTYW.js +56 -0
  64. package/dist/{chunk-5DQRIYDZ.js → chunk-NHCZP4K7.js} +2 -2
  65. package/dist/chunk-NHLBIGRH.js +1506 -0
  66. package/dist/chunk-NQQH3YT7.js +302 -0
  67. package/dist/chunk-NYS75XW5.js +15 -0
  68. package/dist/{chunk-TD7UE2L5.js → chunk-O4XIVISU.js} +7 -7
  69. package/dist/{chunk-WXCJ7VME.js → chunk-O6TL7WWY.js} +6 -6
  70. package/dist/chunk-OQBA45DZ.js +97 -0
  71. package/dist/{chunk-LU7P4LHA.js → chunk-P3FOHJT4.js} +2 -2
  72. package/dist/chunk-PMZCIOCJ.js +25 -0
  73. package/dist/{chunk-I4HZDVNP.js → chunk-PQEFIJ36.js} +2 -2
  74. package/dist/{chunk-HKO36JWF.js → chunk-QBJA7R7N.js} +31 -3
  75. package/dist/chunk-QDC3K2U3.js +262 -0
  76. package/dist/{chunk-5HFBWUMU.js → chunk-QLFS5GO2.js} +4 -4
  77. package/dist/{chunk-GAYUJ7LE.js → chunk-QLL7ILRG.js} +41 -32
  78. package/dist/{chunk-LXPJXFM5.js → chunk-QREDIESB.js} +7 -7
  79. package/dist/chunk-QSNYB6ZV.js +195 -0
  80. package/dist/chunk-R346GLFC.js +31 -0
  81. package/dist/{chunk-VPTUJU4P.js → chunk-SJ5ZKQ4S.js} +2 -2
  82. package/dist/{chunk-QQ7EKM72.js → chunk-SP2RXXYO.js} +6 -54
  83. package/dist/chunk-SUCTJL45.js +45 -0
  84. package/dist/{chunk-5QKCQQ3E.js → chunk-SUW5DORT.js} +2 -2
  85. package/dist/chunk-T56WDKA5.js +183 -0
  86. package/dist/chunk-TVHHYFHE.js +255 -0
  87. package/dist/{chunk-IHKBWSXF.js → chunk-TZ3SGWZZ.js} +2 -2
  88. package/dist/{chunk-ECUO3KDP.js → chunk-U77AMWDL.js} +47 -7
  89. package/dist/{chunk-3UUY7R3Z.js → chunk-ULC6OTWO.js} +7 -7
  90. package/dist/{chunk-AEYBF3TB.js → chunk-UM7N4G5A.js} +2 -2
  91. package/dist/{chunk-3V5AYSEQ.js → chunk-UXMFQ54G.js} +43 -36
  92. package/dist/{chunk-YW7UVM5V.js → chunk-V5DHCITQ.js} +34 -1
  93. package/dist/{chunk-47CMYGET.js → chunk-VAZSBTKF.js} +2 -2
  94. package/dist/{chunk-3MRC2YSQ.js → chunk-VEO4AP2K.js} +2 -2
  95. package/dist/{chunk-PNY46YEY.js → chunk-VFA6GDY5.js} +47 -3
  96. package/dist/chunk-VO67MWHC.js +75 -0
  97. package/dist/{chunk-XK56QHLX.js → chunk-VPKWYKEY.js} +19 -5
  98. package/dist/{chunk-AD7Y7STJ.js → chunk-VYMXRQI6.js} +36 -22
  99. package/dist/{chunk-T3Z6VAAF.js → chunk-W5VSYASO.js} +19 -17
  100. package/dist/{chunk-5PVQ4SRS.js → chunk-WZR7K7ZX.js} +7 -123
  101. package/dist/{chunk-DG4M6ZUE.js → chunk-X3YGUTOB.js} +4 -4
  102. package/dist/chunk-X75E3D2N.js +686 -0
  103. package/dist/{chunk-P3JGPQFL.js → chunk-YDFRH54B.js} +4 -4
  104. package/dist/chunk-YJX4SHTD.js +40 -0
  105. package/dist/{chunk-ZI647VB5.js → chunk-YPI3QQCF.js} +2 -2
  106. package/dist/{chunk-YSEHGPCT.js → chunk-Z2RR6MAK.js} +3 -3
  107. package/dist/{chunk-HCBCAYZU.js → chunk-Z4TXYIEG.js} +5 -5
  108. package/dist/cli/index.js +47 -36
  109. package/dist/{clio-LT5V7SSZ.js → clio-2JXHBBY5.js} +7 -7
  110. package/dist/{code-nav-LMW275PA.js → code-nav-3YYRMYNF.js} +6 -6
  111. package/dist/{compile-cache-CVJMMODC.js → compile-cache-7FPE6PS3.js} +3 -3
  112. package/dist/{components-ZFA3SAER.js → components-RYZV4JGP.js} +5 -5
  113. package/dist/{config-RXS5T3JT.js → config-QZPCMYSO.js} +58 -50
  114. package/dist/{configure-2WYWSCSD.js → configure-TEGEBYCA.js} +21 -19
  115. package/dist/{context-I3BTOTCS.js → context-AV7OEZ4D.js} +11 -11
  116. package/dist/{context-MVOORGMF.js → context-E6H5RNMC.js} +49 -41
  117. package/dist/{context-PALKKQYL.js → context-GSXUE4CT.js} +25 -23
  118. package/dist/{context-clear-N2WOYZ2K.js → context-clear-SHIBYK6T.js} +48 -40
  119. package/dist/{context-working-set-MIEVECVZ.js → context-working-set-5ZGKPGZQ.js} +11 -10
  120. package/dist/{dispatch-runner-VVA4SRRH.js → dispatch-runner-EFMJT4LD.js} +88 -60
  121. package/dist/{docs-7LQ23DLM.js → docs-23KQS3XK.js} +5 -5
  122. package/dist/doctor-QOA5FNY5.js +313 -0
  123. package/dist/{eval-IJ5VEZDJ.js → eval-TFBYQH4H.js} +66 -64
  124. package/dist/eval-inventory-SXH7PDKX.js +316 -0
  125. package/dist/{evidence-L5APPXNV.js → evidence-ERGESKGN.js} +198 -44
  126. package/dist/{evolve-RGNKFJ52.js → evolve-VDXTSYCJ.js} +46 -38
  127. package/dist/{extensions-7WYWUX5A.js → extensions-7BGBHN57.js} +6 -6
  128. package/dist/{fleet-6CNVBZZP.js → fleet-2RRVDF2V.js} +189 -101
  129. package/dist/{fleet-commands-L2SXSYEI.js → fleet-commands-VJ726XIA.js} +10 -10
  130. package/dist/fleet-decisions-EPAPM3XJ.js +157 -0
  131. package/dist/{fleet-graph-2J3OOIPO.js → fleet-graph-JF5QOATM.js} +16 -15
  132. package/dist/fleet-inspect-VLY4S7QM.js +442 -0
  133. package/dist/{fleet-preflight-CZRJ4JP5.js → fleet-preflight-AIZUEJOY.js} +6 -5
  134. package/dist/{fleet-validate-C5RI6DP7.js → fleet-validate-AJRPDMDV.js} +20 -18
  135. package/dist/fleet-verify-JFEL2L3H.js +175 -0
  136. package/dist/fleet-view-ZCON35AG.js +102 -0
  137. package/dist/{init-VBN2ACVA.js → init-DN2WWLFE.js} +64 -56
  138. package/dist/install-XGLBQY5E.js +13 -0
  139. package/dist/interop-OZBKXAYL.js +114 -0
  140. package/dist/{library-JHGUMLY2.js → library-YWZG7IMW.js} +19 -18
  141. package/dist/{memory-K4OQIYWG.js → memory-I4C4HMLW.js} +48 -40
  142. package/dist/{models-2NCZUWDD.js → models-CEYXJBO6.js} +30 -28
  143. package/dist/{monitor-MMVTJABD.js → monitor-NZ6GCI3P.js} +53 -47
  144. package/dist/{orchestrator-ZKBPCHW6.js → orchestrator-GCGQ4N5I.js} +6311 -7145
  145. package/dist/panes-HMABYVO4.js +58 -0
  146. package/dist/panes-KY6W3V2E.js +103 -0
  147. package/dist/{paths-DBXMZMDU.js → paths-II4K7DNR.js} +5 -5
  148. package/dist/{reset-DD5JGOY3.js → reset-DQ6FGCSH.js} +13 -11
  149. package/dist/resources-BB3MVJMD.js +111 -0
  150. package/dist/{run-QEGNX7FL.js → run-H2GQDUER.js} +113 -82
  151. package/dist/{share-JKD3BQMW.js → share-GTJN6A5O.js} +18 -17
  152. package/dist/{skills-LMQIKDOZ.js → skills-L55TEW6R.js} +31 -24
  153. package/dist/{skills-eval-I7X2774U.js → skills-eval-XVXPH2JI.js} +61 -52
  154. package/dist/skills-inventory-S4MXPJFV.js +126 -0
  155. package/dist/slash-commands-ZSGASKJC.js +77 -0
  156. package/dist/{steer-CF5TDANS.js → steer-RZGSCY4R.js} +3 -3
  157. package/dist/{support-I7LOJLIF.js → support-PKEUNNQL.js} +4 -4
  158. package/dist/{targets-RUSR6B5Z.js → targets-NCPZ644J.js} +31 -29
  159. package/dist/{terminal-lease-QYVORFR4.js → terminal-lease-44SV3YCN.js} +4 -4
  160. package/dist/tools-DAF3DI3C.js +27 -0
  161. package/dist/{trace-ODOQIVIW.js → trace-FYVW2MQA.js} +149 -7
  162. package/dist/tui-primitives-2AKXQNZK.js +13 -0
  163. package/dist/{uninstall-ZJF5H5ZN.js → uninstall-DW2PNOIC.js} +5 -5
  164. package/dist/{upgrade-XANW3FXB.js → upgrade-3XPP6OQL.js} +26 -24
  165. package/dist/{usage-4H7ZRXQT.js → usage-3NLHGTU2.js} +57 -49
  166. package/dist/{verifiers-UZXNBZEB.js → verifiers-SSQONKRT.js} +171 -12
  167. package/dist/{verify-BVKWTNDL.js → verify-3U6J7FZI.js} +9 -9
  168. package/dist/{web-fetch-2YHJ3KTG.js → web-fetch-S7RR6GZ7.js} +3 -3
  169. package/dist/{wiki-generate-MY7WV2QI.js → wiki-generate-CEHYGPGQ.js} +67 -59
  170. package/dist/with-panes-MKB46MPQ.js +782 -0
  171. package/dist/worker/entry.js +101 -66
  172. package/docs/README.md +3 -2
  173. package/docs/acp.md +24 -3
  174. package/docs/alcf-provider.md +1 -1
  175. package/docs/architecture.md +2 -2
  176. package/docs/artifact-versions.md +4 -1
  177. package/docs/built-in-agents.md +1 -1
  178. package/docs/capacity-and-scheduling.md +43 -5
  179. package/docs/commands-and-modes.md +31 -2
  180. package/docs/configuration-and-targets.md +40 -10
  181. package/docs/context-engine.md +1 -1
  182. package/docs/development-pipeline.md +19 -0
  183. package/docs/dispatch-typed-intent.md +385 -0
  184. package/docs/documentation-coverage.md +2 -2
  185. package/docs/documentation-guide.md +1 -1
  186. package/docs/environment-variables.md +1 -0
  187. package/docs/eval-runner.md +1 -1
  188. package/docs/evals-internal.md +1 -1
  189. package/docs/evidence-and-memory.md +2 -2
  190. package/docs/evolution.md +1 -1
  191. package/docs/exit-codes-and-output.md +1 -1
  192. package/docs/extensions-and-sharing.md +25 -1
  193. package/docs/fleet-dispatch.md +22 -1
  194. package/docs/installation-and-lifecycle.md +15 -2
  195. package/docs/middleware-and-components.md +1 -1
  196. package/docs/model-catalog.md +10 -1
  197. package/docs/observability.md +3 -3
  198. package/docs/proactive-memory.md +1 -1
  199. package/docs/prompt-envelope-and-tools.md +1 -1
  200. package/docs/provider-adapter-cookbook.md +1 -1
  201. package/docs/safety-model.md +2 -2
  202. package/docs/scientific-validation.md +3 -3
  203. package/docs/session-lifecycle.md +1 -1
  204. package/docs/skills-marketplace.md +1 -1
  205. package/docs/tool-usage.md +18 -8
  206. package/docs/trace-store.md +1 -1
  207. package/docs/troubleshooting.md +1 -1
  208. package/docs/tui-design.md +1 -1
  209. package/docs/worker-dispatch-mechanics.md +1 -1
  210. package/package.json +4 -2
  211. package/src/cli/acp.ts +6 -2
  212. package/src/cli/argv.ts +25 -0
  213. package/src/cli/configure.ts +23 -21
  214. package/src/cli/doctor-panes.ts +124 -0
  215. package/src/cli/doctor-toolchain.ts +57 -0
  216. package/src/cli/doctor.ts +20 -1
  217. package/src/cli/eval-inventory.ts +436 -0
  218. package/src/cli/eval.ts +13 -0
  219. package/src/cli/evidence-detail.ts +88 -0
  220. package/src/cli/evidence-inventory.ts +183 -0
  221. package/src/cli/evidence.ts +30 -5
  222. package/src/cli/fleet-decisions.ts +69 -0
  223. package/src/cli/fleet-inspect.ts +334 -0
  224. package/src/cli/fleet-verify.ts +133 -0
  225. package/src/cli/fleet-view.ts +810 -0
  226. package/src/cli/fleet.ts +148 -37
  227. package/src/cli/index.ts +14 -2
  228. package/src/cli/interop-inspect.ts +128 -0
  229. package/src/cli/interop.ts +34 -0
  230. package/src/cli/panes.ts +35 -0
  231. package/src/cli/reset.ts +5 -2
  232. package/src/cli/run.ts +58 -0
  233. package/src/cli/skills-inventory.ts +185 -0
  234. package/src/cli/skills.ts +16 -13
  235. package/src/cli/tools.ts +321 -0
  236. package/src/cli/trace-inspect.ts +252 -0
  237. package/src/cli/trace.ts +23 -2
  238. package/src/cli/verifiers-inspect.ts +347 -0
  239. package/src/cli/verifiers.ts +9 -0
  240. package/src/core/bus-events.ts +4 -0
  241. package/src/core/config.ts +49 -0
  242. package/src/core/defaults.ts +93 -7
  243. package/src/core/response-schema.ts +44 -4
  244. package/src/core/theme-token-hex.ts +43 -0
  245. package/src/core/tool-names.ts +2 -1
  246. package/src/core/xdg.ts +1 -1
  247. package/src/domains/agents/fleets/build-review.md +0 -3
  248. package/src/domains/agents/fleets/build-test.md +0 -3
  249. package/src/domains/agents/result-contract-filesystem.ts +32 -0
  250. package/src/domains/agents/result-contract.ts +164 -35
  251. package/src/domains/config/classify.ts +3 -0
  252. package/src/domains/dispatch/admission-error.ts +9 -0
  253. package/src/domains/dispatch/admission.ts +22 -21
  254. package/src/domains/dispatch/capacity-lease.ts +21 -1
  255. package/src/domains/dispatch/council-topology.ts +398 -0
  256. package/src/domains/dispatch/extension.ts +222 -50
  257. package/src/domains/dispatch/fleet-node-prompt.ts +62 -0
  258. package/src/domains/dispatch/fleet-plan.ts +7 -2
  259. package/src/domains/dispatch/fleet-run.ts +64 -1
  260. package/src/domains/dispatch/gate-decisions.ts +11 -1
  261. package/src/domains/dispatch/gate-role-prompts.ts +9 -0
  262. package/src/domains/dispatch/gate-topology.ts +289 -0
  263. package/src/domains/dispatch/index.ts +19 -0
  264. package/src/domains/dispatch/intent-compatibility.ts +330 -0
  265. package/src/domains/dispatch/intent.ts +85 -1
  266. package/src/domains/dispatch/reservation-store.ts +24 -4
  267. package/src/domains/dispatch/run-event-journal-bridge.ts +149 -0
  268. package/src/domains/dispatch/run-event-journal.ts +598 -0
  269. package/src/domains/dispatch/state.ts +45 -1
  270. package/src/domains/dispatch/types.ts +13 -0
  271. package/src/domains/dispatch/validation.ts +33 -8
  272. package/src/domains/eval/compare/compare.ts +3 -16
  273. package/src/domains/eval/inventory.ts +113 -0
  274. package/src/domains/eval/schema/serving.ts +31 -0
  275. package/src/domains/evidence/store.ts +6 -0
  276. package/src/domains/memory/index.ts +0 -1
  277. package/src/domains/memory/task-memory-policy.ts +6 -10
  278. package/src/domains/memory/task-memory-telemetry.ts +1 -0
  279. package/src/domains/middleware/memory-intervention.ts +33 -21
  280. package/src/domains/mux/contract.ts +434 -0
  281. package/src/domains/mux/detect.ts +158 -0
  282. package/src/domains/mux/extension.ts +47 -0
  283. package/src/domains/mux/index.ts +96 -0
  284. package/src/domains/mux/manifest.ts +6 -0
  285. package/src/domains/mux/operations.ts +164 -0
  286. package/src/domains/mux/pane-registry.ts +90 -0
  287. package/src/domains/mux/protocol.ts +49 -0
  288. package/src/domains/mux/socket-client.ts +816 -0
  289. package/src/domains/mux/types.ts +222 -0
  290. package/src/domains/mux/viewer-command.ts +59 -0
  291. package/src/domains/mux/yazi/assets/init.lua +2 -0
  292. package/src/domains/mux/yazi/assets/plugins/git.yazi/LICENSE +21 -0
  293. package/src/domains/mux/yazi/assets/plugins/git.yazi/README.md +78 -0
  294. package/src/domains/mux/yazi/assets/plugins/git.yazi/main.lua +255 -0
  295. package/src/domains/mux/yazi/assets/plugins/git.yazi/types.lua +12 -0
  296. package/src/domains/mux/yazi/assets/yazi.toml +17 -0
  297. package/src/domains/mux/yazi/event-stream.ts +180 -0
  298. package/src/domains/mux/yazi/profile.ts +299 -0
  299. package/src/domains/mux/yazi/session.ts +228 -0
  300. package/src/domains/mux/yazi/theme.ts +30 -0
  301. package/src/domains/observability/cost.ts +21 -0
  302. package/src/domains/observability/index.ts +2 -0
  303. package/src/domains/observability/trace-store.ts +42 -0
  304. package/src/domains/providers/endpoint-capacity.ts +154 -22
  305. package/src/domains/providers/endpoint-slots-store.ts +189 -0
  306. package/src/domains/providers/extension.ts +20 -3
  307. package/src/domains/providers/index.ts +22 -0
  308. package/src/domains/providers/model-runtime-capabilities.ts +32 -0
  309. package/src/domains/providers/runtimes/boot-manifest.ts +1 -0
  310. package/src/domains/providers/runtimes/builtins.ts +2 -0
  311. package/src/domains/providers/runtimes/protocol/litellm.ts +375 -0
  312. package/src/domains/providers/support.ts +1 -0
  313. package/src/domains/providers/target-model-cache.ts +124 -0
  314. package/src/domains/resources/index.ts +3 -0
  315. package/src/domains/resources/skills/loader.ts +33 -0
  316. package/src/domains/safety/action-classifier.ts +6 -0
  317. package/src/domains/toolchain/archive.ts +175 -0
  318. package/src/domains/toolchain/contract.ts +28 -0
  319. package/src/domains/toolchain/extension.ts +47 -0
  320. package/src/domains/toolchain/index.ts +39 -0
  321. package/src/domains/toolchain/install.ts +327 -0
  322. package/src/domains/toolchain/manifest.ts +8 -0
  323. package/src/domains/toolchain/paths.ts +34 -0
  324. package/src/domains/toolchain/registry.ts +265 -0
  325. package/src/domains/toolchain/remove.ts +218 -0
  326. package/src/domains/toolchain/resolve.ts +182 -0
  327. package/src/domains/toolchain/types.ts +113 -0
  328. package/src/domains/toolchain/version.ts +88 -0
  329. package/src/engine/acp/server.ts +413 -70
  330. package/src/engine/acp/types.ts +19 -1
  331. package/src/engine/claude/sdk-module.ts +98 -0
  332. package/src/engine/claude/sdk-runtime.ts +19 -11
  333. package/src/engine/tui-primitives.ts +21 -0
  334. package/src/engine/tui.ts +1 -0
  335. package/src/engine/worker-runtime.ts +2 -13
  336. package/src/entry/boot-options.ts +2 -0
  337. package/src/entry/orchestrator.ts +103 -5
  338. package/src/entry/panes-activation.ts +31 -0
  339. package/src/entry/with-panes.ts +20 -0
  340. package/src/interactive/context-overlay.ts +1 -0
  341. package/src/interactive/cost-overlay.ts +2 -0
  342. package/src/interactive/council-grid.ts +1 -3
  343. package/src/interactive/council.ts +11 -0
  344. package/src/interactive/dispatch-board.ts +26 -16
  345. package/src/interactive/interactive-application.ts +153 -6
  346. package/src/interactive/interactive-input-runtime.ts +7 -0
  347. package/src/interactive/interactive-slash-runtime.ts +36 -6
  348. package/src/interactive/memory-overlay.ts +1 -0
  349. package/src/interactive/modal-marker.ts +170 -0
  350. package/src/interactive/mux-bridge.ts +214 -0
  351. package/src/interactive/overlay-frame.ts +58 -2
  352. package/src/interactive/overlay-general-openers.ts +1 -0
  353. package/src/interactive/overlay-key-routing.ts +14 -3
  354. package/src/interactive/overlay-lifecycle.ts +19 -3
  355. package/src/interactive/overlay-model-selectors.ts +40 -3
  356. package/src/interactive/overlay-permission-lifecycle.ts +90 -22
  357. package/src/interactive/overlay-transitions.ts +18 -4
  358. package/src/interactive/overlays/agents.ts +1 -0
  359. package/src/interactive/overlays/ask-user.ts +136 -30
  360. package/src/interactive/overlays/auth-dialog.ts +1 -0
  361. package/src/interactive/overlays/context-reset.ts +1 -0
  362. package/src/interactive/overlays/cwd-fallback.ts +1 -0
  363. package/src/interactive/overlays/decisions.ts +11 -11
  364. package/src/interactive/overlays/extensions.ts +1 -0
  365. package/src/interactive/overlays/fleet-run-approval.ts +1 -0
  366. package/src/interactive/overlays/handoff-review.ts +1 -0
  367. package/src/interactive/overlays/help-reference.ts +2 -0
  368. package/src/interactive/overlays/interop.ts +1 -0
  369. package/src/interactive/overlays/library-install-confirm.ts +1 -0
  370. package/src/interactive/overlays/library-tabs.ts +28 -0
  371. package/src/interactive/overlays/list-overlay.ts +10 -1
  372. package/src/interactive/overlays/message-picker.ts +1 -0
  373. package/src/interactive/overlays/model-scope.ts +86 -0
  374. package/src/interactive/overlays/model-selector.ts +1 -0
  375. package/src/interactive/overlays/prompts.ts +1 -0
  376. package/src/interactive/overlays/session-selector.ts +1 -0
  377. package/src/interactive/overlays/settings-sections.ts +30 -0
  378. package/src/interactive/overlays/settings.ts +579 -44
  379. package/src/interactive/overlays/side-question.ts +1 -0
  380. package/src/interactive/overlays/skills-hub.ts +3 -11
  381. package/src/interactive/overlays/tree-selector.ts +1 -0
  382. package/src/interactive/pane-policy.ts +46 -0
  383. package/src/interactive/panes-runtime.ts +292 -0
  384. package/src/interactive/renderers/compaction-summary.ts +29 -0
  385. package/src/interactive/renderers/worker-entry.ts +122 -14
  386. package/src/interactive/slash-commands.ts +251 -15
  387. package/src/interactive/tasks-overlay.ts +1 -0
  388. package/src/interactive/theme/tokens.ts +3 -14
  389. package/src/interactive/turn-context.ts +47 -2
  390. package/src/interactive/view/artifacts.ts +109 -1
  391. package/src/interactive/view/view-overlay.ts +1 -0
  392. package/src/interactive/watch-pane.ts +152 -0
  393. package/src/interactive/worker-progress.ts +7 -1
  394. package/src/interactive/worker-receipts.ts +19 -1
  395. package/src/interactive/worker-stream.ts +5 -0
  396. package/src/interactive/yazi-bridge.ts +444 -0
  397. package/src/tools/bootstrap.ts +26 -2
  398. package/src/tools/builtin-tool-catalog.ts +15 -0
  399. package/src/tools/compete-worktrees.ts +83 -2
  400. package/src/tools/core-bootstrap.ts +2 -1
  401. package/src/tools/dispatch-admission.ts +14 -3
  402. package/src/tools/dispatch-arguments.ts +20 -20
  403. package/src/tools/dispatch-run-events.ts +134 -19
  404. package/src/tools/dispatch-runner.ts +29 -7
  405. package/src/tools/dispatch-types.ts +15 -3
  406. package/src/tools/dispatch.ts +1 -1
  407. package/src/tools/executables.ts +17 -14
  408. package/src/tools/observation.ts +54 -4
  409. package/src/tools/panes-surface.ts +38 -0
  410. package/src/tools/panes.ts +112 -0
  411. package/src/tools/policy.ts +10 -1
  412. package/src/tools/presentation.ts +1 -0
  413. package/dist/chunk-D73KXYPF.js +0 -37
  414. package/dist/chunk-MLOK6ZOS.js +0 -2888
  415. package/dist/chunk-YKOFT37S.js +0 -279
  416. package/dist/doctor-TWBWFK5V.js +0 -165
@@ -21,6 +21,7 @@ import {
21
21
  import { isExecutionRole } from "./execution-role.js";
22
22
  import { COMPETE_STANCES, type CompeteStance } from "./gate-role-prompts.js";
23
23
  import { type DispatchIntent, isDispatchIntent } from "./intent.js";
24
+ import { classifyDispatchIntentCompatibility, dispatchIntentRefusals } from "./intent-compatibility.js";
24
25
  import { isRoutingIntent, type RoutingIntent } from "./routing-intent.js";
25
26
  import type {
26
27
  DispatchRequestOrigin,
@@ -478,14 +479,21 @@ export function validateJobSpec(spec: unknown): Validated {
478
479
  errors.push("writeRoots must be a non-empty array of non-empty strings");
479
480
  }
480
481
  }
481
- if ("intent" in spec && spec.intent !== undefined && !isDispatchIntent(spec.intent)) {
482
- errors.push("intent must be a normalized dispatch intent");
483
- }
484
- if (isDispatchIntent(spec.intent) && spec.intent.writeRoots.length > 0 && Array.isArray(spec.writeRoots)) {
485
- const jobCwd = typeof spec.cwd === "string" && spec.cwd.length > 0 ? spec.cwd : process.cwd();
486
- const legacy = [...new Set(spec.writeRoots.map((root) => resolvePathBoundary(jobCwd, String(root))))].sort();
487
- const declared = [...new Set(spec.intent.writeRoots.map((root) => resolvePathBoundary(jobCwd, root)))].sort();
488
- if (JSON.stringify(legacy) !== JSON.stringify(declared)) errors.push("intent_write_roots_contradiction");
482
+ // One owner for the typed-intent migration rules (#163). Every dispatch
483
+ // producer reaches a worker through this validator, so classifying here is
484
+ // what makes the compatibility table true of the fleet, CLI, ACP, and
485
+ // extension paths rather than only of the model-facing tool.
486
+ if ("intent" in spec) {
487
+ for (const refusal of dispatchIntentRefusals(
488
+ classifyDispatchIntentCompatibility({
489
+ intent: spec.intent,
490
+ ...(spec.writeRoots !== undefined ? { writeRoots: spec.writeRoots } : {}),
491
+ ...(spec.autonomy !== undefined ? { autonomy: spec.autonomy } : {}),
492
+ ...(typeof spec.cwd === "string" && spec.cwd.length > 0 ? { cwd: spec.cwd } : {}),
493
+ }),
494
+ )) {
495
+ errors.push(refusal.message);
496
+ }
489
497
  }
490
498
 
491
499
  if ("requestOrigin" in spec && spec.requestOrigin !== undefined) {
@@ -696,6 +704,8 @@ function isValidProtectedArtifactRemap(value: unknown): value is ProtectedArtifa
696
704
 
697
705
  const VALID_GATE_ROLES = new Set(["builder", "reviewer", "candidate", "judge", "member", "synthesis"]);
698
706
  const VALID_GATE_VERDICTS = new Set(["pass", "fail", "revise"]);
707
+ const VALID_WORKTREE_BACKENDS = new Set(["herdr", "native"]);
708
+ const VALID_WORKTREE_FALLBACKS = new Set(["mux-unavailable", "mux-operation-failed"]);
699
709
  const VALID_PLAN_TOPOLOGIES = new Set([
700
710
  "parallel",
701
711
  "sequential",
@@ -724,6 +734,20 @@ function isValidGate(value: unknown): value is RunGateProvenance {
724
734
  if (value.verdict !== undefined && (typeof value.verdict !== "string" || !VALID_GATE_VERDICTS.has(value.verdict))) {
725
735
  return false;
726
736
  }
737
+ if (value.worktree !== undefined) {
738
+ if (!isPlainObject(value.worktree)) return false;
739
+ if (typeof value.worktree.backend !== "string" || !VALID_WORKTREE_BACKENDS.has(value.worktree.backend)) return false;
740
+ if (typeof value.worktree.path !== "string" || !path.isAbsolute(value.worktree.path)) return false;
741
+ if (typeof value.worktree.branch !== "string" || value.worktree.branch.length === 0) return false;
742
+ if (value.worktree.workspaceId !== undefined && typeof value.worktree.workspaceId !== "string") return false;
743
+ if (
744
+ value.worktree.fallback !== undefined &&
745
+ (typeof value.worktree.fallback !== "string" || !VALID_WORKTREE_FALLBACKS.has(value.worktree.fallback))
746
+ ) {
747
+ return false;
748
+ }
749
+ if (value.worktree.backend === "herdr" && typeof value.worktree.workspaceId !== "string") return false;
750
+ }
727
751
  return true;
728
752
  }
729
753
 
@@ -734,6 +758,7 @@ function cloneGate(gate: RunGateProvenance): RunGateProvenance {
734
758
  cycle: gate.cycle,
735
759
  ...(gate.subjects !== undefined ? { subjects: gate.subjects.map((subject) => ({ ...subject })) } : {}),
736
760
  ...(gate.verdict !== undefined ? { verdict: gate.verdict } : {}),
761
+ ...(gate.worktree !== undefined ? { worktree: { ...gate.worktree } } : {}),
737
762
  };
738
763
  }
739
764
 
@@ -3,6 +3,7 @@ import { assertComparableTrackedMetricSources } from "../run-compare.js";
3
3
  import type { EvalArtifactV4 } from "../schema/artifact.js";
4
4
  import {
5
5
  type EvalServingConfigurationV1,
6
+ evalServingConfigurationOf,
6
7
  renderEvalServingConfiguration,
7
8
  sameEvalServingConfiguration,
8
9
  } from "../schema/serving.js";
@@ -90,8 +91,8 @@ export function compareEvalArtifactsV4(
90
91
  ): EvalCompareV4Summary {
91
92
  const baselineTokens = baseline.summary.tokens;
92
93
  const candidateTokens = candidate.summary.tokens;
93
- const baselineServing = servingConfigurationOf(baseline);
94
- const candidateServing = servingConfigurationOf(candidate);
94
+ const baselineServing = evalServingConfigurationOf(baseline);
95
+ const candidateServing = evalServingConfigurationOf(candidate);
95
96
  const configDrift = !sameEvalServingConfiguration(baselineServing, candidateServing);
96
97
  if (configDrift && options.allowConfigDrift !== true) {
97
98
  throw new EvalServingConfigurationDriftError(baselineServing, candidateServing);
@@ -330,20 +331,6 @@ function metricComparison(
330
331
  };
331
332
  }
332
333
 
333
- function servingConfigurationOf(artifact: EvalArtifactV4): EvalServingConfigurationV1 {
334
- return (
335
- artifact.servingConfiguration ?? {
336
- targetId: artifact.matrix.target,
337
- runtimeId: null,
338
- modelId: artifact.matrix.model,
339
- serverBuild: null,
340
- total_slots: null,
341
- thinkingLevel: artifact.matrix.thinking,
342
- compiledPromptHash: null,
343
- }
344
- );
345
- }
346
-
347
334
  function normalizeMetricFilter(metric: string | undefined): string | undefined {
348
335
  if (metric === undefined) return undefined;
349
336
  const trimmed = metric.trim();
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Bounded newest-first listing of the eval reports this installation stored.
3
+ *
4
+ * The store has always been addressed by id: `eval report <evalId>` and
5
+ * `eval compare <a> <b>` both require the operator to already know which report
6
+ * they want. Nothing enumerated the directory, so a surface that wants to offer
7
+ * the choice had to invent the enumeration. This is that enumeration, and it is
8
+ * a store concern rather than a wire concern: it decides which files are in the
9
+ * window and hands back parsed artifacts, and says nothing about which of their
10
+ * fields may leave the host.
11
+ */
12
+
13
+ import { readdir } from "node:fs/promises";
14
+ import { loadEvalArtifactV4 } from "./artifacts/store.js";
15
+ import type { EvalArtifactV4 } from "./schema/artifact.js";
16
+ import { evalRoot } from "./store.js";
17
+
18
+ /**
19
+ * The exact shape `createEvalId` mints: an ISO stamp with its separators
20
+ * stripped, the first eight characters of the suite hash, and a random suffix.
21
+ */
22
+ const EVAL_ID_PATTERN = /^eval-(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(\d{3})Z-([0-9a-f]{8})-([0-9a-f]{12})$/u;
23
+
24
+ export interface EvalStoredReport {
25
+ readonly evalId: string;
26
+ /**
27
+ * The instant the run started, read back out of the id.
28
+ *
29
+ * Null unless the id is one this harness minted and its embedded suite-hash
30
+ * prefix agrees with the suite the artifact names. An artifact has no
31
+ * timestamp field of its own, so the id is the only record of when it ran,
32
+ * and a stamp read off an id that does not otherwise match its contents is
33
+ * not a fact worth reporting.
34
+ */
35
+ readonly startedAt: string | null;
36
+ readonly artifact: EvalArtifactV4;
37
+ }
38
+
39
+ export interface EvalStoreListing {
40
+ /** False when the installation has no eval store at all, which reads differently from an empty one. */
41
+ readonly available: boolean;
42
+ /** Reports on disk before the window bound. */
43
+ readonly stored: number;
44
+ readonly reports: readonly EvalStoredReport[];
45
+ /**
46
+ * Files inside the window the current parser refused.
47
+ *
48
+ * Counted rather than dropped silently. Routing accepts artifact v4 only, so
49
+ * a retired shape still on disk is a real thing in this store, and a listing
50
+ * that quietly skipped it would report a smaller store than the operator has.
51
+ */
52
+ readonly unreadable: number;
53
+ }
54
+
55
+ /** The stamp an id carries, without checking it against anything. */
56
+ function idStamp(evalId: string): { startedAt: string; suiteHashPrefix: string } | null {
57
+ const match = EVAL_ID_PATTERN.exec(evalId);
58
+ if (match === null) return null;
59
+ const [, year, month, day, hour, minute, second, millisecond, suiteHashPrefix] = match;
60
+ const startedAt = `${year}-${month}-${day}T${hour}:${minute}:${second}.${millisecond}Z`;
61
+ const parsed = new Date(startedAt);
62
+ if (Number.isNaN(parsed.getTime()) || parsed.toISOString() !== startedAt) return null;
63
+ return { startedAt, suiteHashPrefix: suiteHashPrefix as string };
64
+ }
65
+
66
+ /** Newest first. An id this harness did not mint sorts oldest rather than throwing. */
67
+ function byNewest(left: string, right: string): number {
68
+ const leftStamp = idStamp(left)?.startedAt ?? "";
69
+ const rightStamp = idStamp(right)?.startedAt ?? "";
70
+ if (leftStamp !== rightStamp) return leftStamp < rightStamp ? 1 : -1;
71
+ return left < right ? 1 : -1;
72
+ }
73
+
74
+ export async function listEvalReports(dataDir: string, limit: number): Promise<EvalStoreListing> {
75
+ let entries: string[];
76
+ try {
77
+ entries = await readdir(evalRoot(dataDir));
78
+ } catch (error) {
79
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") {
80
+ return { available: false, stored: 0, reports: [], unreadable: 0 };
81
+ }
82
+ throw error;
83
+ }
84
+ const ids = entries
85
+ .filter((entry) => entry.endsWith(".json"))
86
+ .map((entry) => entry.slice(0, -".json".length))
87
+ .sort(byNewest);
88
+ const reports: EvalStoredReport[] = [];
89
+ let unreadable = 0;
90
+ for (const evalId of ids.slice(0, limit)) {
91
+ let artifact: EvalArtifactV4;
92
+ try {
93
+ artifact = await loadEvalArtifactV4(dataDir, evalId);
94
+ } catch {
95
+ unreadable += 1;
96
+ continue;
97
+ }
98
+ // The id inside the file is authoritative. A file whose stem disagrees with
99
+ // it was renamed or copied in, and the two names it now answers to are not
100
+ // the same report.
101
+ if (artifact.evalId !== evalId) {
102
+ unreadable += 1;
103
+ continue;
104
+ }
105
+ const stamp = idStamp(evalId);
106
+ reports.push({
107
+ evalId,
108
+ startedAt: stamp !== null && artifact.suite.hash.startsWith(stamp.suiteHashPrefix) ? stamp.startedAt : null,
109
+ artifact,
110
+ });
111
+ }
112
+ return { available: true, stored: ids.length, reports, unreadable };
113
+ }
@@ -30,6 +30,37 @@ export function parseEvalServingConfigurationV1(value: unknown, source: string):
30
30
  };
31
31
  }
32
32
 
33
+ /**
34
+ * The serving facts an artifact was produced under.
35
+ *
36
+ * An artifact written before the observation existed has no record of its own,
37
+ * so the matrix it declared is the best available reading and the missing
38
+ * fields stay null rather than being invented. This lives beside
39
+ * `sameEvalServingConfiguration` because the two are one rule: what a
40
+ * comparison reads, and when it decides two readings agree. Anything asking
41
+ * whether two eval runs are comparable must go through both, or it is answering
42
+ * a different question from the one `eval compare` answers.
43
+ *
44
+ * The parameter is structural rather than `EvalArtifactV4` so this module stays
45
+ * free of an import cycle through `schema/artifact.ts`.
46
+ */
47
+ export function evalServingConfigurationOf(artifact: {
48
+ readonly servingConfiguration?: EvalServingConfigurationV1;
49
+ readonly matrix: { readonly target: string; readonly model: string | null; readonly thinking: string | null };
50
+ }): EvalServingConfigurationV1 {
51
+ return (
52
+ artifact.servingConfiguration ?? {
53
+ targetId: artifact.matrix.target,
54
+ runtimeId: null,
55
+ modelId: artifact.matrix.model,
56
+ serverBuild: null,
57
+ total_slots: null,
58
+ thinkingLevel: artifact.matrix.thinking,
59
+ compiledPromptHash: null,
60
+ }
61
+ );
62
+ }
63
+
33
64
  export function sameEvalServingConfiguration(
34
65
  left: EvalServingConfigurationV1,
35
66
  right: EvalServingConfigurationV1,
@@ -205,6 +205,11 @@ function parseOverview(value: unknown, source: string): EvidenceOverview {
205
205
  const totals = readTotals(value.totals, `${source}.totals`);
206
206
  const tags = readStringArray(value, source, "tags") as EvidenceOverview["tags"];
207
207
  const files = readStringArray(value, source, "files");
208
+ // Additive since the redaction pass landed, so a bundle written before it
209
+ // simply has no count. Reading it optionally is what keeps the declared
210
+ // field reachable: it was written to disk and then dropped on the way back.
211
+ const redactionCount =
212
+ typeof value.redactionCount === "number" && Number.isFinite(value.redactionCount) ? value.redactionCount : undefined;
208
213
  return {
209
214
  version: 1,
210
215
  evidenceId,
@@ -224,6 +229,7 @@ function parseOverview(value: unknown, source: string): EvidenceOverview {
224
229
  totals,
225
230
  tags,
226
231
  files,
232
+ ...(redactionCount === undefined ? {} : { redactionCount }),
227
233
  };
228
234
  }
229
235
 
@@ -91,7 +91,6 @@ export {
91
91
  runTaskMemoryPolicy,
92
92
  TASK_MEMORY_POLICY_DEFAULT_TIMEOUT_MS,
93
93
  TASK_MEMORY_POLICY_MAX_OPERATIONS,
94
- TASK_MEMORY_POLICY_MODEL_MAX_OUTPUT_TOKENS,
95
94
  type TaskMemoryEnvelope,
96
95
  type TaskMemoryModelClient,
97
96
  type TaskMemoryModelRequest,
@@ -17,15 +17,7 @@ export const TASK_MEMORY_POLICY_MAX_OPERATIONS = 8;
17
17
  * test pins the pair. Two numbers for one setting means any path that misses
18
18
  * the settings object silently gets the one nobody chose.
19
19
  */
20
- export const TASK_MEMORY_POLICY_DEFAULT_TIMEOUT_MS = 30_000;
21
- /**
22
- * The envelope itself needs a few hundred tokens. The rest is headroom for a
23
- * model that reasons despite thinking being requested off: measured preambles on
24
- * a 9B local route ran past 1,800 tokens before the first `<operations>` byte,
25
- * and a budget that runs out mid-thought yields an empty response, no bank
26
- * writes, and no way for the operator to tell that from a deliberate silence.
27
- */
28
- export const TASK_MEMORY_POLICY_MODEL_MAX_OUTPUT_TOKENS = 4_000;
20
+ export const TASK_MEMORY_POLICY_DEFAULT_TIMEOUT_MS = 60_000;
29
21
 
30
22
  export interface TaskMemoryTrajectoryStep {
31
23
  step: number;
@@ -142,6 +134,8 @@ export type TaskMemoryPolicyReason =
142
134
  | "no_consumer"
143
135
  /** A step was already in flight, so this boundary's triggers stayed pending. */
144
136
  | "step_in_flight"
137
+ /** Consecutive model deadlines degraded this session to the free rules tier. */
138
+ | "llm_timeout_backoff"
145
139
  /** Rules tier: the turn ended with no repeated failure worth reporting. */
146
140
  | "no_repeated_failure"
147
141
  /** Rules tier: compaction reactivation found no knowledge entries to restore. */
@@ -171,6 +165,8 @@ export interface TaskMemoryPolicyInput {
171
165
  trajectory: ReadonlyArray<TaskMemoryTrajectoryStep>;
172
166
  deterministicTrigger: boolean;
173
167
  maxTokens: number;
168
+ /** Capability-derived completion budget; defaults to the visible reminder budget. */
169
+ modelMaxTokens?: number;
174
170
  timeoutMs?: number;
175
171
  /** Phase one still applies; phase two is suppressed when another memory reminder already won this boundary. */
176
172
  suppressIntervention?: boolean;
@@ -297,7 +293,7 @@ export async function runTaskMemoryPolicy(
297
293
  const completion = client.complete({
298
294
  systemPrompt: MEMORY_INTERVENTION_SYSTEM_PROMPT,
299
295
  userPrompt,
300
- maxTokens: TASK_MEMORY_POLICY_MODEL_MAX_OUTPUT_TOKENS,
296
+ maxTokens: positiveInteger(input.modelMaxTokens, input.maxTokens),
301
297
  signal: controller.signal,
302
298
  });
303
299
  const timeout = new Promise<typeof timeoutMarker>((resolve) => {
@@ -226,6 +226,7 @@ const REASONS = new Set<TaskMemoryPolicyReason>([
226
226
  "no_client",
227
227
  "no_consumer",
228
228
  "step_in_flight",
229
+ "llm_timeout_backoff",
229
230
  "no_repeated_failure",
230
231
  "bank_empty",
231
232
  ]);
@@ -31,8 +31,10 @@ import type { MiddlewareEffect, MiddlewareHookInput } from "./types.js";
31
31
 
32
32
  export const MEMORY_INTERVENTION_REGISTRATION_ID = "observer.memory-intervention";
33
33
  export const MEMORY_INTERVENTION_DEFAULT_WINDOW_STEPS = 8;
34
- export const MEMORY_INTERVENTION_DEFAULT_MAX_TOKENS = 400;
34
+ export const MEMORY_INTERVENTION_DEFAULT_MAX_TOKENS = 2_000;
35
35
  export const MEMORY_INTERVENTION_DEFAULT_EVERY_N_TOOLS = 10;
36
+ /** Two full deadlines are enough evidence to stop spending this session's endpoint. */
37
+ export const MEMORY_INTERVENTION_TIMEOUT_BACKOFF_THRESHOLD = 2;
36
38
 
37
39
  export const MEMORY_INTERVENTION_ACTIVITY_LIMIT = 20;
38
40
 
@@ -76,6 +78,8 @@ export interface MemoryInterventionDeps {
76
78
  everyNTools?: number;
77
79
  /** Lazily resolves the explicitly configured background role. Null means rules-only. */
78
80
  getModelClient?: () => TaskMemoryModelClient | null;
81
+ /** Completion budget derived from the resolved background model capability. */
82
+ getModelMaxTokens?: (configuredMaxTokens: number) => number;
79
83
  /**
80
84
  * True when the background target's inference endpoint is already serving the
81
85
  * chat target's stream. A memory step then either queues behind the operator's
@@ -187,6 +191,7 @@ export function createMemoryInterventionRegistration(deps: MemoryInterventionDep
187
191
  let outstandingStep: Promise<void> = Promise.resolve();
188
192
  let rulesInjectedSincePromptedStep = false;
189
193
  let annotatedSinceTurnEnd = false;
194
+ let consecutiveLlmTimeouts = 0;
190
195
 
191
196
  return {
192
197
  id: MEMORY_INTERVENTION_REGISTRATION_ID,
@@ -388,27 +393,32 @@ export function createMemoryInterventionRegistration(deps: MemoryInterventionDep
388
393
  // produced and the policy vocabulary has no value for a step that never ran.
389
394
  let telemetryDecision: TaskMemoryTelemetryDecision | null = null;
390
395
  try {
391
- const client = deps.getModelClient?.() ?? null;
392
- if (client === null) {
393
- promptedResult = silent("no_client");
394
- } else if (deps.backgroundEndpointBusy?.() === true) {
395
- tier = "llm";
396
- promptedStepTier = tier;
397
- promptedResult = silent("endpoint_busy");
398
- telemetryDecision = "dropped";
396
+ if (consecutiveLlmTimeouts >= MEMORY_INTERVENTION_TIMEOUT_BACKOFF_THRESHOLD) {
397
+ promptedResult = silent("llm_timeout_backoff");
399
398
  } else {
400
- tier = "llm";
401
- promptedStepTier = tier;
402
- promptedResult = await runTaskMemoryPolicy(deps.bank, client, {
403
- task: input.task?.trim() || currentTask,
404
- trajectory: [...trajectory],
405
- deterministicTrigger: input.deterministicTrigger,
406
- maxTokens: live.maxTokens,
407
- ...(input.suppressIntervention === undefined ? {} : { suppressIntervention: input.suppressIntervention }),
408
- previousReminder: lastInjectedMessage,
409
- timeoutMs: live.timeoutMs,
410
- ...(deps.onEnvelope === undefined ? {} : { onEnvelope: deps.onEnvelope }),
411
- });
399
+ const client = deps.getModelClient?.() ?? null;
400
+ if (client === null) {
401
+ promptedResult = silent("no_client");
402
+ } else if (deps.backgroundEndpointBusy?.() === true) {
403
+ tier = "llm";
404
+ promptedStepTier = tier;
405
+ promptedResult = silent("endpoint_busy");
406
+ telemetryDecision = "dropped";
407
+ } else {
408
+ tier = "llm";
409
+ promptedStepTier = tier;
410
+ promptedResult = await runTaskMemoryPolicy(deps.bank, client, {
411
+ task: input.task?.trim() || currentTask,
412
+ trajectory: [...trajectory],
413
+ deterministicTrigger: input.deterministicTrigger,
414
+ maxTokens: live.maxTokens,
415
+ modelMaxTokens: positiveInteger(deps.getModelMaxTokens?.(live.maxTokens), live.maxTokens),
416
+ ...(input.suppressIntervention === undefined ? {} : { suppressIntervention: input.suppressIntervention }),
417
+ previousReminder: lastInjectedMessage,
418
+ timeoutMs: live.timeoutMs,
419
+ ...(deps.onEnvelope === undefined ? {} : { onEnvelope: deps.onEnvelope }),
420
+ });
421
+ }
412
422
  }
413
423
  } catch (error) {
414
424
  // runTaskMemoryPolicy resolves its own failures, so reaching here means
@@ -426,6 +436,8 @@ export function createMemoryInterventionRegistration(deps: MemoryInterventionDep
426
436
  error: error instanceof Error ? error.message : "resolving the background model client failed",
427
437
  });
428
438
  }
439
+ if (tier === "llm" && promptedResult.decision === "timeout") consecutiveLlmTimeouts += 1;
440
+ else if (tier === "llm" && telemetryDecision !== "dropped") consecutiveLlmTimeouts = 0;
429
441
  lastDecision = promptedResult.decision;
430
442
  if (promptedResult.usage !== null) {
431
443
  try {