@iowarp/clio-coder 0.3.6 → 0.3.8

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 (323) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/README.md +22 -6
  3. package/dist/{acp-2BEHC4DL.js → acp-U67UHUK2.js} +14 -14
  4. package/dist/{agents-LNNFTM53.js → agents-YU6SGALZ.js} +42 -35
  5. package/dist/assets/codewiki.json +1 -1
  6. package/dist/{auth-KXXFI2VS.js → auth-5ZPJOIVG.js} +32 -24
  7. package/dist/builtins-C6JMZVV6.js +17 -0
  8. package/dist/{chunk-E25LMLRW.js → chunk-26LEYJZH.js} +2 -2
  9. package/dist/{chunk-TSHXZTOQ.js → chunk-2HEJ2F35.js} +5 -5
  10. package/dist/{chunk-PBTHKCPN.js → chunk-2HFZQUHL.js} +7 -7
  11. package/dist/{chunk-FO5ZOVUY.js → chunk-3BINW3FP.js} +5 -5
  12. package/dist/{chunk-4OC57DA6.js → chunk-4DGYLA73.js} +53 -2
  13. package/dist/{chunk-CKXWIANG.js → chunk-4SPRNWDE.js} +18 -16
  14. package/dist/{chunk-E2ER4LJF.js → chunk-5C3AQNDW.js} +25 -1
  15. package/dist/{chunk-XF5N4U5A.js → chunk-5DHKRSMQ.js} +9 -8
  16. package/dist/{chunk-43AOLP7E.js → chunk-5FR74PWO.js} +2 -1
  17. package/dist/{chunk-EKY57CSP.js → chunk-5H3GB5BO.js} +68 -772
  18. package/dist/{chunk-6XXKFVSN.js → chunk-5Q2VVUKB.js} +4 -4
  19. package/dist/{chunk-DJVECN66.js → chunk-7RFXX52T.js} +295 -3705
  20. package/dist/{chunk-ZXF4XRKW.js → chunk-7RGZWPB6.js} +158 -8
  21. package/dist/{chunk-FYYLNIL5.js → chunk-A2NJGIB3.js} +2 -2
  22. package/dist/{chunk-XXQNGV4M.js → chunk-A3WNZD3P.js} +548 -72
  23. package/dist/{chunk-VEZEGCGW.js → chunk-B5CSFE7B.js} +23 -21
  24. package/dist/{chunk-2SFS6XQE.js → chunk-DGSYXYMX.js} +3 -2
  25. package/dist/chunk-DR52UMZW.js +21 -0
  26. package/dist/{chunk-ZWLZP4ZT.js → chunk-DYIM5TJT.js} +98 -12
  27. package/dist/{chunk-QKMUKYO7.js → chunk-E77JEWSD.js} +270 -125
  28. package/dist/{chunk-LYF7OHWH.js → chunk-EMYUUSFG.js} +12 -467
  29. package/dist/{chunk-4VP4KH3K.js → chunk-EQ63NRB7.js} +8 -8
  30. package/dist/chunk-FBVTI2TJ.js +518 -0
  31. package/dist/{chunk-R46L2BIR.js → chunk-FHJEP5SW.js} +19 -25
  32. package/dist/{chunk-WR67VIZY.js → chunk-GN57SG4G.js} +66 -8
  33. package/dist/{chunk-RD5U66HV.js → chunk-GPIEI3LY.js} +9 -9
  34. package/dist/{chunk-PCZJO5TI.js → chunk-GU2UIAFZ.js} +13 -178
  35. package/dist/chunk-GWS3VEIW.js +195 -0
  36. package/dist/chunk-H7IXIC72.js +103 -0
  37. package/dist/{chunk-3BPUFZDL.js → chunk-HLE42MG7.js} +3 -3
  38. package/dist/{chunk-24I7BN55.js → chunk-IFBNV6H6.js} +3 -3
  39. package/dist/{chunk-QNQHSOLF.js → chunk-IGWKHNIQ.js} +114 -55
  40. package/dist/chunk-IIZWH4XA.js +172 -0
  41. package/dist/{chunk-AD2SYQYC.js → chunk-IJ7RPIYJ.js} +124 -6
  42. package/dist/chunk-J3YUBZWY.js +382 -0
  43. package/dist/{chunk-5JGRAMKL.js → chunk-JOZYP4GM.js} +8 -6
  44. package/dist/{chunk-OH3TOQTB.js → chunk-K4XHGFR5.js} +751 -15
  45. package/dist/{chunk-EYPA3EGJ.js → chunk-KTYTFRMB.js} +178 -14
  46. package/dist/chunk-LU7P4LHA.js +33 -0
  47. package/dist/chunk-ME6CCNFO.js +108 -0
  48. package/dist/chunk-MXKJU4JB.js +1100 -0
  49. package/dist/{chunk-RY3LY4J5.js → chunk-N22QMJKY.js} +21 -18
  50. package/dist/chunk-NMPKI6XL.js +3006 -0
  51. package/dist/chunk-NUGM5KR6.js +165 -0
  52. package/dist/{chunk-22NAGB7X.js → chunk-P43ETTHK.js} +5 -94
  53. package/dist/{chunk-NILBFAPG.js → chunk-PMDBGQSJ.js} +2 -2
  54. package/dist/chunk-PT7HYKEM.js +165 -0
  55. package/dist/chunk-RVG5JXAL.js +41 -0
  56. package/dist/{chunk-GEYXPTRF.js → chunk-RWSI4YD7.js} +2 -2
  57. package/dist/{chunk-4BPJXDWC.js → chunk-TANS5ZJS.js} +35 -19
  58. package/dist/{verifiers-NCBTHHN2.js → chunk-TB5666IT.js} +67 -324
  59. package/dist/{chunk-QM3F2GKX.js → chunk-TLQJPP24.js} +7927 -8088
  60. package/dist/{chunk-G7MUEIGA.js → chunk-TT36MB5S.js} +2 -1
  61. package/dist/chunk-TTHACPOM.js +961 -0
  62. package/dist/{chunk-6US73PDB.js → chunk-TYPGUK6W.js} +7 -7
  63. package/dist/{chunk-MFFY33HR.js → chunk-U6MBIEMB.js} +554 -209
  64. package/dist/chunk-VAWNZU7Z.js +242 -0
  65. package/dist/{chunk-IR4CFBFN.js → chunk-VCBR6CU7.js} +12 -12
  66. package/dist/{chunk-WHJYKASB.js → chunk-VHN4MY6O.js} +2 -2
  67. package/dist/{chunk-XYDYPRZI.js → chunk-VWZOAB7K.js} +10 -10
  68. package/dist/{chunk-ZRGEBJ4T.js → chunk-WLFILSD5.js} +48 -48
  69. package/dist/{chunk-K7T3E2SR.js → chunk-WNIJTQQK.js} +12 -11
  70. package/dist/{chunk-CYQKWTG3.js → chunk-WSB3FPX7.js} +68 -20
  71. package/dist/{chunk-KHSFENX2.js → chunk-WWCZ5F23.js} +116 -14
  72. package/dist/{chunk-XE2VEJHX.js → chunk-WXY7KU3G.js} +2 -2
  73. package/dist/{chunk-PPAMZ32Z.js → chunk-XK56QHLX.js} +6 -1
  74. package/dist/{chunk-KOHPCX4K.js → chunk-XWSF374K.js} +5 -5
  75. package/dist/{chunk-CJUB2JJ2.js → chunk-YS5VLNH5.js} +10 -10
  76. package/dist/{chunk-ZZMN5OM4.js → chunk-ZNLWCMVZ.js} +2 -2
  77. package/dist/{chunk-WHGPSPT5.js → chunk-ZVJ5BLO2.js} +2 -2
  78. package/dist/cli/index.js +33 -31
  79. package/dist/{clio-M2KGYUFZ.js → clio-QVTYJ57A.js} +10 -10
  80. package/dist/{code-nav-GQNL7XA6.js → code-nav-FGGFIE7L.js} +5 -5
  81. package/dist/codewiki/build-worker.js +4 -4
  82. package/dist/{components-5TTYYX6G.js → components-ZFA3SAER.js} +9 -9
  83. package/dist/{config-XUUYQIWO.js → config-LW5IJFQN.js} +65 -55
  84. package/dist/{configure-IHJ7YOMV.js → configure-7XIZCOU4.js} +29 -24
  85. package/dist/{context-75MIWW3U.js → context-L3WL3X7K.js} +54 -43
  86. package/dist/{context-ZQ7SIFJV.js → context-N52ZA626.js} +30 -14
  87. package/dist/{context-74JLXAWD.js → context-Y6Y7QPR6.js} +12 -12
  88. package/dist/{context-clear-GYKWNUML.js → context-clear-MBQRLSDQ.js} +54 -43
  89. package/dist/{context-index-SSR5ECNE.js → context-index-HVMFQHK3.js} +5 -5
  90. package/dist/{context-working-set-UX5KEP4J.js → context-working-set-GS6DSO7F.js} +18 -18
  91. package/dist/{dispatch-runner-GIJBHNFL.js → dispatch-runner-22ZCNOM3.js} +367 -79
  92. package/dist/{docs-6FZSCG5B.js → docs-7LQ23DLM.js} +9 -9
  93. package/dist/{doctor-SVJ5BZCW.js → doctor-M7YEDGAE.js} +27 -23
  94. package/dist/{eval-CG6LLBLD.js → eval-BEC2WHDA.js} +73 -20
  95. package/dist/{evidence-ZYFIEN42.js → evidence-REJUMSKM.js} +70 -59
  96. package/dist/{evolve-QGEXEMDW.js → evolve-PY5ZBA5K.js} +50 -39
  97. package/dist/{extensions-ADGNCJJD.js → extensions-HVKU65YU.js} +7 -7
  98. package/dist/{fleet-S5R4ZOQY.js → fleet-7WZEWRFA.js} +236 -377
  99. package/dist/fleet-commands-UVHWM76J.js +70 -0
  100. package/dist/fleet-graph-6ULH7PES.js +125 -0
  101. package/dist/fleet-new-RDVJLHHH.js +48 -0
  102. package/dist/{fleet-preflight-BHSNPBMH.js → fleet-preflight-J53T6CCE.js} +5 -5
  103. package/dist/fleet-validate-72PC4SLA.js +79 -0
  104. package/dist/{init-5DRU55YR.js → init-OG3TPGQG.js} +69 -57
  105. package/dist/library-CNTMPLRF.js +217 -0
  106. package/dist/{memory-7YKKR6UC.js → memory-6IS7F275.js} +52 -41
  107. package/dist/{models-ZPOLRU2C.js → models-ENRJDA5W.js} +37 -31
  108. package/dist/{monitor-US5F5YGZ.js → monitor-XLDVO7TN.js} +79 -42
  109. package/dist/{orchestrator-E2AL4T5N.js → orchestrator-6KSPYRHA.js} +4126 -762
  110. package/dist/{paths-E7KYAQWE.js → paths-DBXMZMDU.js} +6 -6
  111. package/dist/registry-LG64LTF4.js +11 -0
  112. package/dist/{reset-KZ652EK6.js → reset-RZ4ER727.js} +12 -12
  113. package/dist/{run-SRNBKDWD.js → run-Y2CNK5RU.js} +89 -76
  114. package/dist/{share-CGZE33UP.js → share-A55GYP6Z.js} +37 -13
  115. package/dist/{skills-S2X4DLY5.js → skills-ALC5J6AT.js} +29 -13
  116. package/dist/{skills-eval-W2GGIC4R.js → skills-eval-JPBEBYQU.js} +60 -48
  117. package/dist/support-MIETYA5E.js +38 -0
  118. package/dist/{targets-54SWINWB.js → targets-VGNXIR3S.js} +46 -36
  119. package/dist/{terminal-lease-SAIF2OGY.js → terminal-lease-WOBR64YA.js} +4 -4
  120. package/dist/{uninstall-BVLWXKBT.js → uninstall-ZJF5H5ZN.js} +9 -9
  121. package/dist/{upgrade-JKAR27XC.js → upgrade-FUSUAGHR.js} +31 -28
  122. package/dist/{usage-MSAWCLX4.js → usage-N4MKVHKD.js} +140 -68
  123. package/dist/verifiers-YAWOJ3H2.js +336 -0
  124. package/dist/{verify-X5HDROLA.js → verify-LTDHYBGY.js} +10 -9
  125. package/dist/{wiki-generate-GUSOQ6ZP.js → wiki-generate-6M7GHTBJ.js} +75 -62
  126. package/dist/worker/entry.js +67 -57
  127. package/docs/README.md +3 -2
  128. package/docs/acp.md +1 -1
  129. package/docs/alcf-provider.md +1 -1
  130. package/docs/architecture.md +2 -2
  131. package/docs/artifact-versions.md +11 -6
  132. package/docs/built-in-agents.md +26 -2
  133. package/docs/capacity-and-scheduling.md +1 -1
  134. package/docs/commands-and-modes.md +83 -3
  135. package/docs/configuration-and-targets.md +86 -4
  136. package/docs/context-engine.md +1 -1
  137. package/docs/development-pipeline.md +1 -1
  138. package/docs/dispatch-architecture-rationale.md +1 -1
  139. package/docs/documentation-coverage.md +3 -3
  140. package/docs/documentation-guide.md +3 -3
  141. package/docs/eval-runner.md +1 -1
  142. package/docs/evals-internal.md +1 -1
  143. package/docs/evidence-and-memory.md +74 -10
  144. package/docs/evolution.md +1 -1
  145. package/docs/exit-codes-and-output.md +4 -1
  146. package/docs/extensions-and-sharing.md +6 -2
  147. package/docs/fleet-demo-runbook.md +2 -2
  148. package/docs/fleet-dispatch.md +228 -16
  149. package/docs/git-commit-provenance.md +2 -2
  150. package/docs/glossary.md +22 -2
  151. package/docs/installation-and-lifecycle.md +2 -2
  152. package/docs/middleware-and-components.md +2 -1
  153. package/docs/model-catalog.md +1 -1
  154. package/docs/observability.md +56 -9
  155. package/docs/proactive-memory.md +1 -1
  156. package/docs/prompt-envelope-and-tools.md +4 -2
  157. package/docs/provider-adapter-cookbook.md +1 -1
  158. package/docs/release-cut-checklist.md +83 -65
  159. package/docs/resource-library.md +59 -0
  160. package/docs/safety-model.md +2 -2
  161. package/docs/scientific-validation.md +3 -3
  162. package/docs/session-lifecycle.md +37 -1
  163. package/docs/skills-marketplace.md +16 -3
  164. package/docs/tool-usage.md +14 -7
  165. package/docs/trace-store.md +1 -1
  166. package/docs/troubleshooting.md +1 -1
  167. package/docs/tui-design.md +1 -1
  168. package/docs/worker-dispatch-mechanics.md +3 -3
  169. package/package.json +1 -2
  170. package/src/cli/argv.ts +5 -0
  171. package/src/cli/configure.ts +107 -23
  172. package/src/cli/doctor.ts +5 -1
  173. package/src/cli/evidence.ts +30 -25
  174. package/src/cli/fleet-commands.ts +37 -0
  175. package/src/cli/fleet-graph.ts +102 -0
  176. package/src/cli/fleet-new.ts +36 -0
  177. package/src/cli/fleet-preflight.ts +111 -0
  178. package/src/cli/fleet-validate.ts +30 -0
  179. package/src/cli/fleet.ts +173 -335
  180. package/src/cli/index.ts +3 -1
  181. package/src/cli/library.ts +190 -0
  182. package/src/cli/share.ts +13 -1
  183. package/src/cli/shared.ts +1 -0
  184. package/src/cli/targets.ts +4 -1
  185. package/src/cli/usage.ts +111 -19
  186. package/src/cli/validate-model.ts +60 -5
  187. package/src/core/bus-events.ts +29 -0
  188. package/src/core/commit-attribution.ts +4 -4
  189. package/src/core/config.ts +130 -0
  190. package/src/core/defaults.ts +81 -0
  191. package/src/core/path-boundary.ts +100 -0
  192. package/src/domains/agents/builtins/architect.md +1 -0
  193. package/src/domains/agents/builtins/oracle.md +33 -0
  194. package/src/domains/agents/catalog.ts +13 -1
  195. package/src/domains/agents/extension.ts +2 -11
  196. package/src/domains/agents/fleet-contract.ts +304 -24
  197. package/src/domains/agents/index.ts +14 -0
  198. package/src/domains/agents/recipe.ts +7 -1
  199. package/src/domains/agents/registry.ts +73 -5
  200. package/src/domains/agents/result-contract.ts +360 -15
  201. package/src/domains/agents/write-boundary.ts +15 -50
  202. package/src/domains/config/classify.ts +4 -0
  203. package/src/domains/context/project-rules.ts +51 -1
  204. package/src/domains/dispatch/active-route-planner.ts +14 -0
  205. package/src/domains/dispatch/assignment-reconcile.ts +22 -5
  206. package/src/domains/dispatch/assignment-store.ts +151 -14
  207. package/src/domains/dispatch/backoff.ts +2 -1
  208. package/src/domains/dispatch/capability-match.ts +1 -0
  209. package/src/domains/dispatch/checkout-writer-lease.ts +175 -0
  210. package/src/domains/dispatch/contract.ts +48 -0
  211. package/src/domains/dispatch/delegation-plan.ts +164 -0
  212. package/src/domains/dispatch/execution-plan.ts +76 -5
  213. package/src/domains/dispatch/execution-role.ts +12 -2
  214. package/src/domains/dispatch/execution-scheduler.ts +183 -67
  215. package/src/domains/dispatch/extension.ts +412 -74
  216. package/src/domains/dispatch/fleet-gate.ts +14 -0
  217. package/src/domains/dispatch/fleet-plan.ts +63 -3
  218. package/src/domains/dispatch/fleet-run.ts +791 -0
  219. package/src/domains/dispatch/gate-role-prompts.ts +47 -0
  220. package/src/domains/dispatch/host-verification.ts +178 -0
  221. package/src/domains/dispatch/index.ts +41 -1
  222. package/src/domains/dispatch/intent-requirements.ts +40 -0
  223. package/src/domains/dispatch/intent.ts +235 -0
  224. package/src/domains/dispatch/path-scope.ts +370 -0
  225. package/src/domains/dispatch/receipt-integrity.ts +9 -4
  226. package/src/domains/dispatch/state.ts +36 -3
  227. package/src/domains/dispatch/types.ts +64 -12
  228. package/src/domains/dispatch/validation.ts +69 -6
  229. package/src/domains/dispatch/write-boundary-enforcer.ts +45 -0
  230. package/src/domains/dispatch/write-boundary.ts +201 -22
  231. package/src/domains/eval/metrics/evidence.ts +79 -2
  232. package/src/domains/eval/runners/clio-run.ts +12 -2
  233. package/src/domains/evidence/build.ts +69 -11
  234. package/src/domains/evidence/index.ts +21 -0
  235. package/src/domains/evidence/provenance.ts +46 -11
  236. package/src/domains/evidence/trust-projection.ts +274 -0
  237. package/src/domains/evidence/trust-status.ts +155 -18
  238. package/src/domains/evidence/types.ts +4 -0
  239. package/src/domains/extensions/discovery.ts +88 -1
  240. package/src/domains/extensions/resources.ts +20 -8
  241. package/src/domains/extensions/state.ts +6 -2
  242. package/src/domains/extensions/types.ts +4 -1
  243. package/src/domains/lifecycle/doctor.ts +140 -1
  244. package/src/domains/middleware/index.ts +15 -0
  245. package/src/domains/middleware/watchdog.ts +281 -0
  246. package/src/domains/observability/contract.ts +3 -1
  247. package/src/domains/observability/cost.ts +12 -1
  248. package/src/domains/observability/extension.ts +2 -2
  249. package/src/domains/observability/index.ts +10 -0
  250. package/src/domains/observability/out-of-turn-usage.ts +223 -0
  251. package/src/domains/prompts/contract.ts +3 -5
  252. package/src/domains/providers/extension.ts +30 -2
  253. package/src/domains/resources/common-loader.ts +3 -0
  254. package/src/domains/resources/index.ts +20 -0
  255. package/src/domains/resources/library.ts +326 -0
  256. package/src/domains/resources/prompts/loader.ts +119 -14
  257. package/src/domains/resources/skills/marketplace.ts +37 -12
  258. package/src/domains/safety/policy-engine.ts +5 -5
  259. package/src/domains/safety/run-effects.ts +64 -1
  260. package/src/domains/safety/scope.ts +7 -12
  261. package/src/domains/session/handoff.ts +629 -0
  262. package/src/domains/share/archive.ts +67 -2
  263. package/src/engine/acp/server.ts +4 -1
  264. package/src/engine/prompt-templates.ts +18 -1
  265. package/src/engine/worker-runtime.ts +6 -3
  266. package/src/entry/orchestrator.ts +37 -0
  267. package/src/interactive/bus-notices.ts +26 -0
  268. package/src/interactive/chat-loop.ts +235 -1
  269. package/src/interactive/chat-renderer.ts +22 -0
  270. package/src/interactive/cost-overlay.ts +31 -3
  271. package/src/interactive/council-dispatch.ts +30 -0
  272. package/src/interactive/council-grid.ts +213 -0
  273. package/src/interactive/council.ts +99 -0
  274. package/src/interactive/dispatch-board.ts +311 -17
  275. package/src/interactive/fleet-run-preview.ts +307 -0
  276. package/src/interactive/footer/notifications.ts +219 -0
  277. package/src/interactive/handoff-round.ts +56 -0
  278. package/src/interactive/interactive-application.ts +43 -1
  279. package/src/interactive/interactive-event-projection.ts +23 -1
  280. package/src/interactive/interactive-slash-runtime.ts +52 -2
  281. package/src/interactive/interactive-subscriptions.ts +14 -2
  282. package/src/interactive/oracle.ts +179 -0
  283. package/src/interactive/overlay-ask-user-lifecycle.ts +6 -0
  284. package/src/interactive/overlay-general-openers.ts +190 -1
  285. package/src/interactive/overlay-key-routing.ts +17 -1
  286. package/src/interactive/overlay-lifecycle.ts +41 -1
  287. package/src/interactive/overlay-permission-lifecycle.ts +10 -0
  288. package/src/interactive/overlay-resource-openers.ts +11 -3
  289. package/src/interactive/overlay-session-lifecycle.ts +234 -2
  290. package/src/interactive/overlays/fleet-run-approval.ts +208 -0
  291. package/src/interactive/overlays/handoff-review.ts +185 -0
  292. package/src/interactive/overlays/library-install-confirm.ts +151 -0
  293. package/src/interactive/overlays/list-overlay.ts +168 -2
  294. package/src/interactive/overlays/settings.ts +221 -30
  295. package/src/interactive/overlays/side-question.ts +139 -0
  296. package/src/interactive/overlays/skills-hub.ts +401 -15
  297. package/src/interactive/side-question.ts +171 -0
  298. package/src/interactive/slash-commands.ts +439 -7
  299. package/src/interactive/slash-spec.ts +19 -6
  300. package/src/interactive/theme/tokens.ts +30 -0
  301. package/src/interactive/turn-middleware.ts +15 -1
  302. package/src/interactive/view/artifacts.ts +42 -9
  303. package/src/interactive/view/view-overlay.ts +15 -3
  304. package/src/interactive/watchdog-run.ts +75 -0
  305. package/src/interactive/worker-receipts.ts +14 -2
  306. package/src/interactive/worker-share.ts +56 -1
  307. package/src/interactive/worker-stream.ts +15 -0
  308. package/src/tools/bootstrap.ts +3 -0
  309. package/src/tools/compete-worktrees.ts +13 -79
  310. package/src/tools/dispatch-admission.ts +251 -18
  311. package/src/tools/dispatch-arguments.ts +84 -1
  312. package/src/tools/dispatch-plan.ts +165 -6
  313. package/src/tools/dispatch-runner.ts +364 -23
  314. package/src/tools/dispatch-types.ts +20 -1
  315. package/src/tools/dispatch.ts +72 -2
  316. package/src/tools/monitor.ts +29 -0
  317. package/src/tools/profiles.ts +18 -4
  318. package/src/tools/task-worktree.ts +238 -0
  319. package/src/tools/verify/authoring.ts +61 -1
  320. package/src/tools/verify/scripts.ts +62 -0
  321. package/src/tools/worker-evidence.ts +21 -14
  322. package/src/worker/spec-contract.ts +3 -1
  323. package/dist/chunk-HC4CLZ2Y.js +0 -68
