@iowarp/clio-coder 0.3.3 → 0.3.6

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 (370) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/CONTRIBUTING.md +7 -7
  3. package/README.md +3 -3
  4. package/dist/{acp-P2AQILE2.js → acp-2BEHC4DL.js} +9 -8
  5. package/dist/{agents-72W3BI7I.js → agents-LNNFTM53.js} +29 -24
  6. package/dist/assets/codewiki.json +1 -1
  7. package/dist/{auth-5TWEIYDN.js → auth-KXXFI2VS.js} +14 -10
  8. package/dist/{chunk-GGXXDWE4.js → chunk-22NAGB7X.js} +2 -2
  9. package/dist/{chunk-YCWGATWI.js → chunk-24I7BN55.js} +2 -2
  10. package/dist/{chunk-EKMEHE4H.js → chunk-33YXPOE3.js} +2 -3
  11. package/dist/chunk-3BPUFZDL.js +37 -0
  12. package/dist/chunk-43AOLP7E.js +375 -0
  13. package/dist/{chunk-ZDOOVTXZ.js → chunk-4OC57DA6.js} +27 -4
  14. package/dist/{chunk-6SGHMWE3.js → chunk-5JGRAMKL.js} +5 -5
  15. package/dist/{chunk-V6RTAOC2.js → chunk-6US73PDB.js} +572 -51
  16. package/dist/{chunk-5UFT4SUX.js → chunk-6XXKFVSN.js} +3 -3
  17. package/dist/{chunk-A3CYT5EX.js → chunk-AD2SYQYC.js} +55 -2
  18. package/dist/chunk-AOCYTWAV.js +449 -0
  19. package/dist/chunk-CFGTUFWB.js +67 -0
  20. package/dist/chunk-CJUB2JJ2.js +1478 -0
  21. package/dist/{chunk-FNTMWMX5.js → chunk-CKXWIANG.js} +14 -12
  22. package/dist/{chunk-PIWWS5BL.js → chunk-CYQKWTG3.js} +63 -78
  23. package/dist/{chunk-LZSJBIVT.js → chunk-DJVECN66.js} +271 -762
  24. package/dist/{chunk-CBCAPZAA.js → chunk-E25LMLRW.js} +2 -2
  25. package/dist/{chunk-ZWMF7253.js → chunk-E2ER4LJF.js} +304 -9
  26. package/dist/{chunk-STBPMHSX.js → chunk-EKY57CSP.js} +51 -84
  27. package/dist/{chunk-DUYJ5IO6.js → chunk-EYPA3EGJ.js} +12 -4
  28. package/dist/{chunk-M6SHUN7Q.js → chunk-FO5ZOVUY.js} +2 -2
  29. package/dist/chunk-FYYLNIL5.js +313 -0
  30. package/dist/{chunk-OQ33BKR3.js → chunk-G7MUEIGA.js} +3 -60
  31. package/dist/chunk-GEYXPTRF.js +613 -0
  32. package/dist/chunk-GOXNB3AO.js +261 -0
  33. package/dist/{chunk-G4BMMOKF.js → chunk-HVDIIIQW.js} +2 -2
  34. package/dist/chunk-HWUFFB6L.js +83 -0
  35. package/dist/{chunk-4XUGQOHA.js → chunk-K7T3E2SR.js} +15 -8
  36. package/dist/chunk-K7VKOLQQ.js +15 -0
  37. package/dist/{chunk-UFIIWP2H.js → chunk-KHSFENX2.js} +8 -8
  38. package/dist/{chunk-BMEMKKIT.js → chunk-KOHPCX4K.js} +2 -2
  39. package/dist/chunk-LCGCVYZ4.js +57 -0
  40. package/dist/chunk-LL4KHSZI.js +22 -0
  41. package/dist/{chunk-PAJK6MAQ.js → chunk-LYF7OHWH.js} +42 -15
  42. package/dist/{chunk-POHLU5DW.js → chunk-M6L6IDJG.js} +3 -3
  43. package/dist/{chunk-5UUP6MWO.js → chunk-MV3K5QF2.js} +5 -436
  44. package/dist/{chunk-X4RCMKVQ.js → chunk-NDINPTJ4.js} +2 -2
  45. package/dist/{chunk-TZK7PACC.js → chunk-NILBFAPG.js} +14 -8
  46. package/dist/chunk-ODFEOB4F.js +1082 -0
  47. package/dist/{chunk-AGYYIBLL.js → chunk-OH3TOQTB.js} +6 -2
  48. package/dist/chunk-OZNBF4L3.js +23 -0
  49. package/dist/{chunk-DSELYM6W.js → chunk-PBTHKCPN.js} +30 -10
  50. package/dist/{verify-375KUB3Y.js → chunk-PCZJO5TI.js} +127 -42
  51. package/dist/{chunk-ED4KHGC3.js → chunk-PPAMZ32Z.js} +9 -2
  52. package/dist/{chunk-SRDMMSEP.js → chunk-QM3F2GKX.js} +1063 -1645
  53. package/dist/{chunk-X6IAEBZR.js → chunk-QNQHSOLF.js} +7 -7
  54. package/dist/{chunk-OC7FIQPC.js → chunk-R46L2BIR.js} +10 -7
  55. package/dist/{chunk-2TLUCQVG.js → chunk-RD5U66HV.js} +3 -3
  56. package/dist/{chunk-6N5PTWMY.js → chunk-RY3LY4J5.js} +50 -13
  57. package/dist/{chunk-OKGUZO2U.js → chunk-SPULKLCF.js} +4 -3
  58. package/dist/{chunk-OOJYHWRB.js → chunk-TSHXZTOQ.js} +6 -5
  59. package/dist/chunk-TZSKNMZG.js +434 -0
  60. package/dist/{chunk-7MNJORFF.js → chunk-UL3WSD3F.js} +6 -1
  61. package/dist/{chunk-VJWL6YS5.js → chunk-UUVG37B4.js} +2 -2
  62. package/dist/{chunk-COU2UHX6.js → chunk-VEZEGCGW.js} +170 -2
  63. package/dist/chunk-W6GROXXM.js +69 -0
  64. package/dist/{chunk-OAO4GE4M.js → chunk-WHGPSPT5.js} +2 -2
  65. package/dist/chunk-WHJYKASB.js +677 -0
  66. package/dist/{chunk-ORBHGJC5.js → chunk-WR67VIZY.js} +3 -3
  67. package/dist/{chunk-YHZX5GEU.js → chunk-XAKHZX5N.js} +2 -2
  68. package/dist/{chunk-TZTZS7QK.js → chunk-XE2VEJHX.js} +5 -3
  69. package/dist/{chunk-LM5TQCJZ.js → chunk-XF5N4U5A.js} +8 -7
  70. package/dist/{chunk-LWLEKMDQ.js → chunk-XXQNGV4M.js} +1073 -552
  71. package/dist/{chunk-KZWTDYJF.js → chunk-XYDYPRZI.js} +7 -7
  72. package/dist/chunk-ZGVHUX3M.js +66 -0
  73. package/dist/{chunk-LW6DSM3M.js → chunk-ZRGEBJ4T.js} +1192 -1119
  74. package/dist/{chunk-2DJ2KNFG.js → chunk-ZXF4XRKW.js} +202 -40
  75. package/dist/chunk-ZZMN5OM4.js +122 -0
  76. package/dist/cli/index.js +34 -30
  77. package/dist/{clio-JOU4FXVA.js → clio-M2KGYUFZ.js} +7 -6
  78. package/dist/{code-nav-7AX6FYE6.js → code-nav-GQNL7XA6.js} +8 -6
  79. package/dist/codewiki/build-worker.js +4 -4
  80. package/dist/{components-KELWS457.js → components-5TTYYX6G.js} +3 -3
  81. package/dist/{config-XCDVKR23.js → config-XUUYQIWO.js} +47 -35
  82. package/dist/{configure-4GAP54ZW.js → configure-IHJ7YOMV.js} +18 -15
  83. package/dist/{context-77FM5DV5.js → context-74JLXAWD.js} +18 -10
  84. package/dist/{context-4UOGGLQ5.js → context-75MIWW3U.js} +41 -29
  85. package/dist/{context-5VKGUVJJ.js → context-ZQ7SIFJV.js} +85 -9
  86. package/dist/{context-clear-XXJRLCJJ.js → context-clear-GYKWNUML.js} +41 -29
  87. package/dist/{context-index-BZ4UYMTC.js → context-index-SSR5ECNE.js} +3 -3
  88. package/dist/context-working-set-UX5KEP4J.js +1553 -0
  89. package/dist/{dispatch-runner-QPRDDBDX.js → dispatch-runner-GIJBHNFL.js} +47 -32
  90. package/dist/{docs-2C2LTVT2.js → docs-6FZSCG5B.js} +3 -3
  91. package/dist/{doctor-HR46URBJ.js → doctor-SVJ5BZCW.js} +12 -12
  92. package/dist/{eval-XSSNATB4.js → eval-CG6LLBLD.js} +54 -238
  93. package/dist/{evidence-6HG2PY2B.js → evidence-ZYFIEN42.js} +57 -28
  94. package/dist/{evolve-K7YU3NCY.js → evolve-QGEXEMDW.js} +36 -25
  95. package/dist/{extensions-QVDOHDGJ.js → extensions-ADGNCJJD.js} +3 -3
  96. package/dist/{fleet-VY3HHKN6.js → fleet-S5R4ZOQY.js} +73 -44
  97. package/dist/{fleet-preflight-DDN536IT.js → fleet-preflight-BHSNPBMH.js} +3 -3
  98. package/dist/{init-JYGXI3FK.js → init-5DRU55YR.js} +49 -37
  99. package/dist/memory-7YKKR6UC.js +467 -0
  100. package/dist/{models-I5QWSEOM.js → models-ZPOLRU2C.js} +24 -21
  101. package/dist/{monitor-GE4ID3IA.js → monitor-US5F5YGZ.js} +73 -46
  102. package/dist/{orchestrator-EM5MC3HM.js → orchestrator-E2AL4T5N.js} +1624 -1007
  103. package/dist/{paths-UXLN5YYZ.js → paths-E7KYAQWE.js} +3 -3
  104. package/dist/{reset-L2FQEE3E.js → reset-KZ652EK6.js} +6 -5
  105. package/dist/{run-ZU3QMZPZ.js → run-SRNBKDWD.js} +76 -54
  106. package/dist/{share-S5BZQC5I.js → share-CGZE33UP.js} +7 -6
  107. package/dist/{skills-X5VXCRNQ.js → skills-S2X4DLY5.js} +4 -4
  108. package/dist/{skills-eval-WKIHWTHR.js → skills-eval-W2GGIC4R.js} +40 -29
  109. package/dist/{targets-SNCPI2NR.js → targets-54SWINWB.js} +28 -23
  110. package/dist/{terminal-lease-BNAHVHBS.js → terminal-lease-SAIF2OGY.js} +6 -4
  111. package/dist/{uninstall-FZCQCDKC.js → uninstall-BVLWXKBT.js} +3 -3
  112. package/dist/{upgrade-JQHHPQ4K.js → upgrade-JKAR27XC.js} +20 -19
  113. package/dist/{usage-OR4O5SMZ.js → usage-MSAWCLX4.js} +79 -36
  114. package/dist/verifiers-NCBTHHN2.js +1220 -0
  115. package/dist/verify-X5HDROLA.js +25 -0
  116. package/dist/{wiki-generate-UEXP2ARI.js → wiki-generate-GUSOQ6ZP.js} +50 -37
  117. package/dist/worker/entry.js +90 -70
  118. package/dist/{workspace-G4ZWUIPR.js → workspace-ZJ6BFM3Q.js} +4 -4
  119. package/docs/README.md +8 -7
  120. package/docs/acp.md +1 -1
  121. package/docs/alcf-provider.md +1 -1
  122. package/docs/architecture.md +2 -2
  123. package/docs/artifact-placement.md +1 -2
  124. package/docs/artifact-versions.md +1 -1
  125. package/docs/built-in-agents.md +1 -1
  126. package/docs/capacity-and-scheduling.md +1 -1
  127. package/docs/commands-and-modes.md +60 -26
  128. package/docs/config-knobs-audit.md +1 -2
  129. package/docs/configuration-and-targets.md +26 -1
  130. package/docs/context-engine.md +67 -13
  131. package/docs/context-working-set.md +194 -0
  132. package/docs/development-pipeline.md +1 -1
  133. package/docs/documentation-coverage.md +6 -6
  134. package/docs/documentation-guide.md +7 -6
  135. package/docs/environment-variables.md +2 -1
  136. package/docs/eval-runner.md +1 -1
  137. package/docs/evals-internal.md +4 -32
  138. package/docs/evidence-and-memory.md +139 -7
  139. package/docs/evolution.md +1 -1
  140. package/docs/exit-codes-and-output.md +1 -1
  141. package/docs/extensions-and-sharing.md +2 -2
  142. package/docs/fleet-dispatch.md +49 -8
  143. package/docs/glossary.md +21 -1
  144. package/docs/installation-and-lifecycle.md +2 -2
  145. package/docs/middleware-and-components.md +19 -2
  146. package/docs/model-catalog.md +7 -9
  147. package/docs/observability.md +4 -4
  148. package/docs/proactive-memory.md +26 -16
  149. package/docs/prompt-envelope-and-tools.md +7 -5
  150. package/docs/provider-adapter-cookbook.md +1 -1
  151. package/docs/release-cut-checklist.md +43 -40
  152. package/docs/safety-model.md +49 -8
  153. package/docs/scientific-validation.md +21 -3
  154. package/docs/session-lifecycle.md +3 -3
  155. package/docs/skills-marketplace.md +1 -1
  156. package/docs/tool-usage.md +79 -12
  157. package/docs/trace-store.md +1 -1
  158. package/docs/troubleshooting.md +1 -1
  159. package/docs/tui-design.md +38 -4
  160. package/docs/worker-dispatch-mechanics.md +11 -1
  161. package/package.json +13 -13
  162. package/skills/meta/clio-test/SKILL.md +20 -17
  163. package/skills/meta/clio-test/evals.md +3 -3
  164. package/skills/meta/clio-test/references/harness.md +35 -6
  165. package/skills/meta/clio-test/references/test-map.md +20 -10
  166. package/skills/registry.yaml +2 -2
  167. package/skills/skill-marketplace.json +1 -1
  168. package/src/cli/agents.ts +2 -3
  169. package/src/cli/argv.ts +14 -1
  170. package/src/cli/context-working-set.ts +513 -0
  171. package/src/cli/context.ts +8 -0
  172. package/src/cli/evidence.ts +20 -2
  173. package/src/cli/fleet.ts +15 -0
  174. package/src/cli/index.ts +5 -1
  175. package/src/cli/memory.ts +272 -10
  176. package/src/cli/modes/json-stream.ts +2 -2
  177. package/src/cli/modes/print.ts +12 -1
  178. package/src/cli/run.ts +22 -2
  179. package/src/cli/targets.ts +12 -3
  180. package/src/cli/usage.ts +55 -7
  181. package/src/cli/verifiers.ts +325 -0
  182. package/src/core/bash-exec.ts +39 -14
  183. package/src/core/bus-events.ts +22 -4
  184. package/src/core/config.ts +54 -0
  185. package/src/core/defaults.ts +50 -3
  186. package/src/core/response-model-id.ts +134 -0
  187. package/src/core/toml.ts +62 -0
  188. package/src/core/verification-scripts.ts +6 -0
  189. package/src/core/workspace-files.ts +0 -1
  190. package/src/domains/agents/builtins/architect.md +1 -1
  191. package/src/domains/agents/builtins/verifier.md +3 -0
  192. package/src/domains/agents/catalog.ts +5 -4
  193. package/src/domains/agents/recipe.ts +54 -14
  194. package/src/domains/agents/result-contract.ts +7 -4
  195. package/src/domains/config/classify.ts +1 -0
  196. package/src/domains/context/bootstrap.ts +36 -27
  197. package/src/domains/context/project-metadata.ts +19 -63
  198. package/src/domains/context/prompt-context.ts +8 -0
  199. package/src/domains/context/working-set/contract.ts +161 -0
  200. package/src/domains/context/working-set/defaults.ts +28 -0
  201. package/src/domains/context/working-set/engine.ts +203 -0
  202. package/src/domains/context/working-set/fold.ts +62 -0
  203. package/src/domains/context/working-set/horizon.ts +38 -0
  204. package/src/domains/context/working-set/marker.ts +103 -0
  205. package/src/domains/context/working-set/path-index.ts +436 -0
  206. package/src/domains/context/working-set/payload.ts +152 -0
  207. package/src/domains/context/working-set/policies/age-horizon.ts +55 -0
  208. package/src/domains/context/working-set/policies/index.ts +20 -0
  209. package/src/domains/context/working-set/policies/structural.ts +160 -0
  210. package/src/domains/context/working-set/project.ts +132 -0
  211. package/src/domains/context/working-set/protect.ts +109 -0
  212. package/src/domains/context/working-set/recall.ts +177 -0
  213. package/src/domains/context/working-set/replay/controls.ts +112 -0
  214. package/src/domains/context/working-set/replay/load-clio.ts +199 -0
  215. package/src/domains/context/working-set/replay/metrics.ts +185 -0
  216. package/src/domains/context/working-set/replay/reference-graph.ts +79 -0
  217. package/src/domains/context/working-set/replay/report.ts +139 -0
  218. package/src/domains/context/working-set/replay/runner.ts +325 -0
  219. package/src/domains/context/working-set/replay/synthetic.ts +422 -0
  220. package/src/domains/context/working-set/replay/trace.ts +21 -0
  221. package/src/domains/context/working-set/visible.ts +54 -0
  222. package/src/domains/dispatch/budget-envelope.ts +396 -0
  223. package/src/domains/dispatch/contract.ts +2 -0
  224. package/src/domains/dispatch/extension.ts +81 -27
  225. package/src/domains/dispatch/orphan-recovery.ts +1 -0
  226. package/src/domains/dispatch/receipt-integrity.ts +4 -0
  227. package/src/domains/dispatch/state.ts +1 -0
  228. package/src/domains/dispatch/types.ts +10 -3
  229. package/src/domains/dispatch/validation.ts +14 -0
  230. package/src/domains/dispatch/worker-spawn.ts +14 -3
  231. package/src/domains/eval/metrics/evidence.ts +0 -116
  232. package/src/domains/eval/metrics/invariants.ts +1 -1
  233. package/src/domains/eval/runners/clio-run.ts +1 -10
  234. package/src/domains/eval/runners/external-command.ts +2 -29
  235. package/src/domains/eval/schema/suite.ts +0 -7
  236. package/src/domains/eval/suites/run.ts +1 -7
  237. package/src/domains/evidence/build.ts +112 -45
  238. package/src/domains/evidence/eval.ts +24 -7
  239. package/src/domains/evidence/index.ts +53 -0
  240. package/src/domains/evidence/ordering.ts +12 -0
  241. package/src/domains/evidence/run-trust.ts +221 -0
  242. package/src/domains/evidence/store.ts +46 -6
  243. package/src/domains/evidence/trust-status.ts +854 -0
  244. package/src/domains/evidence/types.ts +26 -0
  245. package/src/domains/memory/index.ts +22 -0
  246. package/src/domains/memory/operations.ts +58 -1
  247. package/src/domains/memory/promotion.ts +281 -0
  248. package/src/domains/memory/prompt-section.ts +25 -5
  249. package/src/domains/memory/proposal.ts +51 -7
  250. package/src/domains/memory/task-bank.ts +3 -2
  251. package/src/domains/memory/task-memory-handoff.ts +181 -24
  252. package/src/domains/memory/task-memory-policy.ts +3 -1
  253. package/src/domains/memory/types.ts +37 -0
  254. package/src/domains/memory/validate.ts +178 -0
  255. package/src/domains/middleware/memory-intervention.ts +38 -25
  256. package/src/domains/middleware/runtime.ts +6 -0
  257. package/src/domains/middleware/skills-reminder.ts +19 -4
  258. package/src/domains/middleware/stalled-turn.ts +208 -5
  259. package/src/domains/middleware/types.ts +10 -0
  260. package/src/domains/observability/contract.ts +6 -1
  261. package/src/domains/observability/cost.ts +20 -4
  262. package/src/domains/observability/extension.ts +2 -2
  263. package/src/domains/providers/index.ts +3 -0
  264. package/src/domains/providers/model-discovery.ts +9 -0
  265. package/src/domains/providers/runtime-resolution.ts +38 -1
  266. package/src/domains/providers/runtimes/common/probe-helpers.ts +97 -16
  267. package/src/domains/providers/types/context-window-slots.ts +18 -0
  268. package/src/domains/providers/types/runtime-descriptor.ts +3 -1
  269. package/src/domains/safety/autonomy.ts +1 -1
  270. package/src/domains/safety/call-target.ts +211 -14
  271. package/src/domains/safety/decision-presentation.ts +268 -0
  272. package/src/domains/safety/default-path-policy.ts +8 -0
  273. package/src/domains/safety/finish-contract.ts +4 -3
  274. package/src/domains/safety/policy-engine.ts +48 -6
  275. package/src/domains/safety/redaction.ts +73 -0
  276. package/src/domains/session/compaction/compact.ts +23 -1
  277. package/src/domains/session/compaction/cut-point.ts +2 -0
  278. package/src/domains/session/compaction/tokens.ts +16 -1
  279. package/src/domains/session/context-ledger.ts +12 -1
  280. package/src/domains/session/decision-board.ts +4 -0
  281. package/src/domains/session/entries.ts +110 -1
  282. package/src/domains/session/history.ts +68 -19
  283. package/src/domains/session/manager.ts +9 -2
  284. package/src/domains/session/migrations/index.ts +22 -3
  285. package/src/domains/session/usage.ts +24 -7
  286. package/src/engine/acp/event-mapper.ts +7 -0
  287. package/src/engine/acp/server.ts +32 -2
  288. package/src/engine/agent.ts +18 -1
  289. package/src/engine/apis/lmstudio.ts +25 -4
  290. package/src/engine/apis/openai-completions.ts +147 -22
  291. package/src/engine/claude/sdk-runtime.ts +8 -2
  292. package/src/engine/claude/tool-safety.ts +13 -0
  293. package/src/engine/loop-guard.ts +27 -3
  294. package/src/engine/session.ts +9 -3
  295. package/src/engine/worker-events.ts +4 -3
  296. package/src/engine/worker-runtime.ts +59 -54
  297. package/src/entry/orchestrator.ts +34 -5
  298. package/src/interactive/chat-loop-messages.ts +40 -6
  299. package/src/interactive/chat-loop.ts +13 -0
  300. package/src/interactive/chat-panel.ts +17 -1
  301. package/src/interactive/chat-renderer.ts +49 -24
  302. package/src/interactive/clio-editor.ts +44 -7
  303. package/src/interactive/context-meter.ts +10 -0
  304. package/src/interactive/context-overlay.ts +120 -7
  305. package/src/interactive/context-recall-command.ts +110 -0
  306. package/src/interactive/cost-overlay.ts +39 -8
  307. package/src/interactive/dispatch-board.ts +212 -35
  308. package/src/interactive/footer/widgets.ts +13 -0
  309. package/src/interactive/interactive-application.ts +6 -1
  310. package/src/interactive/interactive-input-runtime.ts +11 -1
  311. package/src/interactive/interactive-presentation.ts +11 -1
  312. package/src/interactive/interactive-slash-runtime.ts +37 -1
  313. package/src/interactive/memory-overlay.ts +89 -4
  314. package/src/interactive/model-session-replay.ts +21 -0
  315. package/src/interactive/overlay-ask-user-lifecycle.ts +1 -1
  316. package/src/interactive/overlay-frame.ts +5 -2
  317. package/src/interactive/overlay-general-openers.ts +46 -1
  318. package/src/interactive/overlay-key-routing.ts +41 -1
  319. package/src/interactive/overlay-lifecycle.ts +11 -4
  320. package/src/interactive/overlay-permission-lifecycle.ts +23 -8
  321. package/src/interactive/overlay-session-lifecycle.ts +8 -4
  322. package/src/interactive/overlay-transitions.ts +11 -0
  323. package/src/interactive/overlays/ask-user.ts +74 -30
  324. package/src/interactive/overlays/decisions.ts +3 -1
  325. package/src/interactive/permission-hint.ts +35 -0
  326. package/src/interactive/permission-overlay.ts +95 -45
  327. package/src/interactive/renderers/tool-execution.ts +37 -51
  328. package/src/interactive/session-last-turn.ts +8 -1
  329. package/src/interactive/session-transcript.ts +2 -2
  330. package/src/interactive/session-usage-reseed.ts +36 -10
  331. package/src/interactive/slash-commands.ts +31 -4
  332. package/src/interactive/status/summary.ts +5 -0
  333. package/src/interactive/status/types.ts +5 -0
  334. package/src/interactive/terminal-lease.ts +1 -0
  335. package/src/interactive/turn-context.ts +333 -110
  336. package/src/interactive/turn-middleware.ts +7 -6
  337. package/src/interactive/turn-runtime.ts +37 -8
  338. package/src/interactive/turn-state.ts +3 -0
  339. package/src/interactive/worker-progress.ts +440 -0
  340. package/src/interactive/worker-stream.ts +51 -110
  341. package/src/tools/agent-tools.ts +39 -7
  342. package/src/tools/ask-user.ts +21 -1
  343. package/src/tools/bash.ts +144 -82
  344. package/src/tools/builtin-tool-catalog.ts +11 -5
  345. package/src/tools/context/index.ts +107 -5
  346. package/src/tools/context/surface.ts +3 -2
  347. package/src/tools/core-bootstrap.ts +21 -0
  348. package/src/tools/dispatch-arguments.ts +8 -0
  349. package/src/tools/dispatch-event-text.ts +19 -0
  350. package/src/tools/dispatch-runner.ts +9 -7
  351. package/src/tools/dispatch.ts +24 -1
  352. package/src/tools/monitor.ts +43 -20
  353. package/src/tools/registry.ts +72 -10
  354. package/src/tools/result-disposition.ts +706 -0
  355. package/src/tools/result-shaping.ts +321 -20
  356. package/src/tools/safe-exec.ts +2 -0
  357. package/src/tools/verify/authoring.ts +1120 -0
  358. package/src/tools/verify/catalog.ts +346 -0
  359. package/src/tools/verify/index.ts +13 -3
  360. package/src/tools/verify/scripts.ts +135 -37
  361. package/src/tools/verify/surface.ts +9 -5
  362. package/src/tools/worker-evidence.ts +54 -12
  363. package/src/worker/spec-contract.ts +43 -3
  364. package/dist/chunk-J7CWMCQD.js +0 -255
  365. package/dist/chunk-T6YILFSB.js +0 -80
  366. package/dist/chunk-VAKQQHWR.js +0 -434
  367. package/dist/chunk-VPAYEGVX.js +0 -184
  368. package/dist/chunk-XBXAASKX.js +0 -18
  369. package/dist/memory-WFZMGYHX.js +0 -236
  370. package/src/domains/eval/metrics/chaos-stream.ts +0 -93
