@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
@@ -41,6 +41,7 @@ import { type ReceiptIntegrityResult, verifyReceiptIntegrity } from "../domains/
41
41
  import { explainRouteDecision } from "../domains/dispatch/routing-intent.js";
42
42
  import type { RunGateProvenance, RunGateSubjectRef, RunPlanProvenance, RunReceipt } from "../domains/dispatch/types.js";
43
43
  import { extractRunProvenance, provenanceCompactSuffix } from "../domains/evidence/provenance.js";
44
+ import { adaptRunReceiptTrustStatus } from "../domains/evidence/trust-status.js";
44
45
  import type { AutonomyLevel } from "../domains/safety/autonomy.js";
45
46
  import {
46
47
  type CandidateWorktree,
@@ -458,8 +459,8 @@ function formatDispatchOutput(
458
459
  .map((run) => integrityFailureBanner(run))
459
460
  .filter((banner): banner is string => banner !== null);
460
461
  const needsSpotCheck = runs.some((run) => {
461
- const state = run.receipt.verification.state;
462
- return state === "unverified" || state === "unknown";
462
+ const state = adaptRunReceiptTrustStatus(run.receipt, { integrity: run.integrity }).validationGrounding.state;
463
+ return state === "absent" || state === "unknown" || state === "ungrounded";
463
464
  });
464
465
  const lines = [
465
466
  `dispatch (${mode}) total=${runs.length} failed=${failed.length}`,
@@ -486,9 +487,8 @@ function formatDispatchOutput(
486
487
  // Evidence confidence comes from the sealed receipt. A receipt that fails
487
488
  // integrity cannot be read as evidence at all.
488
489
  const verification = run.integrity.ok ? receipt.verification : UNVERIFIABLE_RECEIPT_VERIFICATION;
489
- const evidenceSuffix = ` ${receiptEvidenceLabels(receipt, verification, run.integrity).join(" ")}${
490
- run.integrity.ok ? "" : " evidence_verification=unknown/receipt-integrity-failed"
491
- }`;
490
+ const trustStatus = adaptRunReceiptTrustStatus({ ...receipt, verification }, { integrity: run.integrity });
491
+ const evidenceSuffix = ` ${receiptEvidenceLabels(receipt, verification, run.integrity).join(" ")}`;
492
492
  const routingSuffix =
493
493
  run.integrity.ok && receipt.routeDecision !== undefined && receipt.routingIntent !== undefined
494
494
  ? ` route_decision=${receipt.routeDecision.decisionHash} route_mode=${receipt.routeDecision.mode}`
@@ -509,9 +509,9 @@ function formatDispatchOutput(
509
509
  : "(worker text withheld because receipt integrity failed)";
510
510
  return [
511
511
  `- ${stepLabel}${receipt.runId} agent=${receipt.agentId} exit=${receipt.exitCode} target=${receipt.targetId} model=${receipt.wireModelId} tokens=${receipt.tokenCount} receipt=${receiptPath ?? "n/a"}${evidenceSuffix}${outcomeSuffix}${noteSuffix}${failure}${provenance}${routingSuffix}`,
512
- ` ${workerTextLabel(verification)}`,
512
+ ` ${workerTextLabel(trustStatus)}`,
513
513
  ...output.split("\n").map((line) => ` ${line}`),
514
- ...workerTextNonEvidenceNotices(receipt, verification, answerText).map((notice) => ` ${notice}`),
514
+ ...workerTextNonEvidenceNotices(receipt, trustStatus, answerText).map((notice) => ` ${notice}`),
515
515
  ];
516
516
  }),
517
517
  ];
@@ -555,6 +555,7 @@ function dispatchDetails(
555
555
  // Additive provenance keys only; folded in when the receipt carries the
556
556
  // field so a run entry without them keeps its exact shape.
557
557
  const provenance = extractRunProvenance(receipt);
558
+ const trustStatus = adaptRunReceiptTrustStatus(receipt, { integrity });
558
559
  return {
559
560
  runId: receipt.runId,
560
561
  agentId: receipt.agentId,
@@ -566,6 +567,7 @@ function dispatchDetails(
566
567
  // receipt is machine-visible here too.
567
568
  verification: integrity.ok ? receipt.verification : UNVERIFIABLE_RECEIPT_VERIFICATION,
568
569
  receiptIntegrity: integrity,
570
+ trustStatus,
569
571
  ...(receipt.outcome !== undefined && receipt.outcome !== "succeeded"
570
572
  ? { outcome: receipt.outcome, outcomeDetail: receipt.outcomeDetail ?? null }
571
573
  : {}),
@@ -25,6 +25,27 @@ export type { DispatchToolDeps } from "./dispatch-types.js";
25
25
 
26
26
  const THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"] as const;
27
27
 
28
+ const DispatchBudgetPhaseSchema = Type.Object(
29
+ {
30
+ toolCalls: Type.Integer({ minimum: 1 }),
31
+ readReserve: Type.Integer({ minimum: 0 }),
32
+ },
33
+ { additionalProperties: false },
34
+ );
35
+
36
+ const DispatchBudgetSchema = Type.Object(
37
+ {
38
+ toolCalls: Type.Integer({ minimum: 1, description: "Requested tool-call phase boundary." }),
39
+ readReserve: Type.Integer({ minimum: 0, description: "Requested tail reserve for canonical read calls." }),
40
+ retryRevision: Type.Optional(DispatchBudgetPhaseSchema),
41
+ },
42
+ {
43
+ additionalProperties: false,
44
+ description:
45
+ "Invocation budget inside the recipe policy. retryRevision preauthorizes one ceiling for retry, result-contract revision, or review revision phases.",
46
+ },
47
+ );
48
+
28
49
  /**
29
50
  * Stable, lightweight dispatch surface. Admission remains synchronous so the
30
51
  * policy decision and provisional reservation are bound to the exact argument
@@ -62,7 +83,7 @@ export function createDispatchTool(
62
83
  return {
63
84
  name: ToolNames.Dispatch,
64
85
  description:
65
- 'Dispatch one bounded task with task, or a batch with tasks (never both). Singular example: {agent:"debugger", task:"Verify the receipt boundary", briefing:"Prior receipt evidence...", detach:true}. task is the worker assignment; briefing is separate bounded parent context/data and cannot replace task. Ordinary calls auto-wait; detach:true returns ids for monitoring/steering, and collect is the authoritative terminal batch operation before final synthesis. Batch modes are parallel (default), sequential, pipeline, or compete. Task objects may include persona and tool_profile. Sealed receipts are durable evidence; report receipt integrity, evidence verification, briefing provenance, and project-context provenance separately. Call with list:true to see agents. Do not repeat an identical successful dispatch in the same user turn. Prefer this tool over inline exploration whenever work is read-only fan-out, parallel investigation, or the operator asked for a worker by name; if you cannot dispatch, say so plainly and name the reason, and never narrate or summarize a worker you did not actually dispatch.',
86
+ 'Dispatch one bounded task with task, or a batch with tasks (never both). Singular example: {agent:"debugger", task:"Verify the receipt boundary", briefing:"Prior receipt evidence...", detach:true}. task is the worker assignment; briefing is separate bounded parent context/data and cannot replace task. Ordinary calls auto-wait; detach:true returns ids for monitoring/steering, and collect is the authoritative terminal batch operation before final synthesis. Batch modes are parallel (default), sequential, pipeline, or compete. Task objects may include persona, tool_profile, and a recipe-admitted budget envelope. Sealed receipts are durable evidence; report receipt integrity, evidence verification, briefing provenance, and project-context provenance separately. Call with list:true to see agents. Do not repeat an identical successful dispatch in the same user turn. Prefer this tool over inline exploration whenever work is read-only fan-out, parallel investigation, or the operator asked for a worker by name; if you cannot dispatch, say so plainly and name the reason, and never narrate or summarize a worker you did not actually dispatch.',
66
87
  parameters: Type.Object({
67
88
  list: Type.Optional(Type.Boolean({ description: "List available agents instead of dispatching." })),
68
89
  from_scout: Type.Optional(
@@ -105,6 +126,7 @@ export function createDispatchTool(
105
126
  tool_profile: Type.Optional(
106
127
  StringEnum(TOOL_PROFILE_NAMES, { description: "Narrow this worker's available tools." }),
107
128
  ),
129
+ budget: Type.Optional(DispatchBudgetSchema),
108
130
  target: Type.Optional(Type.String()),
109
131
  model: Type.Optional(Type.String()),
110
132
  node: Type.Optional(Type.String({ description: "Fleet node pin: local or a fleet.nodes id." })),
@@ -190,6 +212,7 @@ export function createDispatchTool(
190
212
  Type.String({ description: "Default ad-hoc specialist persona for dispatched tasks, max 8000 chars." }),
191
213
  ),
192
214
  tool_profile: Type.Optional(StringEnum(TOOL_PROFILE_NAMES, { description: "Default worker tool profile." })),
215
+ budget: Type.Optional(DispatchBudgetSchema),
193
216
  target: Type.Optional(Type.String({ description: "Default configured target id (omit for fleet default)." })),
194
217
  model: Type.Optional(Type.String({ description: "Default model override." })),
195
218
  node: Type.Optional(
@@ -2,15 +2,26 @@ import { readFileSync } from "node:fs";
2
2
  import { sleep } from "../core/timers.js";
3
3
  import { renderAgentLedgerBoard } from "../domains/dispatch/agent-ledger-store.js";
4
4
  import type { DurableAssignmentRecord } from "../domains/dispatch/assignment-store.js";
5
+ import {
6
+ formatBudgetPolicy,
7
+ formatBudgetReasons,
8
+ formatBudgetRequest,
9
+ formatEffectiveBudget,
10
+ } from "../domains/dispatch/budget-envelope.js";
5
11
  import type { DispatchContract } from "../domains/dispatch/contract.js";
6
12
  import { UNVERIFIABLE_RECEIPT_VERIFICATION } from "../domains/dispatch/receipt-findings.js";
7
- import { type ReceiptIntegrityResult, verifyReceiptIntegrity } from "../domains/dispatch/receipt-integrity.js";
13
+ import type { ReceiptIntegrityResult } from "../domains/dispatch/receipt-integrity.js";
8
14
  import {
9
15
  isTerminalRunEnvelope,
10
16
  type RunEnvelope,
11
17
  type RunReceipt,
12
18
  type RunReceiptVerification,
13
19
  } from "../domains/dispatch/types.js";
20
+ import {
21
+ adaptRunReceiptTrustStatus,
22
+ type CanonicalTrustStatus,
23
+ inspectRunReceiptTrustStatus,
24
+ } from "../domains/evidence/trust-status.js";
14
25
  import { COST_NOT_MEASURED, costAggregateForAmount, formatCostAggregate } from "../domains/observability/index.js";
15
26
  import type { DispatchRunEventRegistry } from "./dispatch.js";
16
27
  import { monitorToolSurface } from "./monitor-surface.js";
@@ -112,6 +123,14 @@ function runStatus(deps: MonitorToolDeps, runId: string): ToolResult {
112
123
  `started=${run.startedAt} ended=${run.endedAt ?? "n/a"} exit=${run.exitCode ?? "n/a"}`,
113
124
  `tokens=${run.tokenCount} cost=${formatCostAggregate(costAggregateForAmount(run.costUsd, run.costProvenance)) ?? COST_NOT_MEASURED} receipt=${run.receiptPath ?? "n/a"}`,
114
125
  ];
126
+ if (run.budget !== undefined) {
127
+ lines.push(
128
+ `recipe policy: ${formatBudgetPolicy(run.budget)}`,
129
+ `requested envelope: ${formatBudgetRequest(run.budget)}`,
130
+ `effective envelope: ${formatEffectiveBudget(run.budget)}`,
131
+ `clamp or escalation reason: ${formatBudgetReasons(run.budget)}`,
132
+ );
133
+ }
115
134
  if (live) {
116
135
  lines.push(
117
136
  `live: phase=${live.outcomePhase} heartbeat=${live.heartbeat} elapsed=${Math.round(live.elapsedMs / 1000)}s tokens=${live.tokens.total}`,
@@ -138,6 +157,7 @@ function runStatus(deps: MonitorToolDeps, runId: string): ToolResult {
138
157
  tokenCount: run.tokenCount,
139
158
  costUsd: run.costUsd,
140
159
  costProvenance: run.costProvenance ?? "unknown",
160
+ budget: run.budget ?? null,
141
161
  receiptPath: run.receiptPath,
142
162
  running: live !== null,
143
163
  },
@@ -333,14 +353,18 @@ function runReceipt(deps: MonitorToolDeps, runId: string): ToolResult {
333
353
  const body = truncateUtf8(raw, RECEIPT_MAX_BYTES, `\n[receipt truncated; read ${run.receiptPath} for the rest]`);
334
354
  let receipt: RunReceipt | null = null;
335
355
  let receiptIntegrity: ReceiptIntegrityResult;
356
+ let trustStatus: CanonicalTrustStatus;
336
357
  try {
337
358
  receipt = JSON.parse(raw) as RunReceipt;
338
- receiptIntegrity = verifyReceiptIntegrity(receipt, run);
359
+ const inspection = inspectRunReceiptTrustStatus(receipt, run);
360
+ receiptIntegrity = inspection.integrity;
361
+ trustStatus = inspection.status;
339
362
  } catch (err) {
340
363
  receiptIntegrity = {
341
364
  ok: false,
342
365
  reason: `receipt invalid: ${err instanceof Error ? err.message : String(err)}`,
343
366
  };
367
+ trustStatus = adaptRunReceiptTrustStatus(null, { integrity: receiptIntegrity });
344
368
  }
345
369
  return {
346
370
  kind: "ok",
@@ -350,6 +374,7 @@ function runReceipt(deps: MonitorToolDeps, runId: string): ToolResult {
350
374
  runId,
351
375
  receiptPath: run.receiptPath,
352
376
  receiptIntegrity,
377
+ trustStatus,
353
378
  ...(receipt !== null && receiptIntegrity.ok
354
379
  ? {
355
380
  evidenceVerification: receipt.verification,
@@ -366,6 +391,7 @@ interface DurableRunEvidence {
366
391
  output: RunReceipt["output"] | null;
367
392
  verification: RunReceiptVerification;
368
393
  integrity: ReceiptIntegrityResult;
394
+ trustStatus: CanonicalTrustStatus;
369
395
  integrityNote: string | null;
370
396
  integrityFailure: boolean;
371
397
  }
@@ -376,6 +402,7 @@ function unavailableRunEvidence(reason: string, note: string, integrityFailure =
376
402
  output: null,
377
403
  verification: UNVERIFIABLE_RECEIPT_VERIFICATION,
378
404
  integrity: { ok: false, reason },
405
+ trustStatus: adaptRunReceiptTrustStatus(null, { integrity: { ok: false, reason } }),
379
406
  integrityNote: note,
380
407
  integrityFailure,
381
408
  };
@@ -410,29 +437,24 @@ function durableRunEvidence(run: RunEnvelope | null): DurableRunEvidence {
410
437
  `receipt integrity unavailable: cannot read or parse ${run.receiptPath} (${detail}); worker text is unavailable and validation is unknown.`,
411
438
  );
412
439
  }
413
- let integrity: ReceiptIntegrityResult;
414
- try {
415
- integrity = verifyReceiptIntegrity(receipt, run);
416
- } catch (err) {
417
- const detail = err instanceof Error ? err.message : String(err);
418
- return unavailableRunEvidence(
419
- `receipt invalid: ${detail}`,
420
- `receipt integrity failed: invalid receipt (${detail}); worker text is withheld as untrusted and validation is unknown.`,
421
- true,
422
- );
423
- }
440
+ const inspection = inspectRunReceiptTrustStatus(receipt, run);
441
+ const integrity = inspection.integrity;
424
442
  if (!integrity.ok) {
425
- return unavailableRunEvidence(
426
- integrity.reason,
427
- `receipt integrity failed: ${integrity.reason}; worker text is withheld as untrusted and validation is unknown.`,
428
- true,
429
- );
443
+ return {
444
+ ...unavailableRunEvidence(
445
+ integrity.reason,
446
+ `receipt integrity failed: ${integrity.reason}; worker text is withheld as untrusted and validation is unknown.`,
447
+ true,
448
+ ),
449
+ trustStatus: inspection.status,
450
+ };
430
451
  }
431
452
  return {
432
453
  receipt,
433
454
  output: receipt.output ?? null,
434
455
  verification: receipt.verification,
435
456
  integrity,
457
+ trustStatus: inspection.status,
436
458
  integrityNote: null,
437
459
  integrityFailure: false,
438
460
  };
@@ -534,7 +556,7 @@ function collectRunLine(row: CollectedRunRow): string[] {
534
556
  );
535
557
  }
536
558
  if (row.evidence.integrityNote) lines.push(` ${row.evidence.integrityNote}`);
537
- lines.push(` ${workerTextLabel(row.evidence.verification)}`);
559
+ lines.push(` ${workerTextLabel(row.evidence.trustStatus)}`);
538
560
  const output = row.evidence.output;
539
561
  if (output) {
540
562
  const capped = truncateUtf8(output.text, COLLECT_TEXT_BYTES, "...");
@@ -543,7 +565,7 @@ function collectRunLine(row: CollectedRunRow): string[] {
543
565
  lines.push(` agent output${qualifier}${truncatedNote}:`, ...capped.split("\n").map((line) => ` ${line}`));
544
566
  if (row.evidence.receipt) {
545
567
  lines.push(
546
- ...workerTextNonEvidenceNotices(row.evidence.receipt, row.evidence.verification, output.text).map(
568
+ ...workerTextNonEvidenceNotices(row.evidence.receipt, row.evidence.trustStatus, output.text).map(
547
569
  (notice) => ` ${notice}`,
548
570
  ),
549
571
  );
@@ -693,6 +715,7 @@ async function runCollect(
693
715
  exitCode: row.run?.exitCode ?? null,
694
716
  receiptPath: row.run?.receiptPath ?? null,
695
717
  receiptIntegrity: row.evidence.integrity,
718
+ trustStatus: row.evidence.trustStatus,
696
719
  evidenceVerification: row.evidence.verification,
697
720
  briefing: row.evidence.receipt?.briefing ?? null,
698
721
  projectContext: row.evidence.receipt?.projectContext ?? null,
@@ -22,12 +22,14 @@ import {
22
22
  mapAutonomy,
23
23
  } from "../domains/safety/autonomy.js";
24
24
  import type { SafetyContract, SafetyDecision } from "../domains/safety/contract.js";
25
+ import type { DecisionPresentation } from "../domains/safety/decision-presentation.js";
25
26
  import { hashToolCall } from "../domains/safety/loop-detector.js";
26
27
  import { detectValidationCommand } from "../domains/safety/protected-artifacts.js";
27
28
  import { askUserExposure } from "./ask-user.js";
28
29
  import { type DispatchPlanView, describeDispatchPlan } from "./dispatch-plan.js";
29
30
  import type { ToolPresentationPolicy } from "./presentation.js";
30
- import { shapeToolResult } from "./result-shaping.js";
31
+ import type { ToolResultDigest, ToolResultDisposition } from "./result-disposition.js";
32
+ import { DEFAULT_TOOL_RESULT_MAX_BYTES, shapeToolResult, toolResultDigestFor } from "./result-shaping.js";
31
33
 
32
34
  /**
33
35
  * Tool registry. Admission point for every tool call. Delegates classification
@@ -56,6 +58,8 @@ export interface ToolSourceInfo {
56
58
  export interface ToolResultSizePolicy {
57
59
  kind: "exact" | "bounded" | "summary" | "truncate";
58
60
  maxBytes?: number;
61
+ /** Scratch retention ceiling for this tool; defaults to the generic 10 MiB cap. */
62
+ offloadMaxBytes?: number;
59
63
  followUpHint?: string;
60
64
  }
61
65
 
@@ -68,6 +72,8 @@ export interface ToolMetadata {
68
72
  retrySafety: ToolRetrySafety;
69
73
  /** Expected result-size behavior at the registry boundary. */
70
74
  resultSizePolicy: ToolResultSizePolicy;
75
+ /** Independent operator-presentation and model-context policy for this result. */
76
+ resultDisposition?: ToolResultDisposition;
71
77
  /** Coarse cost/latency bucket for dashboard diagnostics. */
72
78
  costLatency: ToolCostLatencyClass;
73
79
  /**
@@ -114,6 +120,15 @@ export interface ToolSpec {
114
120
  * the same function at the top of `run`.
115
121
  */
116
122
  prepareArguments?(args: Record<string, unknown>): Record<string, unknown>;
123
+ /**
124
+ * Resolve an argument-sensitive canonical disposition after normalization
125
+ * and before execution. The registry applies the result exactly once after
126
+ * middleware has annotated the terminal result.
127
+ */
128
+ resolveResultDisposition?(
129
+ args: Record<string, unknown>,
130
+ declared: ToolResultDisposition | undefined,
131
+ ): ToolResultDisposition | undefined;
117
132
  /**
118
133
  * Synchronous admission planner. Unlike `prepareArguments`, this runs before
119
134
  * safety/autonomy mapping so approval-sensitive tools can attach the exact
@@ -136,6 +151,8 @@ export type ToolResult =
136
151
  kind: "ok";
137
152
  output: string;
138
153
  details?: ToolResultDetails;
154
+ /** Internal registry projection consumed only by the agent-tool adapter. */
155
+ modelContext?: string;
139
156
  /**
140
157
  * Early-termination hint propagated to pi-agent-core's
141
158
  * `AgentToolResult.terminate`. When every finalized tool result in
@@ -145,7 +162,7 @@ export type ToolResult =
145
162
  */
146
163
  terminate?: boolean;
147
164
  }
148
- | { kind: "error"; message: string; details?: ToolResultDetails };
165
+ | { kind: "error"; message: string; details?: ToolResultDetails; modelContext?: string };
149
166
 
150
167
  export interface RegistryDeps {
151
168
  safety: SafetyContract;
@@ -184,6 +201,8 @@ export interface ToolInvokeOptions {
184
201
  correlationId?: string;
185
202
  pendingSkillPolicy?: PendingSkillToolPolicy;
186
203
  askUserPolicy?: AskUserToolPolicy;
204
+ /** Host-derived display copy for an ask_user round. It has no admission authority. */
205
+ decisionPresentation?: DecisionPresentation;
187
206
  /** Registry-authenticated one-shot operator approval for this execution. */
188
207
  approval?: { requestId: string; requestedBy: string; actionClass: ActionClass };
189
208
  /**
@@ -243,6 +262,8 @@ export interface AskUserToolPolicy {
243
262
  sessionId?: string;
244
263
  turnId?: string;
245
264
  transcriptPath?: string;
265
+ /** Monotonic exposure fact for live presentation and durable replay. */
266
+ exposure?: AutonomyExposure;
246
267
  summary?: string;
247
268
  rounds: AskUserTranscriptRound[];
248
269
  decisions: AskUserTranscriptDecision[];
@@ -384,6 +405,7 @@ export function createRegistry(deps: RegistryDeps): ToolRegistry {
384
405
  decision: SafetyDecision,
385
406
  options?: ToolInvokeOptions,
386
407
  ): Promise<RegistryVerdict> => {
408
+ let resultDisposition = spec.metadata?.resultDisposition;
387
409
  try {
388
410
  // The hook layer is the only control stage past safety admission. Guards
389
411
  // (loop, protected artifacts, dispatch dedup) are before_tool
@@ -402,17 +424,20 @@ export function createRegistry(deps: RegistryDeps): ToolRegistry {
402
424
  }
403
425
  try {
404
426
  const preparedArgs = prepareToolArgs(spec, call.args ?? {});
405
- const result = shapeToolResult(spec, await spec.run(preparedArgs, options), options);
406
- const afterEffects = runToolHook("after_tool", spec, call, decision, options, result);
407
- const finalResult = shapeToolResult(spec, applyToolResultEffects(result, afterEffects), options);
427
+ resultDisposition = resolveToolResultDisposition(spec, preparedArgs);
428
+ const result = await spec.run(preparedArgs, options);
429
+ const digest = toolResultDigestFor(spec, result, resultDisposition);
430
+ const afterEffects = runToolHook("after_tool", spec, call, decision, options, result, digest);
431
+ const finalResult = shapeToolResult(spec, applyToolResultEffects(result, afterEffects), options, resultDisposition);
408
432
  return { kind: "ok", result: finalResult, decision };
409
433
  } catch (err) {
410
434
  const message = err instanceof Error ? err.message : String(err);
411
- const result = shapeToolResult(spec, { kind: "error", message }, options);
412
- const afterEffects = runToolHook("after_tool", spec, call, decision, options, result);
435
+ const result: ToolResult = { kind: "error", message };
436
+ const digest = toolResultDigestFor(spec, result, resultDisposition);
437
+ const afterEffects = runToolHook("after_tool", spec, call, decision, options, result, digest);
413
438
  return {
414
439
  kind: "ok",
415
- result: shapeToolResult(spec, applyToolResultEffects(result, afterEffects), options),
440
+ result: shapeToolResult(spec, applyToolResultEffects(result, afterEffects), options, resultDisposition),
416
441
  decision,
417
442
  };
418
443
  }
@@ -428,9 +453,10 @@ export function createRegistry(deps: RegistryDeps): ToolRegistry {
428
453
  decision: SafetyDecision,
429
454
  options: ToolInvokeOptions | undefined,
430
455
  result?: ToolResult,
456
+ resultDigest?: ToolResultDigest,
431
457
  ): ReadonlyArray<MiddlewareEffect> => {
432
458
  if (!deps.middleware) return [];
433
- const input = buildToolHookInput(hook, spec, call, decision, "operating", options, result);
459
+ const input = buildToolHookInput(hook, spec, call, decision, "operating", options, result, resultDigest);
434
460
  const effects = deps.middleware.runHook(input).effects;
435
461
  try {
436
462
  deps.onMiddlewareEffects?.(effects, input);
@@ -857,6 +883,38 @@ function prepareToolArgs(spec: ToolSpec, args: Record<string, unknown>): Record<
857
883
  }
858
884
  }
859
885
 
886
+ /**
887
+ * Resolve the argument-sensitive disposition, failing closed. A throwing
888
+ * resolver cannot fall back to the declared disposition: the caller may have
889
+ * asked for a narrower context than the tool declares, and silently restoring
890
+ * the declared mode would widen model context while recording the declared mode
891
+ * as the requested one. The failure keeps the declared presentation and applies
892
+ * the narrowest context instead, so the applied and recorded modes stay honest.
893
+ */
894
+ function resolveToolResultDisposition(
895
+ spec: ToolSpec,
896
+ args: Record<string, unknown>,
897
+ ): ToolResultDisposition | undefined {
898
+ const declared = spec.metadata?.resultDisposition;
899
+ if (!spec.resolveResultDisposition) return declared;
900
+ try {
901
+ return spec.resolveResultDisposition(args, declared);
902
+ } catch (error) {
903
+ const maxBytes =
904
+ declared !== undefined && declared.context.maxBytes !== undefined
905
+ ? declared.context.maxBytes
906
+ : DEFAULT_TOOL_RESULT_MAX_BYTES;
907
+ return {
908
+ presentation: declared?.presentation ?? { foldDefault: "folded", showDiffWhenFolded: false, failureExcerpt: true },
909
+ context: { mode: "metadata-only", maxBytes },
910
+ // The narrowing is recorded with the result, so a resolver bug shows up
911
+ // on the transcript row and in the model's header instead of reading as
912
+ // a deliberate metadata-only request.
913
+ fallback: { reason: "resolver-error", message: error instanceof Error ? error.message : String(error) },
914
+ };
915
+ }
916
+ }
917
+
860
918
  function disposeAdmissionArgs(spec: ToolSpec | undefined, args: Record<string, unknown>): void {
861
919
  try {
862
920
  spec?.disposeAdmissionArguments?.(args);
@@ -1085,6 +1143,7 @@ function buildToolHookInput(
1085
1143
  posture: string,
1086
1144
  options: ToolInvokeOptions | undefined,
1087
1145
  result: ToolResult | undefined,
1146
+ resultDigest: ToolResultDigest | undefined,
1088
1147
  ): MiddlewareHookInput {
1089
1148
  const metadata: Record<string, MiddlewareMetadataValue> = {
1090
1149
  posture,
@@ -1121,6 +1180,7 @@ function buildToolHookInput(
1121
1180
  };
1122
1181
  if (call.args !== undefined) input.toolArgs = call.args;
1123
1182
  if (result?.details !== undefined) input.toolResultDetails = result.details;
1183
+ if (resultDigest !== undefined) input.toolResultDigest = resultDigest;
1124
1184
  if (options?.runId !== undefined) input.runId = options.runId;
1125
1185
  if (options?.sessionId !== undefined) input.sessionId = options.sessionId;
1126
1186
  if (options?.turnId !== undefined) input.turnId = options.turnId;
@@ -1161,7 +1221,9 @@ function applyToolResultEffects(result: ToolResult, effects: ReadonlyArray<Middl
1161
1221
  if (result.terminate === true) annotated.terminate = true;
1162
1222
  return annotated;
1163
1223
  }
1164
- return { kind: "error", message: `${result.message}${suffix}` };
1224
+ const annotated: ToolResult = { kind: "error", message: `${result.message}${suffix}` };
1225
+ if (result.details !== undefined) annotated.details = result.details;
1226
+ return annotated;
1165
1227
  }
1166
1228
 
1167
1229
  function annotationMessages(effects: ReadonlyArray<MiddlewareEffect>): string[] {