@@ -17,6 +17,7 @@ import {
17
17
  type RunReceipt,
18
18
  type RunReceiptVerification,
19
19
  } from "../domains/dispatch/types.js";
20
+ import { summarizeTrustStatus } from "../domains/evidence/trust-projection.js";
20
21
  import {
21
22
  adaptRunReceiptTrustStatus,
22
23
  type CanonicalTrustStatus,
@@ -123,6 +124,11 @@ function runStatus(deps: MonitorToolDeps, runId: string): ToolResult {
123
124
  `started=${run.startedAt} ended=${run.endedAt ?? "n/a"} exit=${run.exitCode ?? "n/a"}`,
124
125
  `tokens=${run.tokenCount} cost=${formatCostAggregate(costAggregateForAmount(run.costUsd, run.costProvenance)) ?? COST_NOT_MEASURED} receipt=${run.receiptPath ?? "n/a"}`,
125
126
  ];
127
+ if (run.council !== undefined || run.gate?.role === "synthesis") {
128
+ lines.push(
129
+ `council: role=${run.gate?.role === "synthesis" ? "synthesis" : "member"} group=${run.council?.group ?? run.gate?.group ?? "unknown"}${run.council?.label ? ` label=${run.council.label}` : ""}`,
130
+ );
131
+ }
126
132
  if (run.budget !== undefined) {
127
133
  lines.push(
128
134
  `recipe policy: ${formatBudgetPolicy(run.budget)}`,
@@ -158,6 +164,15 @@ function runStatus(deps: MonitorToolDeps, runId: string): ToolResult {
158
164
  costUsd: run.costUsd,
159
165
  costProvenance: run.costProvenance ?? "unknown",
160
166
  budget: run.budget ?? null,
167
+ ...(run.council !== undefined || run.gate?.role === "synthesis"
168
+ ? {
169
+ council: {
170
+ role: run.gate?.role === "synthesis" ? "synthesis" : "member",
171
+ group: run.council?.group ?? run.gate?.group ?? null,
172
+ ...(run.council !== undefined ? { label: run.council.label, round: run.council.round } : {}),
173
+ },
174
+ }
175
+ : {}),
161
176
  receiptPath: run.receiptPath,
162
177
  running: live !== null,
163
178
  },
@@ -375,9 +390,11 @@ function runReceipt(deps: MonitorToolDeps, runId: string): ToolResult {
375
390
  receiptPath: run.receiptPath,
376
391
  receiptIntegrity,
377
392
  trustStatus,
393
+ trust: summarizeTrustStatus(trustStatus),
378
394
  ...(receipt !== null && receiptIntegrity.ok
379
395
  ? {
380
396
  evidenceVerification: receipt.verification,
397
+ hostVerification: receipt.hostVerification ?? null,
381
398
  briefing: receipt.briefing ?? null,
382
399
  projectContext: receipt.projectContext ?? null,
383
400
  }
@@ -440,6 +457,17 @@ function durableRunEvidence(run: RunEnvelope | null): DurableRunEvidence {
440
457
  const inspection = inspectRunReceiptTrustStatus(receipt, run);
441
458
  const integrity = inspection.integrity;
442
459
  if (!integrity.ok) {
460
+ // A retired seal is set aside unread, as a missing receipt is. It is
461
+ // not a failed one, so it never reads as tampering here either.
462
+ if (integrity.retired !== undefined) {
463
+ return {
464
+ ...unavailableRunEvidence(
465
+ integrity.reason,
466
+ `${integrity.reason}; worker text is unavailable and validation is unknown.`,
467
+ ),
468
+ trustStatus: inspection.status,
469
+ };
470
+ }
443
471
  return {
444
472
  ...unavailableRunEvidence(
445
473
  integrity.reason,
@@ -717,6 +745,7 @@ async function runCollect(
717
745
  receiptIntegrity: row.evidence.integrity,
718
746
  trustStatus: row.evidence.trustStatus,
719
747
  evidenceVerification: row.evidence.verification,
748
+ hostVerification: row.evidence.receipt?.hostVerification ?? null,
720
749
  briefing: row.evidence.receipt?.briefing ?? null,
721
750
  projectContext: row.evidence.receipt?.projectContext ?? null,
722
751
  ...(output ? { output: { state: output.state, bytes: output.bytes, truncated: output.truncated } } : {}),
@@ -1,8 +1,13 @@
1
1
  import { type BuiltinToolName, isBuiltinToolName, type ToolName, ToolNames } from "../core/tool-names.js";
2
2
 
3
- export type ToolProfileName = "minimal-local" | "science-local" | "full-agent";
3
+ export type ToolProfileName = "minimal-local" | "science-local" | "full-agent" | "council-read-only";
4
4
 
5
- export const TOOL_PROFILE_NAMES: ReadonlyArray<ToolProfileName> = ["minimal-local", "science-local", "full-agent"];
5
+ export const TOOL_PROFILE_NAMES: ReadonlyArray<Exclude<ToolProfileName, "council-read-only">> = [
6
+ "minimal-local",
7
+ "science-local",
8
+ "full-agent",
9
+ ];
10
+ const ALL_TOOL_PROFILE_NAMES: ReadonlyArray<ToolProfileName> = [...TOOL_PROFILE_NAMES, "council-read-only"];
6
11
  const CODEWIKI_TOOL_NAMES: ReadonlyArray<BuiltinToolName> = [ToolNames.CodeNav];
7
12
 
8
13
  export interface ToolProfileContext {
@@ -24,14 +29,23 @@ const MINIMAL_LOCAL_TOOLS: ReadonlyArray<BuiltinToolName> = [
24
29
  ];
25
30
 
26
31
  const SCIENCE_LOCAL_TOOLS: ReadonlyArray<BuiltinToolName> = [...MINIMAL_LOCAL_TOOLS, ToolNames.Verify];
32
+ const COUNCIL_READ_ONLY_TOOLS: ReadonlyArray<BuiltinToolName> = [
33
+ ToolNames.Read,
34
+ ToolNames.Grep,
35
+ ToolNames.Find,
36
+ ToolNames.Ls,
37
+ ToolNames.CodeNav,
38
+ ToolNames.Context,
39
+ ];
27
40
 
28
41
  const NARROW_TOOL_PROFILES: Readonly<Record<Exclude<ToolProfileName, "full-agent">, ReadonlySet<BuiltinToolName>>> = {
29
42
  "minimal-local": new Set(MINIMAL_LOCAL_TOOLS),
30
43
  "science-local": new Set(SCIENCE_LOCAL_TOOLS),
44
+ "council-read-only": new Set(COUNCIL_READ_ONLY_TOOLS),
31
45
  };
32
46
 
33
47
  export function isToolProfileName(value: string): value is ToolProfileName {
34
- return (TOOL_PROFILE_NAMES as ReadonlyArray<string>).includes(value);
48
+ return (ALL_TOOL_PROFILE_NAMES as ReadonlyArray<string>).includes(value);
35
49
  }
36
50
 
37
51
  /**
@@ -72,7 +86,7 @@ export function applyToolProfile(
72
86
  const allowed = NARROW_TOOL_PROFILES[profile];
73
87
  profiled = unique.filter((tool): tool is BuiltinToolName => isBuiltinToolName(tool) && allowed.has(tool));
74
88
  }
75
- return applyCodewikiWorkerPolicy(profiled, context);
89
+ return profile === "council-read-only" ? profiled : applyCodewikiWorkerPolicy(profiled, context);
76
90
  }
77
91
 
78
92
  function uniquePreservingOrder(tools: ReadonlyArray<ToolName>): ToolName[] {
@@ -0,0 +1,238 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { createHash, randomBytes } from "node:crypto";
3
+ import { existsSync, mkdirSync, realpathSync, rmSync, writeFileSync } from "node:fs";
4
+ import { isAbsolute, join, relative, resolve, sep } from "node:path";
5
+
6
+ export type TaskWorktreeApply = "merge" | "preserve";
7
+
8
+ export interface TaskWorktree {
9
+ root: string;
10
+ runId: string;
11
+ path: string;
12
+ branch: string;
13
+ base: string;
14
+ ownerToken: string;
15
+ }
16
+
17
+ export interface TaskWorktreeReceipt {
18
+ path: string;
19
+ branch: string;
20
+ diffHash: string;
21
+ apply: TaskWorktreeApply;
22
+ applied: boolean;
23
+ reason?: string;
24
+ }
25
+
26
+ const SAFE_RUN_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;
27
+ const OWNER_FILE_SUFFIX = ".task-owner.json";
28
+ const COMMIT_IDENTITY = "clio-task";
29
+
30
+ function gitBytes(root: string, args: string[]): Buffer {
31
+ return execFileSync("git", ["-C", root, ...args], {
32
+ stdio: ["ignore", "pipe", "pipe"],
33
+ timeout: 30_000,
34
+ });
35
+ }
36
+
37
+ function git(root: string, args: string[]): string {
38
+ return gitBytes(root, args).toString("utf8").trim();
39
+ }
40
+
41
+ export function isCanonicalWorktreePathInside(parent: string, candidate: string): boolean {
42
+ let canonicalParent: string;
43
+ let canonicalCandidate: string;
44
+ try {
45
+ canonicalParent = realpathSync(parent);
46
+ } catch {
47
+ canonicalParent = resolve(parent);
48
+ }
49
+ try {
50
+ canonicalCandidate = realpathSync(candidate);
51
+ } catch {
52
+ canonicalCandidate = resolve(candidate);
53
+ }
54
+ const rel = relative(canonicalParent, canonicalCandidate);
55
+ return rel.length > 0 && rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel);
56
+ }
57
+
58
+ export function commitWorktreePath(path: string, identity: string, message: string): boolean {
59
+ git(path, ["add", "-A"]);
60
+ if (git(path, ["status", "--porcelain"]).length === 0) return false;
61
+ git(path, [
62
+ "-c",
63
+ `user.name=${identity}`,
64
+ "-c",
65
+ `user.email=${identity}@local`,
66
+ "commit",
67
+ "-m",
68
+ message,
69
+ "--no-verify",
70
+ ]);
71
+ return true;
72
+ }
73
+
74
+ export function worktreeBranchDiffStat(root: string, branch: string): string {
75
+ try {
76
+ return git(root, ["diff", "--shortstat", `HEAD...${branch}`]) || "no changes";
77
+ } catch {
78
+ return "diff unavailable";
79
+ }
80
+ }
81
+
82
+ export function protectedPathsChangedByWorktreeBranch(
83
+ root: string,
84
+ branch: string,
85
+ protectedPaths: ReadonlyArray<string>,
86
+ ): string[] {
87
+ const canonical = realpathSync(root);
88
+ const protectedInside = protectedPaths
89
+ .map((path) => resolve(path))
90
+ .filter((path) => {
91
+ const rel = relative(canonical, path);
92
+ return rel.length > 0 && rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel);
93
+ });
94
+ if (protectedInside.length === 0) return [];
95
+ const changed = git(canonical, ["diff", "--name-only", "-z", "--no-renames", `HEAD...${branch}`])
96
+ .split("\0")
97
+ .filter((path) => path.length > 0)
98
+ .map((path) => resolve(canonical, path));
99
+ const blocked = new Set<string>();
100
+ for (const candidate of changed) {
101
+ for (const protectedPath of protectedInside) {
102
+ const rel = relative(protectedPath, candidate);
103
+ if (
104
+ candidate === protectedPath ||
105
+ (rel.length > 0 && rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel))
106
+ ) {
107
+ blocked.add(protectedPath);
108
+ }
109
+ }
110
+ }
111
+ return [...blocked].sort();
112
+ }
113
+
114
+ export function mergeWorktreeBranch(
115
+ root: string,
116
+ branch: string,
117
+ identity: string,
118
+ ): { ok: true } | { ok: false; reason: string } {
119
+ try {
120
+ git(root, [
121
+ "-c",
122
+ `user.name=${identity}`,
123
+ "-c",
124
+ `user.email=${identity}@local`,
125
+ "merge",
126
+ "--no-edit",
127
+ "--no-verify",
128
+ branch,
129
+ ]);
130
+ return { ok: true };
131
+ } catch (error) {
132
+ try {
133
+ git(root, ["merge", "--abort"]);
134
+ } catch {
135
+ // No merge remains to abort.
136
+ }
137
+ return {
138
+ ok: false,
139
+ reason: error instanceof Error ? (error.message.split("\n")[0] ?? "merge failed") : String(error),
140
+ };
141
+ }
142
+ }
143
+
144
+ function validateRunId(runId: string): void {
145
+ if (!SAFE_RUN_ID.test(runId) || runId === "." || runId === "..")
146
+ throw new Error(`invalid task worktree run id '${runId}'`);
147
+ }
148
+
149
+ export function gitCheckoutRoot(cwd: string): string | null {
150
+ try {
151
+ return realpathSync(git(cwd, ["rev-parse", "--show-toplevel"]));
152
+ } catch {
153
+ return null;
154
+ }
155
+ }
156
+
157
+ export function createTaskWorktree(root: string, runId: string, base?: string): TaskWorktree {
158
+ validateRunId(runId);
159
+ const canonical = realpathSync(root);
160
+ const resolvedBase = base ?? git(canonical, ["rev-parse", "HEAD"]);
161
+ const parent = join(canonical, ".clio-coder", "worktrees");
162
+ const path = join(parent, runId);
163
+ const branch = `clio/task/${runId}`;
164
+ mkdirSync(parent, { recursive: true });
165
+ if (!isCanonicalWorktreePathInside(parent, path))
166
+ throw new Error(`task worktree path escapes its parent for run ${runId}`);
167
+ git(canonical, ["worktree", "add", "-b", branch, path, resolvedBase]);
168
+ const ownerToken = randomBytes(16).toString("hex");
169
+ writeFileSync(
170
+ `${path}${OWNER_FILE_SUFFIX}`,
171
+ `${JSON.stringify({ version: 1, kind: "clio-task-worktree", root: canonical, runId, branch, base: resolvedBase, ownerToken }, null, 2)}\n`,
172
+ { encoding: "utf8", flag: "wx" },
173
+ );
174
+ return { root: canonical, runId, path, branch, base: resolvedBase, ownerToken };
175
+ }
176
+
177
+ function assertOwnership(worktree: TaskWorktree): void {
178
+ const expected = join(worktree.root, ".clio-coder", "worktrees", worktree.runId);
179
+ if (
180
+ resolve(worktree.path) !== resolve(expected) ||
181
+ !isCanonicalWorktreePathInside(join(worktree.root, ".clio-coder", "worktrees"), worktree.path)
182
+ ) {
183
+ throw new Error(`task worktree ${worktree.runId} has an invalid ownership path`);
184
+ }
185
+ if (!existsSync(`${worktree.path}${OWNER_FILE_SUFFIX}`))
186
+ throw new Error(`task worktree ${worktree.runId} has no ownership file`);
187
+ }
188
+
189
+ function commitTaskWorktree(worktree: TaskWorktree, message = `Clio task ${worktree.runId}`): boolean {
190
+ assertOwnership(worktree);
191
+ return commitWorktreePath(worktree.path, COMMIT_IDENTITY, message);
192
+ }
193
+
194
+ function taskWorktreeDiffHash(worktree: Pick<TaskWorktree, "root" | "base" | "branch">): string {
195
+ const bytes = gitBytes(worktree.root, ["diff", `${worktree.base}..${worktree.branch}`]);
196
+ return createHash("sha256").update(bytes).digest("hex");
197
+ }
198
+
199
+ function protectedPathsChangedByTaskBranch(
200
+ worktree: Pick<TaskWorktree, "root" | "branch">,
201
+ protectedPaths: ReadonlyArray<string>,
202
+ ): string[] {
203
+ return protectedPathsChangedByWorktreeBranch(worktree.root, worktree.branch, protectedPaths);
204
+ }
205
+
206
+ export function applyTaskWorktree(input: {
207
+ worktree: TaskWorktree;
208
+ apply: TaskWorktreeApply;
209
+ protectedPaths?: ReadonlyArray<string>;
210
+ }): TaskWorktreeReceipt {
211
+ assertOwnership(input.worktree);
212
+ commitTaskWorktree(input.worktree);
213
+ const receipt: TaskWorktreeReceipt = {
214
+ path: input.worktree.path,
215
+ branch: input.worktree.branch,
216
+ diffHash: taskWorktreeDiffHash(input.worktree),
217
+ apply: input.apply,
218
+ applied: false,
219
+ };
220
+ if (input.apply === "preserve") return receipt;
221
+ const protectedChanges = protectedPathsChangedByTaskBranch(input.worktree, input.protectedPaths ?? []);
222
+ if (protectedChanges.length > 0) return { ...receipt, reason: "protected_artifact_changed" };
223
+ const merged = mergeWorktreeBranch(input.worktree.root, input.worktree.branch, COMMIT_IDENTITY);
224
+ if (!merged.ok) return { ...receipt, reason: "worktree_merge_conflict" };
225
+ return { ...receipt, applied: true };
226
+ }
227
+
228
+ export function cleanupTaskWorktree(worktree: TaskWorktree, deleteBranch: boolean): void {
229
+ assertOwnership(worktree);
230
+ try {
231
+ git(worktree.root, ["worktree", "remove", "--force", worktree.path]);
232
+ } catch {
233
+ if (existsSync(worktree.path)) rmSync(worktree.path, { recursive: true, force: true });
234
+ git(worktree.root, ["worktree", "prune"]);
235
+ }
236
+ if (deleteBranch) git(worktree.root, ["branch", "-D", worktree.branch]);
237
+ rmSync(`${worktree.path}${OWNER_FILE_SUFFIX}`, { force: true });
238
+ }
@@ -24,7 +24,7 @@ import {
24
24
  parseProjectVerifierCatalogText,
25
25
  } from "./catalog.js";
26
26
  import { verifyTool } from "./index.js";
27
- import { discoverDeclaredChecksAtRoot } from "./scripts.js";
27
+ import { discoverDeclaredChecksAtRoot, discoverDeclaredProjectEntriesAtRoot } from "./scripts.js";
28
28
 
29
29
  export type VerifierProposalAuthority = "project-declared" | "toolchain-defined";
30
30
 
@@ -34,6 +34,8 @@ export type VerifierSignalKind =
34
34
  | "cargo"
35
35
  | "cmake-preset"
36
36
  | "python-runner"
37
+ | "just-recipe"
38
+ | "make-target"
37
39
  | "go-module"
38
40
  | "validation-contract"
39
41
  | "manual-entry";
@@ -149,6 +151,12 @@ export interface VerifierAuthoringWorkflowOptions {
149
151
  runCheck?: (id: string) => Promise<ToolResult>;
150
152
  }
151
153
 
154
+ export interface DeclaredProjectCommand {
155
+ id: string;
156
+ command: string[];
157
+ provenance: VerifierProvenance;
158
+ }
159
+
152
160
  interface RawProposal {
153
161
  preferredId: string;
154
162
  description: string;
@@ -466,6 +474,58 @@ function pythonProposals(workspaceRoot: string, diagnostics: string[]): RawPropo
466
474
  return proposals;
467
475
  }
468
476
 
477
+ /**
478
+ * Discover exact invocation vectors from project declarations for fleet command
479
+ * authoring. This shares the verifier authoring readers and provenance model,
480
+ * while retaining entries that are not verification-family names.
481
+ */
482
+ export function discoverDeclaredProjectCommands(workspaceRoot = process.cwd()): DeclaredProjectCommand[] {
483
+ const commands: DeclaredProjectCommand[] = [];
484
+ const add = (id: string, command: string[], pathValue: string, detail: string, kind: VerifierSignalKind): void => {
485
+ commands.push({
486
+ id,
487
+ command,
488
+ provenance: { kind, path: pathValue, detail, authority: "project-declared" },
489
+ });
490
+ };
491
+ for (const entry of discoverDeclaredProjectEntriesAtRoot(workspaceRoot)) {
492
+ add(entry.id, entry.command, entry.path, entry.detail, entry.kind);
493
+ }
494
+ const pyprojectText = regularFileText(path.join(workspaceRoot, "pyproject.toml"), workspaceRoot);
495
+ if (typeof pyprojectText === "string") {
496
+ const document = parseTomlDocument(pyprojectText);
497
+ if (document !== null) {
498
+ for (const [tablePath, label] of [
499
+ [["project", "scripts"], "project.scripts"],
500
+ [["tool", "poetry", "scripts"], "tool.poetry.scripts"],
501
+ ] as const) {
502
+ const scripts = tomlTableAt(document, tablePath);
503
+ if (scripts === null) continue;
504
+ for (const [name, target] of Object.entries(scripts).sort(([left], [right]) => compareCodepoints(left, right))) {
505
+ if (typeof target === "string") add(name, [name], "pyproject.toml", `[${label}] entry '${name}'`, "python-runner");
506
+ }
507
+ }
508
+ for (const [tablePath, module, id, label] of [
509
+ [["tool", "pytest", "ini_options"], "pytest", "pytest", "tool.pytest.ini_options"],
510
+ [["tool", "tox"], "tox", "tox", "tool.tox"],
511
+ [["tool", "nox"], "nox", "nox", "tool.nox"],
512
+ ] as const) {
513
+ if (tomlTableAt(document, tablePath) !== null)
514
+ add(id, ["python", "-m", module], "pyproject.toml", `[${label}]`, "python-runner");
515
+ }
516
+ }
517
+ }
518
+ const seen = new Set<string>();
519
+ return commands.filter((entry) => {
520
+ let id = slug(entry.id, "command");
521
+ let suffix = 2;
522
+ while (seen.has(id)) id = `${slug(entry.id, "command")}-${suffix++}`;
523
+ seen.add(id);
524
+ entry.id = id;
525
+ return true;
526
+ });
527
+ }
528
+
469
529
  function goProposals(workspaceRoot: string, diagnostics: string[]): RawProposal[] {
470
530
  const relative = "go.mod";
471
531
  const text = regularFileText(path.join(workspaceRoot, relative), workspaceRoot);
@@ -21,6 +21,14 @@ import {
21
21
 
22
22
  export type DeclaredCheckDiscoveryResult = { ok: true; sources: DeclaredCheckSource[] } | { ok: false; reason: string };
23
23
 
24
+ export interface DeclaredProjectEntry {
25
+ id: string;
26
+ command: string[];
27
+ path: string;
28
+ detail: string;
29
+ kind: "package-script" | "just-recipe" | "make-target";
30
+ }
31
+
24
32
  function repositoryRelativeCwd(workspaceRoot: string, resolved: string): string {
25
33
  const relative = path.relative(workspaceRoot, resolved);
26
34
  return relative.length === 0 ? "." : relative.split(path.sep).join("/");
@@ -43,6 +51,60 @@ function packageCheckSource(packageRoot: string, workspaceRoot: string): Declare
43
51
  return { kind: "package.json", path: packagePath, checks };
44
52
  }
45
53
 
54
+ /** Discover every exact project-declared entry without promoting it to a verifier check. */
55
+ export function discoverDeclaredProjectEntriesAtRoot(workspaceRoot: string): DeclaredProjectEntry[] {
56
+ const entries: DeclaredProjectEntry[] = [];
57
+ const packagePath = path.join(workspaceRoot, "package.json");
58
+ if (existsSync(packagePath)) {
59
+ const pkg = parsePackageJson(packagePath);
60
+ if (pkg.ok) {
61
+ for (const name of Object.keys(pkg.scripts).sort()) {
62
+ if (typeof pkg.scripts[name] !== "string") continue;
63
+ entries.push({
64
+ id: name,
65
+ command: ["npm", "run", name],
66
+ path: "package.json",
67
+ detail: `package.json script '${name}'`,
68
+ kind: "package-script",
69
+ });
70
+ }
71
+ }
72
+ }
73
+ for (const relative of ["justfile", "Justfile"] as const) {
74
+ const filePath = path.join(workspaceRoot, relative);
75
+ if (!existsSync(filePath)) continue;
76
+ const text = readFileSync(filePath, "utf8");
77
+ for (const match of text.matchAll(/^([A-Za-z0-9][A-Za-z0-9_-]*)\s*(?:[^:=\n]*)?:\s*(?:#.*)?$/gmu)) {
78
+ const name = match[1];
79
+ if (name === undefined || name.startsWith("_")) continue;
80
+ entries.push({
81
+ id: name,
82
+ command: ["just", name],
83
+ path: relative,
84
+ detail: `just recipe '${name}'`,
85
+ kind: "just-recipe",
86
+ });
87
+ }
88
+ break;
89
+ }
90
+ const makePath = path.join(workspaceRoot, "Makefile");
91
+ if (existsSync(makePath)) {
92
+ const text = readFileSync(makePath, "utf8");
93
+ for (const match of text.matchAll(/^([A-Za-z0-9][A-Za-z0-9_.-]*)\s*:(?![=])[^\n]*$/gmu)) {
94
+ const name = match[1];
95
+ if (name === undefined || name.startsWith(".")) continue;
96
+ entries.push({
97
+ id: name,
98
+ command: ["make", name],
99
+ path: "Makefile",
100
+ detail: `Makefile target '${name}'`,
101
+ kind: "make-target",
102
+ });
103
+ }
104
+ }
105
+ return entries;
106
+ }
107
+
46
108
  function providerCollision(sources: ReadonlyArray<DeclaredCheckSource>): string | null {
47
109
  const seen = new Map<string, DeclaredCheck>();
48
110
  for (const source of sources) {
@@ -7,6 +7,7 @@ import {
7
7
  } from "../domains/dispatch/budget-envelope.js";
8
8
  import type { ReceiptIntegrityResult } from "../domains/dispatch/receipt-integrity.js";
9
9
  import type { RunReceipt, RunReceiptVerification } from "../domains/dispatch/types.js";
10
+ import { formatTrustAxes, formatTrustSummary } from "../domains/evidence/trust-projection.js";
10
11
  import { adaptRunReceiptTrustStatus, type CanonicalTrustStatus } from "../domains/evidence/trust-status.js";
11
12
  import { receiptResponseModelIdObservationLabel } from "./dispatch-event-text.js";
12
13
 
@@ -127,10 +128,10 @@ export function receiptEvidenceLabels(
127
128
  verification: RunReceiptVerification,
128
129
  integrity: ReceiptIntegrityResult,
129
130
  ): string[] {
130
- const status = adaptRunReceiptTrustStatus({ ...receipt, verification }, { integrity });
131
- const canonical = canonicalTrustLabel(status);
131
+ const status = adaptRunReceiptTrustStatus({ ...receipt, verification: verification }, { integrity });
132
+ const canonical = canonicalTrustLabels(status);
132
133
  if (!integrity.ok) {
133
- return [canonical, `receipt_integrity=FAILED reason=${JSON.stringify(integrity.reason)}`];
134
+ return [...canonical, `receipt_integrity=FAILED reason=${JSON.stringify(integrity.reason)}`];
134
135
  }
135
136
  const briefing =
136
137
  receipt.briefing === undefined
@@ -154,9 +155,10 @@ export function receiptEvidenceLabels(
154
155
  `budget_reason=${JSON.stringify(formatBudgetReasons(receipt.budget))}`,
155
156
  ];
156
157
  return [
157
- canonical,
158
+ ...canonical,
158
159
  `receipt_integrity=verified/v${receipt.integrity.version}/${receipt.integrity.algorithm}`,
159
160
  `evidence_verification=${verification.state}/${verification.basis}`,
161
+ `host_verification=${receipt.hostVerification?.status ?? "not_requested"}`,
160
162
  ...(responseModelIdObservation ? [responseModelIdObservation] : []),
161
163
  ...budget,
162
164
  ...receiptAdmissionLabels(receipt),
@@ -166,16 +168,13 @@ export function receiptEvidenceLabels(
166
168
  ];
167
169
  }
168
170
 
169
- function canonicalTrustLabel(status: CanonicalTrustStatus): string {
170
- return [
171
- `trust_status=v${status.version}`,
172
- `artifactIntegrity:${status.artifactIntegrity.state}`,
173
- `validationGrounding:${status.validationGrounding.state}`,
174
- `independentReview:${status.independentReview.state}`,
175
- `contextProvenance:${status.contextProvenance.state}`,
176
- `autonomyEnforcement:${status.autonomyEnforcement.state}`,
177
- `completionEvidence:${status.completionEvidence.state}`,
178
- ].join(" ");
171
+ /**
172
+ * The compact projection first, then the canonical axis line, both from the
173
+ * shared projection so the dispatch and monitor text can never spell a state
174
+ * differently from `evidence inspect` or the board.
175
+ */
176
+ function canonicalTrustLabels(status: CanonicalTrustStatus): string[] {
177
+ return [`trust=${JSON.stringify(formatTrustSummary(status))}`, formatTrustAxes(status)];
179
178
  }
180
179
 
181
180
  /**
@@ -191,6 +190,14 @@ export function workerTextLabel(status: CanonicalTrustStatus): string {
191
190
  return "reconnaissance output (advisory leads, not validation evidence):";
192
191
  case "unknown":
193
192
  return "worker claims (validation not observable at this layer):";
193
+ // The three remaining states were one label. The evidence bundle tells
194
+ // a failed check, an inferred claim, and no validation at all apart, so
195
+ // the terminal must too or it hands the operator a coarser verdict than
196
+ // the report for the same run.
197
+ case "failed":
198
+ return "worker claims (validation failed; a check ran and did not pass):";
199
+ case "ungrounded":
200
+ return "worker claims (inferred; validation claimed, none observed):";
194
201
  default:
195
202
  return "worker claims (unverified prose):";
196
203
  }
@@ -162,7 +162,8 @@ interface WorkerSpecFields {
162
162
  */
163
163
  autonomy?: AutonomyLevel;
164
164
  /**
165
- * Absolute directories write-class tool calls are confined to for this run.
165
+ * Absolute path boundaries write-class tool calls are confined to for this run.
166
+ * Exact files omit a trailing slash and subtrees retain one.
166
167
  * Enforced at the shared worker safety seam so a write/edit target outside
167
168
  * every root is a final block. Only set on runtimes that mediate per-tool
168
169
  * calls (native, claude-sdk); dispatch refuses it on subprocess runtimes.
@@ -225,6 +226,7 @@ const TOOL_PROFILE_NAMES = [
225
226
  "minimal-local",
226
227
  "science-local",
227
228
  "full-agent",
229
+ "council-read-only",
228
230
  ] as const satisfies ReadonlyArray<ToolProfileName>;
229
231
  const WORKER_PRODUCTS = ["orientation"] as const satisfies ReadonlyArray<AgentProduct>;
230
232
  const TARGET_LIFECYCLES = ["user-managed", "clio-managed"] as const;
@@ -1,68 +0,0 @@
1
- import { createRequire as __clioCreateRequire } from "node:module"; const require = __clioCreateRequire(import.meta.url);
2
- import {
3
- withStateFileLock
4
- } from "./chunk-IKCO5N3L.js";
5
- import {
6
- safeResourceWrite
7
- } from "./chunk-WEPFGWHJ.js";
8
- import {
9
- init_esm_shims
10
- } from "./chunk-3R73A4XB.js";
11
-
12
- // src/domains/observability/evidence-index.ts
13
- init_esm_shims();
14
- import { readFileSync } from "node:fs";
15
- import { join } from "node:path";
16
- var MAX_EVIDENCE_INDEX_ROWS = 1e3;
17
- var EVIDENCE_INDEX_FILE = "evidence-index.json";
18
- var evidenceIndexWriteQueue = Promise.resolve();
19
- function indexPath(stateDir) {
20
- return join(stateDir, EVIDENCE_INDEX_FILE);
21
- }
22
- function isEvidenceIndexRow(value) {
23
- if (typeof value !== "object" || value === null) return false;
24
- const row = value;
25
- return typeof row.runId === "string" && typeof row.evidenceId === "string" && Array.isArray(row.tags) && row.tags.every((tag) => typeof tag === "string") && typeof row.firstPassSuccess === "boolean" && typeof row.findingCount === "number" && typeof row.generatedAt === "string";
26
- }
27
- function readEvidenceIndex(stateDir) {
28
- let raw;
29
- try {
30
- raw = readFileSync(indexPath(stateDir), "utf8");
31
- } catch {
32
- return [];
33
- }
34
- let parsed;
35
- try {
36
- parsed = JSON.parse(raw);
37
- } catch {
38
- return [];
39
- }
40
- if (!Array.isArray(parsed)) return [];
41
- return parsed.filter(isEvidenceIndexRow);
42
- }
43
- async function writeEvidenceIndexRow(stateDir, row) {
44
- let bounded = [];
45
- await withStateFileLock(indexPath(stateDir), () => {
46
- const existing = readEvidenceIndex(stateDir).filter((entry) => entry.runId !== row.runId);
47
- existing.push(row);
48
- bounded = existing.length > MAX_EVIDENCE_INDEX_ROWS ? existing.slice(-MAX_EVIDENCE_INDEX_ROWS) : existing;
49
- safeResourceWrite(indexPath(stateDir), `${JSON.stringify(bounded, null, 2)}
50
- `, { encoding: "utf8" });
51
- });
52
- return bounded;
53
- }
54
- async function writeEvidenceIndexRowQueued(stateDir, row) {
55
- let written = [];
56
- const write = evidenceIndexWriteQueue.then(async () => {
57
- written = await writeEvidenceIndexRow(stateDir, row);
58
- });
59
- evidenceIndexWriteQueue = write.catch(() => void 0);
60
- await write;
61
- return written;
62
- }
63
-
64
- export {
65
- readEvidenceIndex,
66
- writeEvidenceIndexRowQueued
67
- };
68
- //# sourceMappingURL=chunk-HC4CLZ2Y.js.map