@@ -2,9 +2,11 @@ import { homedir } from "node:os";
2
2
  import { relative } from "node:path";
3
3
  import { BusChannels } from "../core/bus-events.js";
4
4
  import type { SafeEventBus } from "../core/event-bus.js";
5
+ import type { WorkingSetView } from "../domains/context/working-set/contract.js";
6
+ import { formatContextWindowSlots } from "../domains/providers/index.js";
5
7
  import type { ContextLedger, ContextLedgerGroup } from "../domains/session/context-ledger.js";
6
8
  import { type OverlayHandle, Text, type TUI, visibleWidth } from "../engine/tui.js";
7
- import { contextCategorySwatch, renderContextMeterGrid } from "./context-meter.js";
9
+ import { contextCategorySwatch, renderContextMeterGrid, renderEvictedTokensLine } from "./context-meter.js";
8
10
  import { buildHint, showClioOverlayFrame } from "./overlay-frame.js";
9
11
  import { abbreviateModelId, type ClioToken, clioTheme, formatContextPercent } from "./theme/index.js";
10
12
 
@@ -81,7 +83,85 @@ function legendRow(group: ContextLedgerGroup, contentWidth: number): string {
81
83
  return `${swatch} ${theme.fg(labelToken, labelText)} ${theme.fg("muted", right)}`;
82
84
  }
