@iowarp/clio-coder 0.4.3 → 0.4.4

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 (340) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +1 -1
  3. package/dist/{acp-H2NGRPWO.js → acp-WNAYYF4F.js} +4 -5
  4. package/dist/{agents-TL5LLUQP.js → agents-3OKXHLOI.js} +33 -31
  5. package/dist/assets/codewiki.json +1 -1
  6. package/dist/{auth-E5SW4HMS.js → auth-VKNNMGPU.js} +10 -11
  7. package/dist/{builtins-IA7V7FUC.js → builtins-WGALA46I.js} +4 -4
  8. package/dist/{chunk-F5JHEYZM.js → chunk-23L32XTI.js} +10 -7
  9. package/dist/{chunk-DWUOQKRU.js → chunk-25QBEXRS.js} +2 -2
  10. package/dist/{chunk-LLDJM5XK.js → chunk-26QSH3EJ.js} +2 -2
  11. package/dist/{chunk-N2Z7HLVY.js → chunk-2ASED4PZ.js} +10 -10
  12. package/dist/{chunk-MCEPRMZW.js → chunk-2CU2H6KE.js} +2 -2
  13. package/dist/chunk-2DSOYNFC.js +108 -0
  14. package/dist/{chunk-LDJG7DW3.js → chunk-2ZSONWVL.js} +4 -4
  15. package/dist/{chunk-GI7YYQ3F.js → chunk-36CT5VVL.js} +324 -41
  16. package/dist/{chunk-4UVU7BJ5.js → chunk-3GY4F45V.js} +2 -2
  17. package/dist/{chunk-PUVDKJ2Y.js → chunk-3ODX73FK.js} +3 -5
  18. package/dist/{chunk-IUE3Y34X.js → chunk-3UNOLWNZ.js} +2 -2
  19. package/dist/{chunk-6PTFB5VS.js → chunk-3UUXNFEX.js} +8 -4
  20. package/dist/{chunk-2APPQIER.js → chunk-4M6Z5QVF.js} +4 -4
  21. package/dist/{chunk-K6BSR66V.js → chunk-4NSRCOYP.js} +4 -1
  22. package/dist/{chunk-JGRC33J2.js → chunk-54X7T7DK.js} +12 -3
  23. package/dist/{chunk-YQWYVTMC.js → chunk-5636DCO5.js} +4 -4
  24. package/dist/{chunk-7E7I3WLS.js → chunk-57XXR6DR.js} +23 -22
  25. package/dist/{chunk-7ZYNNDKC.js → chunk-5TUB6SLS.js} +2 -2
  26. package/dist/{chunk-VW6DOEDG.js → chunk-6OSVSQL5.js} +11 -2
  27. package/dist/{chunk-L47TF46W.js → chunk-6PAZTBPA.js} +14 -2
  28. package/dist/{chunk-XIVNBFZS.js → chunk-6Q3CYFD3.js} +34 -16
  29. package/dist/{chunk-RSJ25QSL.js → chunk-6QOTUPRG.js} +155 -36
  30. package/dist/{chunk-JKKCYP3C.js → chunk-6UINWWS6.js} +10 -4
  31. package/dist/{chunk-WBKFA554.js → chunk-72YIHOZQ.js} +2 -2
  32. package/dist/{chunk-PAJQJ7BS.js → chunk-75W7L2E2.js} +246 -697
  33. package/dist/{chunk-RRNP2ANY.js → chunk-7UGL4MB5.js} +4 -4
  34. package/dist/{chunk-EKCHAPYA.js → chunk-AUPNRN7C.js} +2 -2
  35. package/dist/{chunk-ZDN3Y73Y.js → chunk-BJVFZO5U.js} +6 -48
  36. package/dist/{chunk-IWT4SF4R.js → chunk-CUSRQKPU.js} +64 -2
  37. package/dist/{chunk-SKHCAU7K.js → chunk-DQOVN6KV.js} +3 -2
  38. package/dist/{chunk-ZWPRK62N.js → chunk-DT3LWJOB.js} +4 -4
  39. package/dist/chunk-DXKJURES.js +671 -0
  40. package/dist/{chunk-BEPZRGGU.js → chunk-EL24TAU4.js} +2 -2
  41. package/dist/{chunk-OML5D5V5.js → chunk-ELWDPP3Y.js} +5 -5
  42. package/dist/{chunk-NDINPTJ4.js → chunk-ELZVTCGV.js} +5 -4
  43. package/dist/chunk-EXLD33WO.js +381 -0
  44. package/dist/{chunk-IJNZMHLA.js → chunk-FEAXX7B6.js} +2 -2
  45. package/dist/{chunk-TM6LQDI3.js → chunk-FFUPXJC4.js} +74 -323
  46. package/dist/chunk-GX5WYQO4.js +59 -0
  47. package/dist/chunk-I2DWJ4GM.js +390 -0
  48. package/dist/{chunk-TXOTCRLG.js → chunk-I5FWO7L5.js} +5 -5
  49. package/dist/chunk-IRXAATOX.js +539 -0
  50. package/dist/chunk-IXIY2H4R.js +44 -0
  51. package/dist/{chunk-KK4JZPBQ.js → chunk-IZXGRF7P.js} +76 -10
  52. package/dist/{chunk-5TSRNF4G.js → chunk-JCI2ROMZ.js} +164 -6
  53. package/dist/{chunk-INY6HTFL.js → chunk-JEIYHLOR.js} +2 -2
  54. package/dist/{chunk-MUW2BDDH.js → chunk-JQLNNIKT.js} +2 -2
  55. package/dist/{chunk-XPWWI35G.js → chunk-JSD46VO2.js} +19 -8
  56. package/dist/{chunk-VA5FNYMT.js → chunk-JT2RFCC5.js} +39 -2
  57. package/dist/{chunk-V2ANDPVT.js → chunk-K6T2ZAMZ.js} +168 -6
  58. package/dist/{chunk-B4OAX3SI.js → chunk-KFV5L5SK.js} +13 -6
  59. package/dist/{chunk-JEQ3XTHC.js → chunk-LLXSDWXS.js} +2 -2
  60. package/dist/{chunk-E3TPLWFX.js → chunk-LTIKRKFL.js} +3 -3
  61. package/dist/{chunk-NIQJ66N4.js → chunk-N56KALIC.js} +17 -17
  62. package/dist/{chunk-JDAY6FIL.js → chunk-NAI6ZFCY.js} +13 -9
  63. package/dist/{chunk-AF4YM7Z4.js → chunk-NRO2BJRH.js} +2490 -2182
  64. package/dist/{chunk-WRBAGUNF.js → chunk-NXIMQY5W.js} +2 -2
  65. package/dist/{chunk-I7ZPNEJM.js → chunk-NXYCB2VD.js} +5 -5
  66. package/dist/chunk-ODGTEFFI.js +50 -0
  67. package/dist/{chunk-2VIKGWFZ.js → chunk-OEJSLEPW.js} +2 -2
  68. package/dist/{chunk-KKOJXO6R.js → chunk-OMQNJVKW.js} +4 -2
  69. package/dist/{chunk-54CBCGIR.js → chunk-Q4WO54TA.js} +132 -77
  70. package/dist/{chunk-B4VEBZKF.js → chunk-QUFRYSWI.js} +12 -6
  71. package/dist/{chunk-42FMPA75.js → chunk-QZWQA4DE.js} +2 -2
  72. package/dist/{chunk-HEQY7ZFI.js → chunk-RAY4OVGZ.js} +2 -2
  73. package/dist/{chunk-G76U63X4.js → chunk-RQCKCSRL.js} +7 -7
  74. package/dist/{chunk-64I3JVYM.js → chunk-RXTN6AKH.js} +2 -2
  75. package/dist/{chunk-UPZU6GE4.js → chunk-RZDWV63N.js} +3 -3
  76. package/dist/{chunk-2UH2KFUP.js → chunk-S6PYF2XF.js} +2 -2
  77. package/dist/{chunk-JSC3U7TI.js → chunk-TOIVGRUX.js} +2 -2
  78. package/dist/{chunk-7DRAWPTZ.js → chunk-TQAHXW6Y.js} +1 -1
  79. package/dist/{chunk-JIEGK6UF.js → chunk-U6TMQNSI.js} +48 -4
  80. package/dist/{chunk-AX2THNSA.js → chunk-UEPWCCTY.js} +4 -4
  81. package/dist/{chunk-QWGDJJYJ.js → chunk-USR47QNF.js} +4 -4
  82. package/dist/{chunk-Y3CBHOR6.js → chunk-V6HJFQZE.js} +2 -2
  83. package/dist/chunk-V76WTFTW.js +318 -0
  84. package/dist/{chunk-NMJXSHBJ.js → chunk-W54I7H25.js} +2 -2
  85. package/dist/{chunk-2UG5F4C5.js → chunk-XULDXHTN.js} +24 -12
  86. package/dist/chunk-XXYSBZIQ.js +283 -0
  87. package/dist/{chunk-MWUZBSAQ.js → chunk-Y55JBDO5.js} +331 -51
  88. package/dist/{chunk-W6RRQCPQ.js → chunk-YD5GIKET.js} +4 -4
  89. package/dist/{chunk-CE5AX47J.js → chunk-YECAMM3D.js} +2 -2
  90. package/dist/{chunk-WCXUNS7U.js → chunk-YNFKXPEC.js} +6 -6
  91. package/dist/cli/index.js +36 -35
  92. package/dist/{clio-CMMK4KRR.js → clio-QLICPCF5.js} +2 -2
  93. package/dist/{code-nav-MDZNQS33.js → code-nav-IJR2DBPR.js} +6 -6
  94. package/dist/{components-UCUQ4QXW.js → components-2TGAI2RC.js} +3 -4
  95. package/dist/{config-SVM5P5YI.js → config-IUA6OYNS.js} +52 -47
  96. package/dist/{configure-LE3IK2TJ.js → configure-VEPX4NMX.js} +14 -15
  97. package/dist/{context-VNCR7KAG.js → context-2DKHWH2T.js} +23 -23
  98. package/dist/{context-2OHRKS42.js → context-4MPR7WKB.js} +48 -42
  99. package/dist/{context-E3VC7RX5.js → context-BOYF5EJM.js} +11 -11
  100. package/dist/{context-clear-BW4O37TG.js → context-clear-S4ZJCQUX.js} +48 -42
  101. package/dist/{context-working-set-VDS25HXZ.js → context-working-set-3I3FYX6Y.js} +8 -8
  102. package/dist/detail-A7JAVSIG.js +98 -0
  103. package/dist/{dispatch-runner-5AHT53RF.js → dispatch-runner-RJ5I2F2O.js} +71 -58
  104. package/dist/{docs-PD3EXDKU.js → docs-SPOV3BAN.js} +3 -5
  105. package/dist/{doctor-WNNVO6FY.js → doctor-DKICC2SN.js} +54 -31
  106. package/dist/{eval-7G7SGAYO.js → eval-OQOQUDHK.js} +47 -56
  107. package/dist/{evidence-VD6736FQ.js → evidence-4DQ25GUQ.js} +53 -150
  108. package/dist/evidence-4F5USFKH.js +208 -0
  109. package/dist/{evolve-AL3NGVRL.js → evolve-GSS52E5J.js} +44 -41
  110. package/dist/{extensions-MOVJ32NM.js → extensions-G7MFLYHT.js} +4 -5
  111. package/dist/{fleet-QZHUMAGI.js → fleet-Q37YHHAQ.js} +74 -68
  112. package/dist/{fleet-commands-BAYT5FJZ.js → fleet-commands-G7E4N7SM.js} +14 -11
  113. package/dist/{fleet-decisions-IREVMRU4.js → fleet-decisions-O7M6QBA2.js} +6 -6
  114. package/dist/{fleet-graph-YCTT3HTI.js → fleet-graph-TOUBW6OW.js} +13 -13
  115. package/dist/{fleet-inspect-QVJTDAVB.js → fleet-inspect-SW33JJNI.js} +43 -39
  116. package/dist/{fleet-preflight-25QAFPK4.js → fleet-preflight-CV2655TW.js} +2 -3
  117. package/dist/{fleet-validate-5O57AAJ7.js → fleet-validate-KESZX2YH.js} +16 -16
  118. package/dist/{fleet-verify-CPH2W2T6.js → fleet-verify-UQPMTVE3.js} +42 -38
  119. package/dist/{fleet-view-SWBR3VGQ.js → fleet-view-MN2VG4MR.js} +43 -39
  120. package/dist/{init-J477LKZH.js → init-PXEXQSBF.js} +60 -54
  121. package/dist/{interop-3FCM6XLG.js → interop-ZG5T62U3.js} +6 -7
  122. package/dist/inventory-C26CFDRR.js +101 -0
  123. package/dist/{library-QUQEIUG6.js → library-B2W4N74O.js} +16 -17
  124. package/dist/{memory-SGGSEP65.js → memory-YCANYS5A.js} +45 -42
  125. package/dist/{models-HEKUAXXK.js → models-GERTU3YI.js} +20 -22
  126. package/dist/{monitor-HKU57TYQ.js → monitor-CPNIUULB.js} +50 -44
  127. package/dist/{orchestrator-VDFAEFAI.js → orchestrator-J4BSH4WQ.js} +491 -1182
  128. package/dist/{panes-DN2SSFOH.js → panes-BOHAEGYC.js} +3 -3
  129. package/dist/{panes-TALGNPZT.js → panes-NXSLDQZ2.js} +5 -6
  130. package/dist/{paths-NBMFAIEZ.js → paths-VSUWNC22.js} +3 -4
  131. package/dist/{reset-EAJFFJVB.js → reset-TNWTB5LU.js} +5 -6
  132. package/dist/{resources-OVKSEFVE.js → resources-4PXNMD5G.js} +14 -14
  133. package/dist/{run-7DP7ZF2J.js → run-D6XJ34CN.js} +79 -83
  134. package/dist/{share-WML67FT3.js → share-2NWMJJEE.js} +14 -15
  135. package/dist/{skills-SG662R2K.js → skills-KR7WON5G.js} +18 -19
  136. package/dist/{skills-eval-VVZEUU46.js → skills-eval-O2ZNOLDS.js} +49 -46
  137. package/dist/{skills-inventory-I2E23GET.js → skills-inventory-ZZOUBK7O.js} +14 -14
  138. package/dist/{slash-commands-S7MBJDQK.js → slash-commands-ZXPJD64J.js} +32 -23
  139. package/dist/{steer-2LQOMCPB.js → steer-XA25PSCS.js} +3 -3
  140. package/dist/{support-CC2UJBJ6.js → support-7EMVWYG2.js} +2 -2
  141. package/dist/{targets-4QC3HIEW.js → targets-OMH2XCSN.js} +25 -27
  142. package/dist/tasks-IPAGMEIX.js +36 -0
  143. package/dist/{terminal-lease-TUHIJ6Y2.js → terminal-lease-C2J3JYRE.js} +4 -4
  144. package/dist/{tools-TFGJICCU.js → tools-EFFEAIDP.js} +5 -6
  145. package/dist/{uninstall-5PEVOE5B.js → uninstall-HALS6BLF.js} +7 -8
  146. package/dist/{upgrade-M4WXY6KN.js → upgrade-MS72RJEP.js} +14 -11
  147. package/dist/{usage-N7ZNVLEM.js → usage-NHG6MCJM.js} +60 -51
  148. package/dist/{verifiers-DJTP4XX6.js → verifiers-7AUNVXDY.js} +150 -17
  149. package/dist/{verify-RWE4PPEK.js → verify-FWYGPKMR.js} +12 -10
  150. package/dist/{web-fetch-MPARV2K7.js → web-fetch-V4FKSDAV.js} +4 -4
  151. package/dist/{wiki-generate-C7IQOXSP.js → wiki-generate-743CIGJW.js} +63 -56
  152. package/dist/{with-panes-4GCGSL7J.js → with-panes-BDQEWBRT.js} +2 -2
  153. package/dist/worker/entry.js +36 -33
  154. package/docs/README.md +3 -2
  155. package/docs/architecture/acp.md +17 -0
  156. package/docs/architecture/artifact-versions.md +1 -1
  157. package/docs/architecture/dispatch-typed-intent.md +1 -1
  158. package/docs/architecture/evidence-and-memory.md +1 -1
  159. package/docs/architecture/observability.md +7 -1
  160. package/docs/architecture/prompt-envelope-and-tools.md +15 -5
  161. package/docs/architecture/safety-model.md +10 -17
  162. package/docs/architecture/tui-design.md +1 -1
  163. package/docs/guide/built-in-agents.md +8 -8
  164. package/docs/guide/commands-and-modes.md +17 -2
  165. package/docs/guide/configuration-and-targets.md +3 -1
  166. package/docs/guide/configuration-reference.md +10 -5
  167. package/docs/guide/environment-variables.md +2 -2
  168. package/docs/guide/tool-usage.md +78 -3
  169. package/docs/history/config-knobs-audit.md +2 -2
  170. package/docs/process/development-pipeline.md +6 -1
  171. package/docs/process/git-commit-provenance.md +15 -0
  172. package/docs/process/release-cut-checklist.md +207 -0
  173. package/docs/process/scientific-validation.md +18 -17
  174. package/evals/behavioral-machinery-support.ts +1 -0
  175. package/evals/behavioral-machinery.yaml +1 -1
  176. package/package.json +1 -1
  177. package/skills/coding/coding-standards/SKILL.md +14 -4
  178. package/skills/context/context-handoff/SKILL.md +3 -3
  179. package/skills/context/context-prime/SKILL.md +3 -3
  180. package/skills/planning/architecture/SKILL.md +5 -5
  181. package/skills/planning/backlog/SKILL.md +4 -4
  182. package/skills/planning/prd/SKILL.md +4 -3
  183. package/skills/planning/product-intent/SKILL.md +8 -8
  184. package/skills/planning/tech-spec/SKILL.md +4 -4
  185. package/skills/registry.yaml +32 -32
  186. package/skills/research/arxiv-literature/SKILL.md +3 -3
  187. package/skills/research/experiment-protocol/SKILL.md +3 -3
  188. package/skills/research/scientific-debugging/SKILL.md +3 -2
  189. package/skills/research/scientific-modernization/SKILL.md +3 -3
  190. package/skills/skill-marketplace.json +16 -16
  191. package/skills/workflow/cut-it/SKILL.md +3 -4
  192. package/skills/workflow/design-council/SKILL.md +5 -10
  193. package/skills/workflow/grill-me/SKILL.md +14 -15
  194. package/skills/workflow/workflow-distiller/SKILL.md +4 -4
  195. package/src/cli/args.ts +0 -8
  196. package/src/cli/configure.ts +2 -1
  197. package/src/cli/doctor-state-size.ts +1 -12
  198. package/src/cli/doctor-validation-contract.ts +28 -0
  199. package/src/cli/doctor.ts +5 -0
  200. package/src/cli/evidence-detail.ts +1 -75
  201. package/src/cli/evidence-inventory.ts +1 -167
  202. package/src/cli/index.ts +2 -0
  203. package/src/cli/run.ts +0 -2
  204. package/src/cli/targets.ts +1 -1
  205. package/src/cli/tasks.ts +84 -0
  206. package/src/cli/upgrade.ts +10 -5
  207. package/src/cli/usage.ts +6 -0
  208. package/src/cli/verifiers.ts +147 -1
  209. package/src/cli/wiki-generate.ts +1 -0
  210. package/src/core/commit-attribution.ts +41 -1
  211. package/src/core/git-commit-attribution.ts +46 -3
  212. package/src/core/run-overrides.ts +0 -5
  213. package/src/core/skill-activation.ts +3 -0
  214. package/src/core/tool-names.ts +5 -2
  215. package/src/domains/agents/builtins/architect.md +1 -1
  216. package/src/domains/agents/builtins/coder.md +1 -1
  217. package/src/domains/agents/builtins/documenter.md +1 -1
  218. package/src/domains/agents/builtins/git-master.md +1 -1
  219. package/src/domains/agents/builtins/provenance.md +7 -7
  220. package/src/domains/agents/builtins/tester.md +1 -1
  221. package/src/domains/agents/builtins/verifier.md +2 -2
  222. package/src/domains/agents/builtins/wiki-writer.md +4 -3
  223. package/src/domains/context/extension.ts +31 -7
  224. package/src/domains/context/refresh.ts +3 -0
  225. package/src/domains/context/wiki/frontmatter.ts +5 -2
  226. package/src/domains/context/wiki/generate.ts +6 -0
  227. package/src/domains/context/wiki/prompts.ts +43 -0
  228. package/src/domains/dispatch/active-route-planner.ts +4 -0
  229. package/src/domains/dispatch/code-step.ts +11 -4
  230. package/src/domains/dispatch/contract.ts +31 -7
  231. package/src/domains/dispatch/execution-scheduler.ts +2 -0
  232. package/src/domains/dispatch/extension.ts +50 -27
  233. package/src/domains/dispatch/fleet-commit-attribution.ts +5 -0
  234. package/src/domains/dispatch/fleet-run.ts +1 -0
  235. package/src/domains/dispatch/host-verification.ts +114 -13
  236. package/src/domains/dispatch/intent.ts +28 -18
  237. package/src/domains/dispatch/orphan-recovery.ts +2 -0
  238. package/src/domains/dispatch/receipt-integrity.ts +4 -0
  239. package/src/domains/dispatch/reservation-store.ts +5 -3
  240. package/src/domains/dispatch/state.ts +15 -2
  241. package/src/domains/dispatch/types.ts +17 -2
  242. package/src/domains/eval/runners/clio-run.ts +12 -9
  243. package/src/domains/eval/runners/context-index.ts +2 -7
  244. package/src/domains/eval/runners/context-init.ts +3 -6
  245. package/src/domains/eval/runners/external-command.ts +29 -11
  246. package/src/domains/evidence/build.ts +102 -15
  247. package/src/domains/evidence/detail.ts +69 -0
  248. package/src/domains/evidence/eval.ts +13 -1
  249. package/src/domains/evidence/finish-contract-map.ts +5 -1
  250. package/src/domains/evidence/inventory.ts +167 -0
  251. package/src/domains/evidence/store.ts +16 -0
  252. package/src/domains/evidence/types.ts +12 -0
  253. package/src/domains/extensions/resources.ts +7 -0
  254. package/src/domains/middleware/marketplace-offer.ts +20 -1
  255. package/src/domains/middleware/runtime.ts +7 -3
  256. package/src/domains/mux/detect.ts +3 -6
  257. package/src/domains/observability/accountability.ts +15 -1
  258. package/src/domains/observability/contract.ts +52 -7
  259. package/src/domains/observability/evidence-index.ts +10 -0
  260. package/src/domains/observability/extension.ts +9 -5
  261. package/src/domains/observability/projection.ts +394 -45
  262. package/src/{interactive → domains/observability}/worker-progress.ts +3 -3
  263. package/src/domains/prompts/fragments/operating/contract.md +2 -0
  264. package/src/domains/prompts/fragments/wiki/page.md +8 -0
  265. package/src/domains/providers/model-discovery.ts +1 -4
  266. package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +16 -14
  267. package/src/domains/providers/runtimes/claude/claude-code.ts +9 -0
  268. package/src/domains/providers/support.ts +1 -1
  269. package/src/domains/providers/types/runtime-descriptor.ts +1 -1
  270. package/src/domains/safety/action-classifier.ts +7 -0
  271. package/src/domains/safety/default-path-policy.ts +2 -0
  272. package/src/domains/safety/finish-contract-registration.ts +29 -14
  273. package/src/domains/safety/finish-contract.ts +252 -40
  274. package/src/domains/safety/index.ts +20 -1
  275. package/src/domains/safety/policy-engine.ts +26 -6
  276. package/src/domains/safety/rigor.ts +53 -39
  277. package/src/domains/safety/validation-contract.ts +388 -0
  278. package/src/domains/session/archive-readers.ts +10 -1
  279. package/src/domains/session/decision-board.ts +101 -2
  280. package/src/domains/session/entries.ts +44 -7
  281. package/src/domains/session/extension.ts +4 -4
  282. package/src/domains/session/handoff.ts +2 -1
  283. package/src/domains/session/manager.ts +2 -3
  284. package/src/domains/session/task-board.ts +14 -1
  285. package/src/domains/session/tree/fork.ts +1 -2
  286. package/src/domains/session/tree/navigator.ts +1 -1
  287. package/src/domains/user-tasks/acceptance.ts +56 -0
  288. package/src/domains/user-tasks/active-acceptance.ts +40 -0
  289. package/src/domains/user-tasks/store.ts +34 -3
  290. package/src/engine/acp/adapter.ts +24 -6
  291. package/src/engine/acp/server.ts +21 -4
  292. package/src/engine/acp/transport.ts +53 -8
  293. package/src/engine/acp/types.ts +4 -0
  294. package/src/engine/apis/ollama-native.ts +15 -0
  295. package/src/engine/claude/subprocess-runtime.ts +107 -60
  296. package/src/engine/external-subprocess.ts +12 -4
  297. package/src/entry/orchestrator.ts +11 -2
  298. package/src/interactive/dispatch-board.ts +46 -717
  299. package/src/interactive/fleet-run-preview.ts +2 -1
  300. package/src/interactive/interactive-application.ts +3 -2
  301. package/src/interactive/interactive-presentation.ts +55 -12
  302. package/src/interactive/interactive-slash-runtime.ts +2 -1
  303. package/src/interactive/oracle.ts +5 -2
  304. package/src/interactive/overlays/fleet-run-approval.ts +3 -2
  305. package/src/interactive/overlays/message-picker.ts +2 -2
  306. package/src/interactive/overlays/settings.ts +2 -2
  307. package/src/interactive/overlays/tree-selector.ts +2 -2
  308. package/src/interactive/renderers/branch-summary.ts +1 -1
  309. package/src/interactive/slash-autocomplete.ts +4 -6
  310. package/src/interactive/slash-commands.ts +25 -39
  311. package/src/interactive/slash-spec.ts +28 -0
  312. package/src/interactive/view/artifacts.ts +2 -0
  313. package/src/interactive/worker-stream.ts +7 -3
  314. package/src/tools/bootstrap.ts +4 -0
  315. package/src/tools/builtin-tool-catalog.ts +31 -0
  316. package/src/tools/compete-worktrees.ts +7 -1
  317. package/src/tools/core-bootstrap.ts +16 -0
  318. package/src/tools/decide.ts +136 -0
  319. package/src/tools/dispatch-admission.ts +21 -0
  320. package/src/tools/dispatch-plan.ts +5 -2
  321. package/src/tools/dispatch-runner.ts +15 -1
  322. package/src/tools/dispatch-types.ts +6 -0
  323. package/src/tools/evidence.ts +96 -0
  324. package/src/tools/limitation.ts +76 -0
  325. package/src/tools/policy.ts +9 -0
  326. package/src/tools/presentation.ts +3 -0
  327. package/src/tools/registry.ts +1 -1
  328. package/src/tools/result-shaping.ts +17 -5
  329. package/src/tools/task-worktree.ts +13 -3
  330. package/src/tools/tasks.ts +10 -1
  331. package/src/tools/verify/authoring.ts +170 -83
  332. package/src/tools/verify/catalog.ts +122 -5
  333. package/src/tools/verify/index.ts +2 -1
  334. package/src/tools/verify/numeric.ts +298 -0
  335. package/src/tools/verify/perf.ts +143 -0
  336. package/src/tools/verify/scripts.ts +229 -2
  337. package/dist/chunk-7DICMOS6.js +0 -313
  338. package/dist/chunk-RVG5JXAL.js +0 -41
  339. package/dist/chunk-T56WDKA5.js +0 -183
  340. package/dist/chunk-VPKWYKEY.js +0 -169