83
85
 
84
- export function renderContextLedgerLines(ledger: ContextLedger, contentWidth: number): string[] {
86
+ function evictedTokens(view: WorkingSetView): number {
87
+ let total = 0;
88
+ for (const state of view.evicted.values()) total += state.tokensFreed;
89
+ return total;
90
+ }
91
+
92
+ function formatChurn(view: WorkingSetView): string {
93
+ if (view.itemsEvicted === 0) return "n/a";
94
+ return (view.recalls / view.itemsEvicted).toFixed(2);
95
+ }
96
+
97
+ /**
98
+ * Prose for one cache-disturbance reason. The wire values are stamped by
99
+ * `noteColdReason` in turn-context.ts and persisted on the assistant entry's
100
+ * `promptCache.expectedColdReasons`; the overlay reads them back, so an unknown
101
+ * reason renders as itself rather than disappearing.
102
+ */
103
+ function coldReasonLabel(reason: string): string {
104
+ switch (reason) {
105
+ case "working_set_evict":
106
+ return "working-set eviction";
107
+ case "compaction":
108
+ return "compaction";
109
+ case "dispatch":
110
+ return "dispatch traffic";
111
+ default:
112
+ return reason;
113
+ }
114
+ }
115
+
116
+ /** The operator's working-set configuration, as `/context` states it. */
117
+ export interface WorkingSetConfigView {
118
+ enabled: boolean;
119
+ policy: string;
120
+ }
121
+
122
+ /**
123
+ * The working-set section: what the projection has taken out of the window
124
+ * and how often the model has asked for it back. Churn is recalls over items
125
+ * evicted; a high number means the policy evicts what is still needed.
126
+ */
127
+ /**
128
+ * The policy line names what is configured, not what last ran. `lastPolicyId`
129
+ * is stamped by the first applied event, and eviction runs only when pressure
130
+ * crosses `compaction.threshold`, so a whole session at the shipped default
131
+ * read `policy none` (issue #190). With no configuration in hand (older
132
+ * callers) the last applied policy is still the best available claim.
133
+ */
134
+ function workingSetPolicyLabel(view: WorkingSetView, config: WorkingSetConfigView | null | undefined): string {
135
+ if (config === null || config === undefined) return `policy ${view.lastPolicyId ?? "none"}`;
136
+ if (!config.enabled) return "disabled";
137
+ const state = view.evictionEvents === 0 ? " · no events yet" : "";
138
+ const lastRan =
139
+ view.lastPolicyId !== null && view.lastPolicyId !== config.policy ? ` (last event by ${view.lastPolicyId})` : "";
140
+ return `policy ${config.policy}${lastRan}${state}`;
141
+ }
142
+
143
+ function renderWorkingSetLines(view: WorkingSetView, config: WorkingSetConfigView | null | undefined): string[] {
144
+ const theme = clioTheme();
145
+ const items = view.evicted.size;
146
+ const summary = [
147
+ `${items} evicted item${items === 1 ? "" : "s"}`,
148
+ `${formatTokens(evictedTokens(view))} tokens`,
149
+ `${view.evictionEvents} event${view.evictionEvents === 1 ? "" : "s"}`,
150
+ `${view.recalls} recall${view.recalls === 1 ? "" : "s"}`,
151
+ `churn ${formatChurn(view)}`,
152
+ ].join(" · ");
153
+ return [
154
+ `${theme.fg("muted", "working set")} ${theme.fg("dim", "·")} ${theme.fg("accent", workingSetPolicyLabel(view, config))}`,
155
+ theme.fg("dim", summary),
156
+ ];
157
+ }
158
+
159
+ export function renderContextLedgerLines(
160
+ ledger: ContextLedger,
161
+ contentWidth: number,
162
+ workingSet?: WorkingSetView | null,
163
+ workingSetConfig?: WorkingSetConfigView | null,
164
+ ): string[] {
85
165
  const theme = clioTheme();
86
166
  const lines: string[] = [];
87
167
 
@@ -98,7 +178,14 @@ export function renderContextLedgerLines(ledger: ContextLedger, contentWidth: nu
98
178
 
99
179
  if (ledger.contextWindow > 0) {
100
180
  const source = ledger.measured ? "measured" : "≈ estimated";
101
- const summary = `${formatTokens(ledger.usedTokens)} / ${formatTokens(ledger.contextWindow)} tokens (${formatContextPercent(ledger.percent)})`;
181
+ // `196,608 (786,432 / 4 slots)`: a llama.cpp window that is one slot's
182
+ // share of the server's KV budget names the split, because the bare
183
+ // number reads as the whole server and the meter is measured against
184
+ // the share (issue #187).
185
+ const window = ledger.contextWindowSlots
186
+ ? formatContextWindowSlots(ledger.contextWindow, ledger.contextWindowSlots)
187
+ : formatTokens(ledger.contextWindow);
188
+ const summary = `${formatTokens(ledger.usedTokens)} / ${window} tokens (${formatContextPercent(ledger.percent)})`;
102
189
  const provenance = contextWindowProvenanceLabel(ledger.contextWindowSource);
103
190
  const trailer = provenance ? `${provenance} window · ${source}` : source;
104
191
  lines.push(`${theme.fg("title", summary)} ${theme.fg("dim", "·")} ${theme.fg("muted", trailer)}`);
@@ -110,8 +197,13 @@ export function renderContextLedgerLines(ledger: ContextLedger, contentWidth: nu
110
197
  lines.push("");
111
198
 
112
199
  for (const group of ledger.meter) lines.push(legendRow(group, contentWidth));
200
+ if (workingSet && workingSet.evicted.size > 0) lines.push(renderEvictedTokensLine(evictedTokens(workingSet), theme));
113
201
 
114
202
  lines.push("");
203
+ if (workingSet) {
204
+ for (const line of renderWorkingSetLines(workingSet, workingSetConfig)) lines.push(line);
205
+ lines.push("");
206
+ }
115
207
  if (ledger.projectPreload && ledger.groups.some((group) => group.category === "project")) {
116
208
  lines.push(theme.fg("dim", `project preload: ${ledger.projectPreload}`));
117
209
  }
@@ -141,11 +233,21 @@ export function renderContextLedgerLines(ledger: ContextLedger, contentWidth: nu
141
233
  const uncached =
142
234
  cache.uncachedInputTokens !== null ? `uncached input ${formatTokens(cache.uncachedInputTokens)}` : null;
143
235
  const line = ["prompt cache:", shell, "·", backend, "·", read, ...(uncached ? ["·", uncached] : [])].join(" ");
236
+ // Reasons Clio recorded before the run: working-set eviction, summary
237
+ // compaction, and dispatch traffic all move the byte prefix a local
238
+ // single-slot backend caches, so a cold turn after one of them is the
239
+ // expected outcome rather than a provider surprise.
240
+ const coldReasons = cache.backendVerdict === "cold" ? (cache.expectedColdReasons ?? []) : [];
144
241
  // A reused shell with a cold backend means Clio kept the bytes stable
145
242
  // but the provider re-prefilled anyway; surface that disagreement
146
- // instead of hiding it.
147
- const misleading = cache.shellReused && cache.backendVerdict === "cold";
243
+ // instead of hiding it. An expected reason explains the same numbers, so
244
+ // it is reported on its own line and not as a warning.
245
+ const misleading = cache.shellReused && cache.backendVerdict === "cold" && coldReasons.length === 0;
148
246
  lines.push(theme.fg(misleading ? "warning" : "dim", line));
247
+ if (coldReasons.length > 0) {
248
+ const reasons = coldReasons.map(coldReasonLabel).join(", ");
249
+ lines.push(theme.fg("dim", `last cold turn: ${reasons} (expected)`));
250
+ }
149
251
  }
150
252
 
151
253
  if (ledger.lastCompaction) {
@@ -170,6 +272,10 @@ export interface OpenContextOverlayOptions {
170
272
  onEvent(handler: (event: { type: string }) => void): () => void;
171
273
  isStreaming(): boolean;
172
274
  };
275
+ /** Working-set fold at the live leaf; null or absent hides the section. */
276
+ getWorkingSet?: () => WorkingSetView | null;
277
+ /** The configured `context.workingSet` block, so the policy line states what is set. */
278
+ getWorkingSetConfig?: () => WorkingSetConfigView | null;
173
279
  }
174
280
 
175
281
  /**
@@ -183,7 +289,14 @@ export function openContextOverlay(
183
289
  getLedger: () => ContextLedger,
184
290
  options?: OpenContextOverlayOptions,
185
291
  ): OverlayHandle {
186
- const text = new Text(renderContextLedgerLines(getLedger(), DEFAULT_CONTENT_WIDTH).join("\n"), 0, 0);
292
+ const render = (): string =>
293
+ renderContextLedgerLines(
294
+ getLedger(),
295
+ DEFAULT_CONTENT_WIDTH,
296
+ options?.getWorkingSet?.() ?? null,
297
+ options?.getWorkingSetConfig?.() ?? null,
298
+ ).join("\n");
299
+ const text = new Text(render(), 0, 0);
187
300
  const handle = showClioOverlayFrame(tui, text, {
188
301
  anchor: "center",
189
302
  width: CONTEXT_OVERLAY_WIDTH,
@@ -192,7 +305,7 @@ export function openContextOverlay(
192
305
  });
193
306
 
194
307
  const refresh = (): void => {
195
- text.setText(renderContextLedgerLines(getLedger(), DEFAULT_CONTENT_WIDTH).join("\n"));
308
+ text.setText(render());
196
309
  text.invalidate();
197
310
  tui.requestRender();
198
311
  };
@@ -0,0 +1,110 @@
1
+ /**
2
+ * `/context recall <ref>`: the operator's half of working-set recall.
3
+ *
4
+ * The model recalls through `context(scope="recall", ref=...)`, which puts the
5
+ * body back in front of the model at the tail of the working set. This command
6
+ * answers a different question, asked by a person: what was in the result the
7
+ * marker replaced. So the body goes to the transcript and nowhere else. It is
8
+ * never submitted as a turn, never replayed, and never counted against the
9
+ * context window, which is why an operator can read a 40k-line build log back
10
+ * without paying for it.
11
+ *
12
+ * Everything else is identical to the tool path, deliberately: the same
13
+ * `resolveRecall` over the same fold at the same live leaf, the same
14
+ * `contextRecall` ledger entry (with `trigger: "operator"`), and the same
15
+ * `BusChannels.ContextRecalled` publication. A recall is a churn signal
16
+ * whoever asked for it, and a policy that keeps evicting something a human
17
+ * keeps reading back is a policy worth changing.
18
+ */
19
+
20
+ import type { ContextRecalledPayload } from "../core/bus-events.js";
21
+ import type { EvictedState } from "../domains/context/working-set/contract.js";
22
+ import { foldWorkingSet } from "../domains/context/working-set/fold.js";
23
+ import {
24
+ buildRecallFields,
25
+ recallErrorMessage,
26
+ recallParentTurnId,
27
+ resolveRecall,
28
+ } from "../domains/context/working-set/recall.js";
29
+ import type { SessionEntryInput } from "../domains/session/contract.js";
30
+ import type { SessionEntry } from "../domains/session/entries.js";
31
+
32
+ /** Ledger access the command needs, mirroring the context tool's `ContextSessionDeps`. */
33
+ export interface OperatorRecallDeps {
34
+ hasSession(): boolean;
35
+ readEntries(): ReadonlyArray<SessionEntry>;
36
+ /** The live append point (`/tree` pin or tree leaf); undefined lets the fold infer it. */
37
+ activeLeafTurnId(): string | undefined;
38
+ appendEntry(entry: SessionEntryInput): SessionEntry;
39
+ /** Publisher for `BusChannels.ContextRecalled`; the runtime supplies the bus. */
40
+ onRecalled?: (payload: ContextRecalledPayload) => void;
41
+ now?: () => number;
42
+ }
43
+
44
+ export type OperatorRecallOutcome =
45
+ | {
46
+ ok: true;
47
+ /** One-line summary for the notice bar. */
48
+ headline: string;
49
+ /** The original body, byte-exact, for the transcript. */
50
+ body: string;
51
+ }
52
+ | { ok: false; message: string };
53
+
54
+ function formatTokens(tokens: number): string {
55
+ return tokens.toLocaleString("en-US");
56
+ }
57
+
58
+ /**
59
+ * Ref, why it left, what it costs to read, and where the full artifact lives
60
+ * when the original result was offloaded. Nothing else: the body is on the next
61
+ * line and the operator is already looking at it.
62
+ */
63
+ function headlineFor(ref: string, tokens: number, state: EvictedState | undefined, offloadPath?: string): string {
64
+ const parts = [ref];
65
+ if (state !== undefined) {
66
+ parts.push(state.by === undefined ? `evicted: ${state.reason}` : `evicted: ${state.reason} by ${state.by}`);
67
+ }
68
+ parts.push(`${formatTokens(tokens)} tokens`);
69
+ if (offloadPath !== undefined) parts.push(`offload: ${offloadPath}`);
70
+ return `[/context recall] ${parts.join(" · ")}`;
71
+ }
72
+
73
+ export function runOperatorRecall(ref: string, deps: OperatorRecallDeps): OperatorRecallOutcome {
74
+ if (!deps.hasSession()) {
75
+ return { ok: false, message: "[/context recall] no active session; start one with /new or /resume first" };
76
+ }
77
+ const trimmed = ref.trim();
78
+ if (trimmed.length === 0) {
79
+ return { ok: false, message: "[/context recall] needs a ref: the turnId named in an [evicted ...] marker" };
80
+ }
81
+ const entries = deps.readEntries();
82
+ const leaf = deps.activeLeafTurnId();
83
+ const view = foldWorkingSet(entries, leaf);
84
+ const resolved = resolveRecall(entries, view, trimmed, leaf);
85
+ // A ref that resolves to nothing is usually a typo or a stale marker; the
86
+ // shared message ends with the refs the operator could have typed instead.
87
+ if (!resolved.ok)
88
+ return { ok: false, message: `[/context recall] ${recallErrorMessage(resolved.error, entries, view)}` };
89
+ const { result } = resolved;
90
+ const fields = buildRecallFields(result, { trigger: "operator" });
91
+ try {
92
+ deps.appendEntry({ ...fields, parentTurnId: recallParentTurnId(entries, leaf) });
93
+ } catch (err) {
94
+ return {
95
+ ok: false,
96
+ message: `[/context recall] recall of ${result.ref.entry} could not be recorded: ${err instanceof Error ? err.message : String(err)}`,
97
+ };
98
+ }
99
+ deps.onRecalled?.({
100
+ ref: result.ref.entry,
101
+ trigger: "operator",
102
+ tokensReadmitted: result.tokens,
103
+ at: deps.now?.() ?? Date.now(),
104
+ });
105
+ return {
106
+ ok: true,
107
+ headline: headlineFor(result.ref.entry, result.tokens, view.evicted.get(result.ref.entry), result.offloadPath),
108
+ body: result.body,
109
+ };
110
+ }
@@ -1,3 +1,8 @@
1
+ import {
2
+ addResponseModelIdObservationCounts,
3
+ type ResponseModelIdObservationCounts,
4
+ responseModelIdObservationCountsLabel,
5
+ } from "../core/response-model-id.js";
1
6
  import {
2
7
  aggregateCostAmounts,
3
8
  type CostAggregate,
@@ -16,7 +21,9 @@ export const COST_OVERLAY_WIDTH = DEFAULT_CONTENT_WIDTH + 4;
16
21
 
17
22
  export interface CostRow {
18
23
  providerId: string;
19
- modelId: string;
24
+ attributedModelId: string;
25
+ requestedModelIds: string[];
26
+ responseModelIdObservationCounts: ResponseModelIdObservationCounts;
20
27
  runs: number;
21
28
  tokens: number;
22
29
  input: number;
@@ -33,9 +40,17 @@ function formatTokens(n: number): string {
33
40
  }
34
41
 
35
42
  export function aggregateCostEntries(entries: ReadonlyArray<CostEntry>): CostRow[] {
36
- const grouped = new Map<string, { row: Omit<CostRow, "cost">; entries: CostEntry[] }>();
43
+ const grouped = new Map<
44
+ string,
45
+ {
46
+ row: Omit<CostRow, "cost" | "requestedModelIds" | "responseModelIdObservationCounts">;
47
+ requestedModelIds: Set<string>;
48
+ responseModelIdObservationCounts: ResponseModelIdObservationCounts;
49
+ entries: CostEntry[];
50
+ }
51
+ >();
37
52
  for (const entry of entries) {
38
- const key = `${entry.providerId}::${entry.modelId}`;
53
+ const key = `${entry.providerId}::${entry.attributedModelId}`;
39
54
  const existing = grouped.get(key);
40
55
  if (existing) {
41
56
  existing.row.runs += 1;
@@ -46,13 +61,18 @@ export function aggregateCostEntries(entries: ReadonlyArray<CostEntry>): CostRow
46
61
  existing.row.cacheWrite += entry.cacheWrite;
47
62
  existing.row.reasoningTokens += entry.reasoningTokens;
48
63
  existing.row.apiCalls += entry.apiCalls ?? 1;
64
+ for (const requestedModelId of entry.requestedModelIds) existing.requestedModelIds.add(requestedModelId);
65
+ addResponseModelIdObservationCounts(
66
+ existing.responseModelIdObservationCounts,
67
+ entry.responseModelIdObservationCounts,
68
+ );
49
69
  existing.entries.push(entry);
50
70
  continue;
51
71
  }
52
72
  grouped.set(key, {
53
73
  row: {
54
74
  providerId: entry.providerId,
55
- modelId: entry.modelId,
75
+ attributedModelId: entry.attributedModelId,
56
76
  runs: 1,
57
77
  tokens: entry.tokens,
58
78
  input: entry.input,
@@ -62,22 +82,31 @@ export function aggregateCostEntries(entries: ReadonlyArray<CostEntry>): CostRow
62
82
  reasoningTokens: entry.reasoningTokens,
63
83
  apiCalls: entry.apiCalls ?? 1,
64
84
  },
85
+ requestedModelIds: new Set(entry.requestedModelIds),
86
+ responseModelIdObservationCounts: { ...entry.responseModelIdObservationCounts },
65
87
  entries: [entry],
66
88
  });
67
89
  }
68
- const rows = Array.from(grouped.values(), ({ row, entries }) => ({
90
+ const rows = Array.from(grouped.values(), ({ row, entries, requestedModelIds, responseModelIdObservationCounts }) => ({
69
91
  ...row,
92
+ requestedModelIds: [...requestedModelIds].sort(),
93
+ responseModelIdObservationCounts,
70
94
  cost: aggregateCostAmounts(entries.map((entry) => ({ usd: entry.usd, provenance: entry.provenance }))),
71
95
  }));
72
96
  rows.sort((a, b) => {
73
97
  if (a.providerId !== b.providerId) return a.providerId < b.providerId ? -1 : 1;
74
- if (a.modelId !== b.modelId) return a.modelId < b.modelId ? -1 : 1;
98
+ if (a.attributedModelId !== b.attributedModelId) return a.attributedModelId < b.attributedModelId ? -1 : 1;
75
99
  return 0;
76
100
  });
77
101
  return rows;
78
102
  }
79
103
 
80
- function sumRows(rows: ReadonlyArray<CostRow>): Omit<CostRow, "providerId" | "modelId" | "cost"> {
104
+ function sumRows(
105
+ rows: ReadonlyArray<CostRow>,
106
+ ): Omit<
107
+ CostRow,
108
+ "providerId" | "attributedModelId" | "requestedModelIds" | "responseModelIdObservationCounts" | "cost"
109
+ > {
81
110
  return rows.reduce(
82
111
  (acc, row) => ({
83
112
  runs: acc.runs + row.runs,
@@ -156,6 +185,8 @@ function modelBlock(row: CostRow): string[] {
156
185
  // block with token rows and no cost row.
157
186
  const cost = formatCostAggregate(row.cost);
158
187
  return kvBlock([
188
+ ["requested model ids", row.requestedModelIds.join(", ")],
189
+ ["response model id observation", responseModelIdObservationCountsLabel(row.responseModelIdObservationCounts)],
159
190
  ["turns", formatTokens(row.runs)],
160
191
  ["model calls", formatTokens(row.apiCalls)],
161
192
  ...(cost === null ? [] : [["cost", cost] as const]),
@@ -185,7 +216,7 @@ export function formatCostOverlayBodyLines(
185
216
  } else {
186
217
  for (const [index, row] of rows.entries()) {
187
218
  if (index > 0) lines.push("");
188
- lines.push(theme.style("accent", `${row.providerId} · ${row.modelId}`, { bold: true }));
219
+ lines.push(theme.style("accent", `${row.providerId} · attributed model ${row.attributedModelId}`, { bold: true }));
189
220
  for (const line of modelBlock(row)) {
190
221
  lines.push(line);
191
222
  }