@@ -12,6 +12,8 @@ import type {
12
12
  } from "../dispatch/index.js";
13
13
  import { type ExecutionRole, isExecutionRole, readGateDecisionArtifactsForRunIds } from "../dispatch/index.js";
14
14
  import { detectValidationCommand } from "../safety/protected-artifacts.js";
15
+ import { foldDecisionBoard } from "../session/decision-board.js";
16
+ import { type DecisionLedgerEntry, decisionRef } from "../session/entries.js";
15
17
  import {
16
18
  type AuditJsonRow,
17
19
  type BashExecutionEntry,
@@ -23,6 +25,7 @@ import {
23
25
  readSessionEntriesForId,
24
26
  type SessionEntry,
25
27
  } from "../session/index.js";
28
+ import { filterEntriesToActivePath } from "../session/tree/active-path.js";
26
29
  import { attributeEvidenceFailure } from "./failure-attribution.js";
27
30
  import { renderEvidenceFindingsMarkdown } from "./findings-markdown.js";
28
31
  import { compareCodepoints as compareStrings } from "./ordering.js";
@@ -37,6 +40,7 @@ import {
37
40
  type EvidenceAuditLinkedRow,
38
41
  type EvidenceBuildResult,
39
42
  type EvidenceCleanTraceRow,
43
+ type EvidenceDecision,
40
44
  type EvidenceFinding,
41
45
  type EvidenceGateDecisionsFile,
42
46
  type EvidenceLinkConfidence,
@@ -94,6 +98,7 @@ interface LinkedSessionEntry {
94
98
  }
95
99
 
96
100
  interface SessionLinkResult {
101
+ decisionBoards: Map<string, DecisionLedgerEntry[]>;
97
102
  entries: LinkedSessionEntry[];
98
103
  attemptedSessionIds: string[];
99
104
  missingSessionIds: string[];
@@ -163,7 +168,10 @@ export async function buildEvidence(options: BuildEvidenceOptions): Promise<Evid
163
168
  gateDecisions: gateDecisions.decisions,
164
169
  validationEvidence,
165
170
  });
166
- const findings = buildFindings(runSources, trustStatusRaw, sessionLinks, auditLinks, protectedArtifactsRaw);
171
+ const decisionLinks = resolveReceiptDecisions(runSources, sessionLinks);
172
+ const rawFindings = buildFindings(runSources, trustStatusRaw, sessionLinks, auditLinks, protectedArtifactsRaw);
173
+ for (const row of decisionLinks.findings)
174
+ rawFindings.push({ ...row, id: `finding-${String(rawFindings.length + 1).padStart(3, "0")}` });
167
175
  // Export-boundary redaction (cold path): secret-shaped values are scrubbed
168
176
  // from everything the bundle serializes: envelopes, receipts (including
169
177
  // delegation toolCallLog arguments), tool-event previews, audit rows,
@@ -171,6 +179,7 @@ export async function buildEvidence(options: BuildEvidenceOptions): Promise<Evid
171
179
  // session files are untouched; the bundle is the boundary, and the
172
180
  // overview's redactionCount keeps the bundle honest about its filtering.
173
181
  const tally = createRedactionTally();
182
+ const findings = redactSecretsDeep(rawFindings, tally);
174
183
  const redactedRunSources: EvidenceRunSource[] = runSources.map((item) => ({
175
184
  ...item,
176
185
  envelope: redactSecretsDeep(item.envelope, tally),
@@ -187,18 +196,21 @@ export async function buildEvidence(options: BuildEvidenceOptions): Promise<Evid
187
196
  };
188
197
  const protectedArtifacts = redactSecretsDeep(protectedArtifactsRaw, tally);
189
198
  const trustStatus = redactSecretsDeep(trustStatusRaw, tally);
190
- const overview = buildOverview(
191
- evidenceId,
192
- source,
193
- redactedRunSources,
194
- findings,
195
- sessionLinks,
196
- redactedAuditLinks,
197
- redactedToolEvents,
198
- protectedArtifacts,
199
- );
199
+ const overview: EvidenceOverview = {
200
+ ...buildOverview(
201
+ evidenceId,
202
+ source,
203
+ redactedRunSources,
204
+ findings,
205
+ sessionLinks,
206
+ redactedAuditLinks,
207
+ redactedToolEvents,
208
+ protectedArtifacts,
209
+ ),
210
+ decisions: redactSecretsDeep(decisionLinks.decisions, tally),
211
+ };
200
212
  const transcript = redactSecretsText(
201
- renderTranscript(overview, redactedRunSources, sessionLinks, trustStatusRaw),
213
+ renderTranscript(overview, redactedRunSources, sessionLinks, trustStatusRaw, findings),
202
214
  tally,
203
215
  );
204
216
  const finalOverview: EvidenceOverview = { ...overview, redactionCount: tally.count };
@@ -215,7 +227,17 @@ export async function buildEvidence(options: BuildEvidenceOptions): Promise<Evid
215
227
  protectedArtifacts,
216
228
  transcript,
217
229
  );
218
- return { evidenceId, directory, overview: finalOverview, findings, trustStatus };
230
+ return {
231
+ evidenceId,
232
+ directory,
233
+ overview: finalOverview,
234
+ findings,
235
+ trustStatus,
236
+ ungroundedClaims: runSources.reduce((total, source) => {
237
+ const grounding = authenticatedReceipt(source)?.validationGrounding;
238
+ return total + (grounding === undefined ? 0 : Math.max(0, grounding.claimed - grounding.grounded));
239
+ }, 0),
240
+ };
219
241
  }
220
242
 
221
243
  function buildOverview(
@@ -229,7 +251,10 @@ function buildOverview(
229
251
  protectedArtifacts: EvidenceProtectedArtifactsFile,
230
252
  ): EvidenceOverview {
231
253
  const envelopes = runSources.map((item) => item.envelope);
232
- const receipts = runSources.flatMap((item) => (item.receipt === null ? [] : [item.receipt]));
254
+ const receipts = runSources.flatMap((item) => {
255
+ const receipt = authenticatedReceipt(item);
256
+ return receipt === null ? [] : [receipt];
257
+ });
233
258
  const toolStats = receipts.flatMap((receipt) => receipt.toolStats);
234
259
  const runIds = envelopes.map((envelope) => envelope.id).sort(compareStrings);
235
260
  const sessionIds = uniqueStrings(
@@ -619,7 +644,7 @@ async function writeEvidenceFiles(
619
644
  await writeJson(join(directory, "overview.json"), overview);
620
645
  await writeFile(
621
646
  join(directory, "transcript.md"),
622
- transcript ?? renderTranscript(overview, runSources, sessionLinks, trustStatus),
647
+ transcript ?? renderTranscript(overview, runSources, sessionLinks, trustStatus, findings),
623
648
  "utf8",
624
649
  );
625
650
  await writeJsonl(join(directory, "trace.raw.jsonl"), rawTraceRows(runSources));
@@ -736,6 +761,7 @@ async function linkSessionEntries(
736
761
  const attemptedSessionIds = sourceSessionIds(source, runSources);
737
762
  const windows = attributionWindows(ledger, runSources, attemptedSessionIds);
738
763
  const result: SessionLinkResult = {
764
+ decisionBoards: new Map(),
739
765
  entries: [],
740
766
  attemptedSessionIds,
741
767
  missingSessionIds: [],
@@ -748,6 +774,7 @@ async function linkSessionEntries(
748
774
  continue;
749
775
  }
750
776
  result.readErrors.push(...read.errors);
777
+ result.decisionBoards.set(sessionId, foldDecisionBoard(filterEntriesToActivePath(read.entries, read.leafTurnId)));
751
778
  for (const entry of read.entries) {
752
779
  const link = linkSessionEntry(entry, windows);
753
780
  if (source.kind === "run" && !linkCoversRun(link, source.runId)) continue;
@@ -1280,6 +1307,7 @@ function renderTranscript(
1280
1307
  runSources: ReadonlyArray<EvidenceRunSource>,
1281
1308
  sessionLinks: SessionLinkResult,
1282
1309
  trustStatus: EvidenceTrustStatusFile,
1310
+ findings: ReadonlyArray<EvidenceFinding>,
1283
1311
  ): string {
1284
1312
  const trustByRun = new Map(trustStatus.runs.map((entry) => [entry.runId, entry.status]));
1285
1313
  const lines = [
@@ -1306,6 +1334,21 @@ function renderTranscript(
1306
1334
  }
1307
1335
  }
1308
1336
  }
1337
+ const decisionFindings = findings.filter(
1338
+ (row) => row.tag === "context-provenance" && row.message.startsWith("Decision ref "),
1339
+ );
1340
+ if (decisionFindings.length > 0) {
1341
+ lines.push("", "## Decision provenance");
1342
+ for (const row of decisionFindings) lines.push(`- [${row.severity}] ${row.runId}: ${row.message}`);
1343
+ for (const decision of overview.decisions ?? []) {
1344
+ lines.push(
1345
+ `\n### ${decision.ref} (run ${decision.runId}, session ${decision.sessionId})`,
1346
+ "```json",
1347
+ JSON.stringify(decision.record, null, 2),
1348
+ "```",
1349
+ );
1350
+ }
1351
+ }
1309
1352
  if (sessionLinks.entries.length > 0) {
1310
1353
  lines.push("", "## Linked Session Transcript");
1311
1354
  for (const linked of sessionLinks.entries) {
@@ -1577,6 +1620,7 @@ function parseRunEnvelope(value: unknown, source: string): RunEnvelope {
1577
1620
  // tampered. The validated reads below still gate the fields evidence uses.
1578
1621
  return {
1579
1622
  ...(value as Partial<RunEnvelope>),
1623
+ version: 1,
1580
1624
  id: readString(value, source, "id"),
1581
1625
  agentId: readString(value, source, "agentId"),
1582
1626
  executionRole: readExecutionRole(value, source),
@@ -1874,3 +1918,46 @@ function sanitizeEvidenceId(value: string): string {
1874
1918
  const clean = value.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
1875
1919
  return clean.length === 0 ? "unknown" : clean;
1876
1920
  }
1921
+
1922
+ /** Receipt refs authenticate the link, while the session ledger supplies the recorded argument. */
1923
+ function resolveReceiptDecisions(
1924
+ runSources: ReadonlyArray<EvidenceRunSource>,
1925
+ sessions: SessionLinkResult,
1926
+ ): {
1927
+ decisions: EvidenceDecision[];
1928
+ findings: EvidenceFinding[];
1929
+ } {
1930
+ const decisions: EvidenceDecision[] = [];
1931
+ const findings: EvidenceFinding[] = [];
1932
+ for (const source of runSources) {
1933
+ const receipt = authenticatedReceipt(source);
1934
+ if (!receipt?.decisionRefs?.length) continue;
1935
+ const sessionId = receipt.sessionId;
1936
+ const board = sessionId === null ? [] : (sessions.decisionBoards.get(sessionId) ?? []);
1937
+ const records = new Map(
1938
+ board.flatMap((entry) =>
1939
+ entry.decisions.map(
1940
+ (record) =>
1941
+ [
1942
+ decisionRef(entry.interviewId, record.key),
1943
+ { ...record, source: record.source ?? (entry.origin === "agent" ? ("agent" as const) : ("operator" as const)) },
1944
+ ] as const,
1945
+ ),
1946
+ ),
1947
+ );
1948
+ for (const ref of new Set(receipt.decisionRefs)) {
1949
+ const record = records.get(ref);
1950
+ if (record && sessionId !== null) decisions.push({ runId: receipt.runId, sessionId, ref, record });
1951
+ findings.push(
1952
+ finding(
1953
+ findings.length,
1954
+ record ? "info" : "warn",
1955
+ "context-provenance",
1956
+ receipt.runId,
1957
+ `Decision ref ${ref} ${record ? "resolved" : "does not resolve"} on session ${sessionId ?? "(unlinked)"} active path`,
1958
+ ),
1959
+ );
1960
+ }
1961
+ }
1962
+ return { decisions, findings };
1963
+ }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Fixed machine-readable projection of one evidence bundle's trust record.
3
+ *
4
+ * `evidence inspect <id>` prints an operator record that quotes the task text,
5
+ * the bundle's file list, and per-finding prose. This is the same bundle read
6
+ * down to the one thing a GUI can carry safely and usefully: which runs the
7
+ * bundle covers, what verdict each run earned, and which axis produced it.
8
+ *
9
+ * Every value here comes from a closed vocabulary. The axis names, the axis
10
+ * states, and the verdicts are all enumerations the harness owns, so there is
11
+ * no free-form text on this surface at all, which is what lets it answer the
12
+ * question the inventory raises without reopening the boundary the inventory
13
+ * closed.
14
+ *
15
+ * Unlike the other fixed reads this one takes an identifier, because an
16
+ * operator names the bundle. The GUI host may only pass back an id it served
17
+ * inside its current bounded window; see `apps/workbench/artifact-allowlist.ts`.
18
+ */
19
+
20
+ import { clioDataDir } from "../../core/xdg.js";
21
+ import { inspectEvidence, TRUST_STATUS_AXES, type TrustStatusAxis, type TrustVerdict, trustVerdict } from "./index.js";
22
+
23
+ export const EVIDENCE_DETAIL_MAX_RUNS = 16;
24
+
25
+ export interface EvidenceDetailRun {
26
+ readonly runId: string;
27
+ readonly verdict: TrustVerdict;
28
+ /** Every axis, always all six, so an absent axis is stated rather than missing. */
29
+ readonly axes: Readonly<Record<TrustStatusAxis, string>>;
30
+ }
31
+
32
+ export interface EvidenceDetailSnapshot {
33
+ readonly version: 1;
34
+ readonly generatedAt: string;
35
+ readonly evidenceId: string;
36
+ readonly sourceKind: "run" | "session" | "eval";
37
+ /** False when the bundle predates the canonical trust projection. */
38
+ readonly canonical: boolean;
39
+ readonly runs: readonly EvidenceDetailRun[];
40
+ readonly runsTruncated: boolean;
41
+ }
42
+
43
+ export async function evidenceDetailSnapshot(
44
+ evidenceId: string,
45
+ now: () => number = Date.now,
46
+ dataDir: string = clioDataDir(),
47
+ ): Promise<EvidenceDetailSnapshot> {
48
+ const inspected = await inspectEvidence(dataDir, evidenceId);
49
+ const all = inspected.trustStatus.runs;
50
+ const window = all.slice(0, EVIDENCE_DETAIL_MAX_RUNS);
51
+ return {
52
+ version: 1,
53
+ generatedAt: new Date(now()).toISOString(),
54
+ evidenceId: inspected.overview.evidenceId,
55
+ sourceKind: inspected.overview.source.kind,
56
+ canonical: inspected.trustStatus.projection === "canonical",
57
+ runs: window.map(
58
+ (run): EvidenceDetailRun => ({
59
+ runId: run.runId,
60
+ verdict: trustVerdict(run.status),
61
+ axes: Object.fromEntries(TRUST_STATUS_AXES.map((axis) => [axis, run.status[axis].state])) as Record<
62
+ TrustStatusAxis,
63
+ string
64
+ >,
65
+ }),
66
+ ),
67
+ runsTruncated: all.length > window.length,
68
+ };
69
+ }
@@ -9,6 +9,7 @@ import { renderEvidenceFindingsMarkdown } from "./findings-markdown.js";
9
9
  import { compareCodepoints as compareStrings } from "./ordering.js";
10
10
  import { buildEvidenceTrustStatusFile } from "./run-trust.js";
11
11
  import { evidenceDirectory, findingsFile } from "./store.js";
12
+ import { inspectRunReceiptTrustStatus } from "./trust-status.js";
12
13
  import {
13
14
  EVIDENCE_VERSION,
14
15
  type EvidenceAuditLinkedRow,
@@ -107,7 +108,18 @@ export async function buildEvalEvidence(options: BuildEvalEvidenceOptions): Prom
107
108
  gateDecisions,
108
109
  trustStatus,
109
110
  );
110
- return { evidenceId, directory, overview, findings, trustStatus };
111
+ return {
112
+ evidenceId,
113
+ directory,
114
+ overview,
115
+ findings,
116
+ trustStatus,
117
+ ungroundedClaims: linkedRuns.runSources.reduce((total, source) => {
118
+ if (!inspectRunReceiptTrustStatus(source.receipt, source.envelope).integrity.ok) return total;
119
+ const grounding = source.receipt?.validationGrounding;
120
+ return total + (grounding === undefined ? 0 : Math.max(0, grounding.claimed - grounding.grounded));
121
+ }, 0),
122
+ };
111
123
  }
112
124
 
113
125
  export function evalEvidenceId(evalId: string): string {
@@ -7,7 +7,7 @@ import type { EvidenceTag } from "./types.js";
7
7
  *
8
8
  * The forensic layer (`evidence/build.ts`) speaks the canonical 23-tag
9
9
  * `EVIDENCE_TAGS` vocabulary over durable artifacts. The live layer
10
- * (`safety/finish-contract.ts`) speaks a 3-kind in-loop vocabulary
10
+ * (`safety/finish-contract.ts`) speaks a 4-kind in-loop vocabulary
11
11
  * (`FinishContractEvidenceKind`) over the last ~80 session entries. They are
12
12
  * the same accountability concept observed at two depths.
13
13
  *
@@ -29,11 +29,15 @@ import type { EvidenceTag } from "./types.js";
29
29
  * - dispatch_receipt: a passed dispatch receipt, whose forensic concerns are
30
30
  * `receipt-integrity` (the receipt verifies) and `session-linked` (the run
31
31
  * is linked to its session).
32
+ * - limitation: a successful `limitation` tool receipt, which the forensic
33
+ * layer records as the `completion-evidence` info row for a run that
34
+ * finished limited instead of evidenced.
32
35
  */
33
36
  export const FINISH_CONTRACT_EVIDENCE_TAGS: Record<FinishContractEvidenceKind, readonly EvidenceTag[]> = {
34
37
  validation_command: ["no-validation", "proxy-validation"],
35
38
  protected_artifact: ["protected-artifact"],
36
39
  dispatch_receipt: ["receipt-integrity", "session-linked"],
40
+ limitation: ["completion-evidence"],
37
41
  } as const;
38
42
 
39
43
  /** The canonical tags a single live finish-contract kind projects onto. */
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Fixed machine-readable projection of recent evidence artifacts.
3
+ *
4
+ * `evidence list` is an operator table and `evidence inspect <id>` needs an id,
5
+ * so neither is a transport a GUI host can invoke blind. This command accepts
6
+ * no identifier, path, or limit, selects a bounded newest-first window itself,
7
+ * and emits provenance, tags, totals, and a trust verdict.
8
+ *
9
+ * An overview carries the working directories the runs executed in, the task
10
+ * text the operator typed, and the file names inside the bundle. None of that
11
+ * appears here. What does is the shape of the artifact and how far it can be
12
+ * trusted, which is what an operator picks a bundle by.
13
+ */
14
+
15
+ import { clioDataDir } from "../../core/xdg.js";
16
+ import { truncateToWidth } from "../../engine/tui-primitives.js";
17
+ import { sanitizeCallTargetText } from "../safety/call-target.js";
18
+ import {
19
+ EVIDENCE_TAGS,
20
+ type EvidenceOverview,
21
+ type EvidenceTag,
22
+ listEvidenceOverviews,
23
+ loadEvidenceTrustStatus,
24
+ type TrustVerdict,
25
+ trustVerdict,
26
+ } from "./index.js";
27
+
28
+ export const EVIDENCE_INVENTORY_MAX_ARTIFACTS = 12;
29
+ export const EVIDENCE_INVENTORY_MAX_IDS = 8;
30
+
31
+ const IDENTITY_WIDTH = 128;
32
+
33
+ /**
34
+ * Worst verdict first.
35
+ *
36
+ * An artifact covering several runs is only as trustworthy as its weakest run,
37
+ * so the fold takes the worst rather than the newest or the most common. A
38
+ * `compromised` run inside an otherwise clean bundle is the fact the operator
39
+ * needs, and averaging it away would be the one summary worth not printing.
40
+ */
41
+ const VERDICT_SEVERITY: ReadonlyArray<TrustVerdict> = ["compromised", "unverified", "unknown", "grounded", "reviewed"];
42
+
43
+ export interface EvidenceInventoryArtifact {
44
+ readonly evidenceId: string;
45
+ readonly sourceKind: "run" | "session" | "eval";
46
+ readonly generatedAt: string;
47
+ readonly startedAt: string | null;
48
+ readonly endedAt: string | null;
49
+ readonly runIds: readonly string[];
50
+ readonly runIdsTruncated: boolean;
51
+ readonly agentIds: readonly string[];
52
+ readonly statuses: readonly string[];
53
+ readonly tags: readonly EvidenceTag[];
54
+ readonly totals: Readonly<{
55
+ runs: number;
56
+ receipts: number;
57
+ toolCalls: number;
58
+ toolErrors: number;
59
+ blockedToolCalls: number;
60
+ protectedArtifacts: number;
61
+ tokens: number;
62
+ costUsd: number;
63
+ wallTimeMs: number;
64
+ }>;
65
+ /** Secret-shaped values the builder replaced across the bundle's exports. */
66
+ readonly redactionCount: number;
67
+ readonly trust: Readonly<{
68
+ verdict: TrustVerdict;
69
+ /** Runs whose canonical trust status the bundle actually recorded. */
70
+ runsCovered: number;
71
+ /** True when the bundle predates the canonical trust projection. */
72
+ historical: boolean;
73
+ }>;
74
+ }
75
+
76
+ export interface EvidenceInventorySnapshot {
77
+ readonly version: 1;
78
+ readonly generatedAt: string;
79
+ readonly artifacts: readonly EvidenceInventoryArtifact[];
80
+ readonly truncated: boolean;
81
+ }
82
+
83
+ function bounded(value: string, width: number): string {
84
+ const sanitized = sanitizeCallTargetText(value);
85
+ if (sanitized.length === 0) return "unavailable";
86
+ return sanitizeCallTargetText(truncateToWidth(sanitized, width, "…", false));
87
+ }
88
+
89
+ /** Distinct, sanitized, bounded, in first-seen order. */
90
+ function identities(values: ReadonlyArray<string>): string[] {
91
+ const seen: string[] = [];
92
+ for (const value of values) {
93
+ const text = bounded(value, IDENTITY_WIDTH);
94
+ if (!seen.includes(text)) seen.push(text);
95
+ if (seen.length >= EVIDENCE_INVENTORY_MAX_IDS) break;
96
+ }
97
+ return seen;
98
+ }
99
+
100
+ function tally(value: number | undefined): number {
101
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.trunc(value) : 0;
102
+ }
103
+
104
+ function amount(value: number | undefined): number {
105
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : 0;
106
+ }
107
+
108
+ /** Newest generation first. An unparseable stamp sorts oldest rather than throwing. */
109
+ function byNewest(a: EvidenceOverview, b: EvidenceOverview): number {
110
+ return (Date.parse(b.generatedAt) || 0) - (Date.parse(a.generatedAt) || 0);
111
+ }
112
+
113
+ export async function evidenceInventorySnapshot(
114
+ now: () => number = Date.now,
115
+ dataDir: string = clioDataDir(),
116
+ ): Promise<EvidenceInventorySnapshot> {
117
+ const all = (await listEvidenceOverviews(dataDir)).sort(byNewest);
118
+ const window = all.slice(0, EVIDENCE_INVENTORY_MAX_ARTIFACTS);
119
+ const artifacts: EvidenceInventoryArtifact[] = [];
120
+ for (const overview of window) {
121
+ // One unreadable trust file costs that artifact its verdict, never the
122
+ // whole inventory: the bundle itself is still the thing being listed.
123
+ let verdict: TrustVerdict = "unknown";
124
+ let runsCovered = 0;
125
+ let historical = true;
126
+ try {
127
+ const status = await loadEvidenceTrustStatus(dataDir, overview.evidenceId);
128
+ historical = status.projection !== "canonical";
129
+ runsCovered = status.runs.length;
130
+ const verdicts = status.runs.map((run) => trustVerdict(run.status));
131
+ verdict = VERDICT_SEVERITY.find((candidate) => verdicts.includes(candidate)) ?? "unknown";
132
+ } catch {
133
+ verdict = "unknown";
134
+ }
135
+ artifacts.push({
136
+ evidenceId: bounded(overview.evidenceId, IDENTITY_WIDTH),
137
+ sourceKind: overview.source.kind,
138
+ generatedAt: overview.generatedAt,
139
+ startedAt: overview.startedAt,
140
+ endedAt: overview.endedAt,
141
+ runIds: identities(overview.runIds),
142
+ runIdsTruncated: overview.runIds.length > EVIDENCE_INVENTORY_MAX_IDS,
143
+ agentIds: identities(overview.agentIds),
144
+ statuses: identities(overview.statuses),
145
+ tags: overview.tags.filter((tag) => EVIDENCE_TAGS.includes(tag)),
146
+ totals: {
147
+ runs: tally(overview.totals.runs),
148
+ receipts: tally(overview.totals.receipts),
149
+ toolCalls: tally(overview.totals.toolCalls),
150
+ toolErrors: tally(overview.totals.toolErrors),
151
+ blockedToolCalls: tally(overview.totals.blockedToolCalls),
152
+ protectedArtifacts: tally(overview.totals.protectedArtifacts),
153
+ tokens: tally(overview.totals.tokens),
154
+ costUsd: amount(overview.totals.costUsd),
155
+ wallTimeMs: tally(overview.totals.wallTimeMs),
156
+ },
157
+ redactionCount: tally(overview.redactionCount),
158
+ trust: { verdict, runsCovered, historical },
159
+ });
160
+ }
161
+ return {
162
+ version: 1,
163
+ generatedAt: new Date(now()).toISOString(),
164
+ artifacts,
165
+ truncated: all.length > window.length,
166
+ };
167
+ }
@@ -2,6 +2,7 @@ import { readdir, readFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
3
  import { assertSafeId } from "../../core/safe-id.js";
4
4
  import { type GateDecisionArtifact, verifyGateDecisionArtifact } from "../dispatch/index.js";
5
+ import { isDecisionRecord } from "../session/entries.js";
5
6
  import { compareCodepoints as compareStrings } from "./ordering.js";
6
7
  import { hasRunProvenance, type RunProvenanceView, runProvenanceFromUnknown } from "./provenance.js";
7
8
  import { normalizeTrustStatus } from "./trust-status.js";
@@ -230,6 +231,7 @@ function parseOverview(value: unknown, source: string): EvidenceOverview {
230
231
  tags,
231
232
  files,
232
233
  ...(redactionCount === undefined ? {} : { redactionCount }),
234
+ ...(value.decisions === undefined ? {} : { decisions: readDecisions(value.decisions, `${source}.decisions`) }),
233
235
  };
234
236
  }
235
237
 
@@ -335,3 +337,17 @@ function isRecord(value: unknown): value is Record<string, unknown> {
335
337
  export function findingsFile(evidenceId: string, findings: EvidenceFinding[]): EvidenceFindingsFile {
336
338
  return { version: 1, evidenceId, findings };
337
339
  }
340
+
341
+ function readDecisions(value: unknown, source: string): NonNullable<EvidenceOverview["decisions"]> {
342
+ if (!Array.isArray(value)) throw new Error(`${source}: expected array`);
343
+ return value.map((entry: unknown, index) => {
344
+ const path = `${source}[${index}]`;
345
+ if (!isRecord(entry) || !isDecisionRecord(entry.record)) throw new Error(`${path}: expected recorded decision`);
346
+ return {
347
+ runId: readString(entry, path, "runId"),
348
+ sessionId: readString(entry, path, "sessionId"),
349
+ ref: readString(entry, path, "ref"),
350
+ record: entry.record,
351
+ };
352
+ });
353
+ }
@@ -2,6 +2,7 @@ import type { GateDecisionArtifact, RunEnvelope, RunReceipt, ToolCallStat } from
2
2
  import type { RunPersonaOverride, RunPipelineProvenance, RunReceiptAutonomyEnforcement } from "../dispatch/types.js";
3
3
  import type { EvalCommandPhase, EvalFailureClass, EvalRunRecord } from "../eval/index.js";
4
4
  import type { ProtectedArtifact } from "../safety/protected-artifacts.js";
5
+ import type { DecisionRecord } from "../session/entries.js";
5
6
  import type { RunEscalationCounts } from "./provenance.js";
6
7
  import type { CanonicalTrustStatus } from "./trust-status.js";
7
8
 
@@ -81,7 +82,16 @@ export interface EvidenceTotals {
81
82
  wallTimeMs: number;
82
83
  }
83
84
 
85
+ export interface EvidenceDecision {
86
+ runId: string;
87
+ sessionId: string;
88
+ ref: string;
89
+ record: DecisionRecord;
90
+ }
91
+
84
92
  export interface EvidenceOverview {
93
+ /** Recorded arguments resolved from authenticated receipts on the linked active session path. */
94
+ decisions?: EvidenceDecision[];
85
95
  version: 1;
86
96
  evidenceId: string;
87
97
  source: EvidenceSource;
@@ -137,6 +147,8 @@ export interface EvidenceBuildResult {
137
147
  overview: EvidenceOverview;
138
148
  findings: EvidenceFinding[];
139
149
  trustStatus: EvidenceTrustStatusFile;
150
+ /** Total claims without matching commands, from integrity-verified receipts only. */
151
+ ungroundedClaims: number;
140
152
  }
141
153
 
142
154
  export interface EvidenceInspectable {
@@ -22,6 +22,13 @@ export function extensionSnapshotFor(cwd = process.cwd()): ExtensionSnapshot {
22
22
  return buildExtensionSnapshot({ cwd, generation: 0 });
23
23
  }
24
24
 
25
+ /**
26
+ * The canonical accessor for the enabled roots of one extension resource
27
+ * kind. The agent registry, fleet contract, skill and common resource
28
+ * loaders, and the extensions contract all read through it, so each of them
29
+ * sees the committed snapshot for the booted cwd or the ephemeral
30
+ * generation-0 build otherwise. Returns a fresh array the caller may mutate.
31
+ */
25
32
  export function enabledExtensionResourceRoots(
26
33
  kind: ExtensionResourceKind,
27
34
  cwd = process.cwd(),
@@ -53,6 +53,8 @@ export interface MarketplaceOfferInstallResult {
53
53
  }
54
54
 
55
55
  export interface MarketplaceOfferDeps {
56
+ /** Whether the session can render ask_user. Defaults to interactive offers. */
57
+ interactive?: boolean;
56
58
  /** Installed skill names the matcher must exclude. */
57
59
  listInstalledSkillNames(): ReadonlyArray<string>;
58
60
  /** The local marketplace lookup (catalog + index); already local-only. */
@@ -80,10 +82,18 @@ export function offerBindingTag(offerTag: string): string {
80
82
  return `[clio-install:${offerTag}]`;
81
83
  }
82
84
 
85
+ function boundedDescription(text: string): string {
86
+ return text
87
+ .replace(/\[[^[\]]*\]/gu, " ")
88
+ .replace(/\s+/gu, " ")
89
+ .trim()
90
+ .slice(0, 200);
91
+ }
92
+
83
93
  export function marketplaceOfferReminder(entry: MarketplaceSkill, offerTag: string): string {
84
94
  return (
85
95
  `[Marketplace] This request may need expertise no installed skill covers. The local marketplace has ` +
86
- `"${entry.name}" (not installed): ${entry.description} ` +
96
+ `"${entry.name}" (not installed): ${boundedDescription(entry.description)} ` +
87
97
  `First check the installed side with context(scope="skills"); if ${entry.name} is genuinely the right fit ` +
88
98
  `and nothing installed serves, ask the operator with ask_user (mode=single_question, header "Install skill") ` +
89
99
  `whether to install ${entry.name}, offering exactly these options in this order: ` +
@@ -299,6 +309,15 @@ export function createMarketplaceOfferRegistration(deps: MarketplaceOfferDeps):
299
309
  const match = bestMatch(input.text ?? "");
300
310
  if (!match) return NO_EFFECTS;
301
311
  offeredNames.add(match.entry.name);
312
+ if (deps.interactive === false) {
313
+ return [
314
+ {
315
+ kind: "inject_reminder",
316
+ severity: "info",
317
+ message: `[Marketplace] Skill "${match.entry.name}" matches this request; install with clio-coder skills install ${match.entry.name}.`,
318
+ },
319
+ ];
320
+ }
302
321
  const tag = newOfferTag();
303
322
  pendingOffer = { entry: match.entry, tag };
304
323
  return [{ kind: "inject_reminder", severity: "info", message: marketplaceOfferReminder(match.entry, tag) }];
@@ -110,9 +110,13 @@ export type MiddlewareDiagnostic =
110
110
  export type MiddlewareDiagnosticSink = (diagnostic: MiddlewareDiagnostic) => void;
111
111
 
112
112
  /**
113
- * Default diagnostic sink. stderr-only for now; once the typed bus lands a
114
- * `middleware.hookFailed` channel, the composition root supplies a sink that
115
- * also emits there.
113
+ * Default diagnostic sink, and the one the domain loader constructs the
114
+ * bundle with. It writes to stderr only. The composition root
115
+ * (src/entry/orchestrator.ts) replaces it through setDiagnosticSink with a
116
+ * sink that publishes every diagnostic on the typed bus as
117
+ * `middleware.hookFailed`, which the interactive warn notice consumes, and
118
+ * that still calls this writer for non-interactive runs, which have no
119
+ * notice subscriber.
116
120
  */
117
121
  export function writeMiddlewareDiagnosticToStderr(diagnostic: MiddlewareDiagnostic): void {
118
122
  if (diagnostic.kind === "hook_failed") {
@@ -126,12 +126,9 @@ export async function detectMux(options: DetectMuxOptions = {}): Promise<MuxDete
126
126
  return { detection: none("panes are turned off"), client: null };
127
127
  }
128
128
  if (enabled === "embedded") {
129
- // Embedded mode (Clio owning the pane host) is not implemented yet. An
130
- // operator who picked it wanted panes, so the rung degrades to guest
131
- // detection instead of refusing everything; the notice below says which
132
- // mode actually runs. When the guest ladder also fails, that failure is
133
- // reported on its own terms.
134
- log("info", "interface.panes.enabled=embedded is not implemented yet; detecting a guest pane host instead");
129
+ const reason = "embedded pane hosting is not implemented; use auto or guest";
130
+ log("warning", reason);
131
+ return { detection: none(reason, [], true), client: null };
135
132
  }
136
133
  if (env.HERDR_ENV !== "1") {
137
134
  return { detection: none("HERDR_ENV is not 1, so Clio is not running inside a pane host"), client: null };