@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
@@ -1,6 +1,12 @@
1
1
  import { createRequire as __clioCreateRequire } from "node:module"; const require = __clioCreateRequire(import.meta.url);
2
2
  import {
3
- AGENT_AUTOMATION_AUTHORITIES,
3
+ loadProjectVerifierCatalog
4
+ } from "./chunk-A2NJGIB3.js";
5
+ import {
6
+ pathBoundaryCovers,
7
+ resolvePathBoundary
8
+ } from "./chunk-TTHACPOM.js";
9
+ import {
4
10
  classify
5
11
  } from "./chunk-AOCYTWAV.js";
6
12
  import {
@@ -12,9 +18,6 @@ import {
12
18
  tokenizeShellLike,
13
19
  toolMutationPaths
14
20
  } from "./chunk-MV3K5QF2.js";
15
- import {
16
- loadProjectVerifierCatalog
17
- } from "./chunk-FYYLNIL5.js";
18
21
  import {
19
22
  isProjectVerifierCheckId,
20
23
  isVerificationScriptName
@@ -28,715 +31,20 @@ import {
28
31
  import {
29
32
  foreignAgentDirs
30
33
  } from "./chunk-IHXBNWMM.js";
34
+ import {
35
+ resolvePackageRoot
36
+ } from "./chunk-IWHMRKLL.js";
31
37
  import {
32
38
  require_dist
33
39
  } from "./chunk-APJ265NV.js";
34
40
  import {
35
41
  clioConfigDir
36
42
  } from "./chunk-BNAZZHFG.js";
37
- import {
38
- resolvePackageRoot
39
- } from "./chunk-IWHMRKLL.js";
40
43
  import {
41
44
  __toESM,
42
45
  init_esm_shims
43
46
  } from "./chunk-3R73A4XB.js";
44
47
 
45
- // src/domains/agents/result-contract.ts
46
- init_esm_shims();
47
- import { createHash } from "node:crypto";
48
- import path from "node:path";
49
-
50
- // src/core/json-payload.ts
51
- init_esm_shims();
52
- function jsonPayloadCandidates(text) {
53
- const trimmed = text.trim();
54
- const candidates = [trimmed];
55
- const fenced = /```[A-Za-z0-9_-]*\s*\n?([\s\S]*?)```/.exec(trimmed)?.[1]?.trim();
56
- if (fenced !== void 0 && fenced.length > 0) candidates.push(fenced);
57
- const start = trimmed.indexOf("{");
58
- const end = trimmed.lastIndexOf("}");
59
- if (start >= 0 && end > start) candidates.push(trimmed.slice(start, end + 1));
60
- return candidates;
61
- }
62
- function parseJsonObjectPayload(text) {
63
- let parsedSomething = false;
64
- for (const candidate of jsonPayloadCandidates(text)) {
65
- let value;
66
- try {
67
- value = JSON.parse(candidate);
68
- } catch {
69
- continue;
70
- }
71
- parsedSomething = true;
72
- if (value === null || typeof value !== "object" || Array.isArray(value)) continue;
73
- return { ok: true, value };
74
- }
75
- return { ok: false, reason: parsedSomething ? "not-object" : "not-json" };
76
- }
77
-
78
- // src/domains/agents/result-contract.ts
79
- function canonical(value) {
80
- if (value === null) return "null";
81
- if (typeof value === "string" || typeof value === "boolean") return JSON.stringify(value);
82
- if (typeof value === "number") {
83
- if (!Number.isFinite(value)) throw new Error("result contract cannot digest non-finite numbers");
84
- return JSON.stringify(value);
85
- }
86
- if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
87
- if (typeof value === "object") {
88
- const record = value;
89
- return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${canonical(record[key])}`).join(",")}}`;
90
- }
91
- throw new Error(`result contract cannot digest ${typeof value}`);
92
- }
93
- function digest(value) {
94
- return createHash("sha256").update(canonical(value), "utf8").digest("hex");
95
- }
96
- function resultContractDigest(contract) {
97
- return digest(contract);
98
- }
99
- function resultContractSourceId(contract) {
100
- return `agent-result-contract:${contract.kind}:${resultContractDigest(contract)}`;
101
- }
102
- function failure(contract, quality, reason) {
103
- return {
104
- conformance: "fail",
105
- quality,
106
- sourceId: resultContractSourceId(contract),
107
- validatorDigest: digest({ contract, reason }),
108
- reason
109
- };
110
- }
111
- function success(contract, quality, value, extra = {}) {
112
- return {
113
- conformance: "pass",
114
- quality,
115
- sourceId: resultContractSourceId(contract),
116
- validatorDigest: digest({ contract, value }),
117
- ...extra
118
- };
119
- }
120
- function parseJson(output) {
121
- if (output === null || output.trim().length === 0) return { ok: false, reason: "missing final result" };
122
- const parsed = parseJsonObjectPayload(output);
123
- if (parsed.ok) return parsed;
124
- return {
125
- ok: false,
126
- reason: parsed.reason === "not-object" ? "result must be a JSON object" : "result must be valid JSON"
127
- };
128
- }
129
- function hasOnlyKeys(value, keys) {
130
- const allowed = new Set(keys);
131
- return Object.keys(value).every((key) => allowed.has(key));
132
- }
133
- function string(value) {
134
- return typeof value === "string" && value.trim().length > 0;
135
- }
136
- function parseFindings(value) {
137
- if (!Array.isArray(value)) return null;
138
- const findings = [];
139
- for (const entry of value) {
140
- if (entry === null || typeof entry !== "object" || Array.isArray(entry)) return null;
141
- const finding = entry;
142
- const line = finding.line;
143
- if (!hasOnlyKeys(finding, ["claim", "path", "line"]) || !string(finding.claim) || !string(finding.path) || typeof line !== "number" || !Number.isSafeInteger(line) || line < 1) {
144
- return null;
145
- }
146
- findings.push({ claim: finding.claim, path: finding.path, line });
147
- }
148
- return findings;
149
- }
150
- var RESULT_CONTRACT_KINDS = [
151
- "architect-plan",
152
- "scout-report",
153
- "verifier-report",
154
- "debugger-report",
155
- "research-report",
156
- "mutation-report",
157
- "provenance-report",
158
- "external-delegation"
159
- ];
160
- function parseSubtasks(value) {
161
- if (!Array.isArray(value) || value.length > 4) return null;
162
- const subtasks = [];
163
- const ids = /* @__PURE__ */ new Set();
164
- for (const entry of value) {
165
- if (entry === null || typeof entry !== "object" || Array.isArray(entry)) return null;
166
- const subtask = entry;
167
- if (!hasOnlyKeys(subtask, ["id", "task", "dependencies", "expectedResultContract", "requestedAuthority"]) || !string(subtask.id) || !/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/u.test(subtask.id) || ids.has(subtask.id) || !string(subtask.task) || Buffer.byteLength(subtask.task, "utf8") > 4096 || !Array.isArray(subtask.dependencies) || subtask.dependencies.length > 4 || subtask.dependencies.some((dependency) => !string(dependency)) || new Set(subtask.dependencies).size !== subtask.dependencies.length || !RESULT_CONTRACT_KINDS.includes(subtask.expectedResultContract) || !AGENT_AUTOMATION_AUTHORITIES.includes(subtask.requestedAuthority)) {
168
- return null;
169
- }
170
- ids.add(subtask.id);
171
- subtasks.push({
172
- id: subtask.id,
173
- task: subtask.task,
174
- dependencies: [...subtask.dependencies],
175
- expectedResultContract: subtask.expectedResultContract,
176
- requestedAuthority: subtask.requestedAuthority
177
- });
178
- }
179
- for (const subtask of subtasks) {
180
- if (subtask.dependencies.some((dependency) => dependency === subtask.id || !ids.has(dependency))) return null;
181
- }
182
- const remaining = new Set(ids);
183
- const completed = /* @__PURE__ */ new Set();
184
- while (remaining.size > 0) {
185
- const ready = subtasks.filter(
186
- (subtask) => remaining.has(subtask.id) && subtask.dependencies.every((dependency) => completed.has(dependency))
187
- );
188
- if (ready.length === 0) return null;
189
- for (const subtask of ready) {
190
- remaining.delete(subtask.id);
191
- completed.add(subtask.id);
192
- }
193
- }
194
- return subtasks;
195
- }
196
- function isContextHandbookResult(value) {
197
- if (!hasOnlyKeys(value, ["projectName", "identity", "conventions", "invariants", "sections"])) return false;
198
- if (!string(value.projectName) || !string(value.identity)) return false;
199
- if (!Array.isArray(value.conventions) || value.conventions.some((entry) => !string(entry))) return false;
200
- if (!Array.isArray(value.invariants) || value.invariants.some((entry) => !string(entry))) return false;
201
- if (!Array.isArray(value.sections)) return false;
202
- return value.sections.every((entry) => {
203
- if (entry === null || typeof entry !== "object" || Array.isArray(entry)) return false;
204
- const section = entry;
205
- return hasOnlyKeys(section, ["title", "body"]) && string(section.title) && string(section.body);
206
- });
207
- }
208
- function validateContextHandbook(contract, output) {
209
- const parsed = parseJson(output);
210
- if (!parsed.ok) return failure(contract, "fail", parsed.reason);
211
- if (!isContextHandbookResult(parsed.value)) {
212
- return failure(
213
- contract,
214
- "fail",
215
- "context handbook result must carry projectName, identity, conventions[], invariants[], and sections[{title, body}] and nothing else"
216
- );
217
- }
218
- return success(contract, "unmeasured", parsed.value);
219
- }
220
- function salvageScoutClaims(value) {
221
- const grounded = [];
222
- const ungrounded = [];
223
- if (!Array.isArray(value)) return { grounded, ungrounded };
224
- for (const entry of value) {
225
- if (entry === null || typeof entry !== "object" || Array.isArray(entry)) continue;
226
- const finding = entry;
227
- if (!string(finding.claim)) continue;
228
- const line = finding.line;
229
- if (string(finding.path) && typeof line === "number" && Number.isSafeInteger(line) && line >= 1) {
230
- grounded.push({ claim: finding.claim, path: finding.path, line });
231
- continue;
232
- }
233
- ungrounded.push(finding.claim);
234
- }
235
- return { grounded, ungrounded };
236
- }
237
- function degradedScout(contract, value, reason) {
238
- const salvaged = salvageScoutClaims(value.findings);
239
- if (salvaged.grounded.length === 0 && salvaged.ungrounded.length === 0) return null;
240
- const degradedReason = `${reason} (accepted as a degraded reconnaissance result; findings are leads, not validation evidence)`;
241
- const scout = {
242
- findings: salvaged.grounded,
243
- citations: salvaged.grounded.map(({ path: citedPath, line }) => ({ path: citedPath, line })),
244
- needsSplit: false,
245
- proposedSubtasks: [],
246
- ungroundedClaims: salvaged.ungrounded,
247
- degradedReason
248
- };
249
- return success(contract, "unmeasured", scout, { scout, reason: degradedReason });
250
- }
251
- function validateScout(contract, output) {
252
- const parsed = parseJson(output);
253
- if (!parsed.ok) return failure(contract, "fail", parsed.reason);
254
- const value = parsed.value;
255
- const degrade = (reason) => degradedScout(contract, value, reason) ?? failure(contract, "fail", reason);
256
- if (!hasOnlyKeys(value, ["findings", "needsSplit", "proposedSubtasks"])) {
257
- return degrade("Scout result has unknown fields");
258
- }
259
- const findings = parseFindings(value.findings);
260
- const proposedSubtasks = parseSubtasks(value.proposedSubtasks);
261
- if (findings === null || typeof value.needsSplit !== "boolean" || proposedSubtasks === null) {
262
- return degrade(
263
- "Scout result must carry findings as {claim, path, line} objects, needsSplit, and 0..4 typed proposed subtasks"
264
- );
265
- }
266
- if (value.needsSplit !== proposedSubtasks.length > 0) {
267
- return degrade("Scout needsSplit must agree with proposedSubtasks");
268
- }
269
- if (findings.length === 0 && !value.needsSplit) {
270
- return degrade("Scout result must carry at least one cited finding, or set needsSplit");
271
- }
272
- if (value.needsSplit && findings.length > 0) {
273
- return degrade("Scout split recommendations carry typed subtasks instead of findings");
274
- }
275
- const scout = {
276
- findings,
277
- citations: findings.map(({ path: citedPath, line }) => ({ path: citedPath, line })),
278
- needsSplit: value.needsSplit,
279
- proposedSubtasks
280
- };
281
- return success(contract, "pass", scout, { scout });
282
- }
283
- function parseChecks(value) {
284
- if (!Array.isArray(value) || value.length === 0) return null;
285
- const checks = [];
286
- for (const entry of value) {
287
- if (entry === null || typeof entry !== "object" || Array.isArray(entry)) return null;
288
- const check = entry;
289
- if (!hasOnlyKeys(check, ["name", "passed", "evidence"]) || !string(check.name) || typeof check.passed !== "boolean" || !string(check.evidence)) {
290
- return null;
291
- }
292
- checks.push({ name: check.name, passed: check.passed, evidence: check.evidence });
293
- }
294
- return checks;
295
- }
296
- function validateScoutCitation(input, citation) {
297
- const cwd = path.resolve(input.cwd);
298
- const citedPath = path.resolve(cwd, citation.path);
299
- const relative = path.relative(cwd, citedPath);
300
- if (relative === "" || relative.startsWith(`..${path.sep}`) || relative === ".." || path.isAbsolute(relative)) {
301
- return { ok: false, reason: `Scout citation path escapes the workspace: ${citation.path}` };
302
- }
303
- const content = input.filesystem.readFile(citedPath);
304
- if (content === null) return { ok: false, reason: `Scout citation cannot be read: ${citation.path}` };
305
- const lineCount = content.split(/\r\n|\r|\n/u).length;
306
- if (citation.line > lineCount) {
307
- return { ok: false, reason: `Scout citation is past end of file: ${citation.path}:${citation.line}` };
308
- }
309
- if (input.observedReadRanges !== void 0) {
310
- const spans = input.observedReadRanges.get(citedPath) ?? [];
311
- if (!spans.some(([start, end]) => citation.line >= start && citation.line <= end)) {
312
- const observed = spans.length === 0 ? "this run never read that file" : `this run read only ${spans.map(([start, end]) => `${start}-${end}`).join(", ")}`;
313
- return {
314
- ok: false,
315
- reason: `Scout citation is not grounded in a live read: ${citation.path}:${citation.line} (${observed})`
316
- };
317
- }
318
- }
319
- return {
320
- ok: true,
321
- evidence: { ...citation, contentDigest: createHash("sha256").update(content, "utf8").digest("hex") }
322
- };
323
- }
324
- function validateScoutCitations(input, citations) {
325
- const evidence = [];
326
- for (const citation of citations) {
327
- const checked = validateScoutCitation(input, citation);
328
- if (!checked.ok) return checked;
329
- evidence.push(checked.evidence);
330
- }
331
- return { ok: true, evidence };
332
- }
333
- function groundDegradedScout(contract, input, scout, degradedReason) {
334
- const grounded = [];
335
- const evidence = [];
336
- const demoted = [];
337
- for (const finding of scout.findings) {
338
- const checked = validateScoutCitation(input, { path: finding.path, line: finding.line });
339
- if (checked.ok) {
340
- grounded.push(finding);
341
- evidence.push(checked.evidence);
342
- continue;
343
- }
344
- demoted.push(finding.claim);
345
- }
346
- const degraded = {
347
- findings: grounded,
348
- citations: grounded.map(({ path: citedPath, line }) => ({ path: citedPath, line })),
349
- needsSplit: false,
350
- proposedSubtasks: [],
351
- ungroundedClaims: [...scout.ungroundedClaims ?? [], ...demoted],
352
- degradedReason
353
- };
354
- return success(contract, "unmeasured", { scout: degraded, evidence }, { scout: degraded, reason: degradedReason });
355
- }
356
- function validateVerifier(contract, output) {
357
- const parsed = parseJson(output);
358
- if (!parsed.ok) return failure(contract, "fail", parsed.reason);
359
- const value = parsed.value;
360
- if (!hasOnlyKeys(value, ["verdict", "checks"]) || value.verdict !== "pass" && value.verdict !== "fail") {
361
- return failure(contract, "fail", "Verifier result must carry pass or fail verdict and checks");
362
- }
363
- const checks = parseChecks(value.checks);
364
- if (checks === null || value.verdict === "pass" !== checks.every((check) => check.passed)) {
365
- return failure(contract, "fail", "Verifier verdict must agree with every typed check");
366
- }
367
- const verifier = { verdict: value.verdict, checks };
368
- return success(contract, value.verdict, verifier, { verifier });
369
- }
370
- function parseVerifierResult(output) {
371
- const validation = validateVerifier({ kind: "verifier-report" }, output);
372
- return validation.verifier ?? null;
373
- }
374
- function validateCodeReport(contract, output) {
375
- const parsed = parseJson(output);
376
- if (!parsed.ok) return failure(contract, "unmeasured", parsed.reason);
377
- const value = parsed.value;
378
- if (!hasOnlyKeys(value, ["passed", "exitCode", "checks", "artifactPaths", "outputExcerpt"]) || typeof value.passed !== "boolean" || typeof value.exitCode !== "number" || !Number.isSafeInteger(value.exitCode) || typeof value.outputExcerpt !== "string" || !Array.isArray(value.artifactPaths) || value.artifactPaths.some((entry) => !string(entry))) {
379
- return failure(
380
- contract,
381
- "unmeasured",
382
- "Code result must carry passed, integer exitCode, checks, artifactPaths, and outputExcerpt"
383
- );
384
- }
385
- const checks = parseChecks(value.checks);
386
- if (checks === null) return failure(contract, "unmeasured", "Code result must carry typed checks");
387
- if (value.passed !== (value.exitCode === 0) || value.passed !== checks.every((check) => check.passed)) {
388
- return failure(contract, "unmeasured", "Code result passed must agree with its exit code and every check");
389
- }
390
- return success(contract, "unmeasured", value);
391
- }
392
- var RESULT_COMMIT_MESSAGE_MAX_BYTES = 1e3;
393
- var AUTHORSHIP_FIELDS = ["commitMessage", "summary"];
394
- function hasControlCharacters(value) {
395
- for (const character of value) {
396
- const code = character.codePointAt(0) ?? 0;
397
- if (code === 127) return true;
398
- if (code < 32 && character !== "\n" && character !== "\r" && character !== " ") return true;
399
- }
400
- return false;
401
- }
402
- function normalizeAuthored(value) {
403
- return value.replace(/\r\n/gu, "\n").replace(/\r/gu, "\n").trim();
404
- }
405
- function validateAuthorship(value) {
406
- for (const field of AUTHORSHIP_FIELDS) {
407
- const raw = value[field];
408
- if (raw === void 0 || raw === null) continue;
409
- if (typeof raw !== "string") return `${field} must be a string when present`;
410
- if (raw.trim().length === 0) continue;
411
- if (Buffer.byteLength(raw, "utf8") > RESULT_COMMIT_MESSAGE_MAX_BYTES) {
412
- return `${field} must be at most ${RESULT_COMMIT_MESSAGE_MAX_BYTES} bytes`;
413
- }
414
- if (hasControlCharacters(raw)) return `${field} must not contain control characters`;
415
- }
416
- return null;
417
- }
418
- function resultContractAuthorship(contract, output) {
419
- const empty = { commitMessage: null, summary: null };
420
- if (contract.kind !== "mutation-report" && contract.kind !== "architect-plan") return empty;
421
- const parsed = parseJson(output);
422
- if (!parsed.ok || validateAuthorship(parsed.value) !== null) return empty;
423
- const read = (field) => {
424
- const raw = parsed.value[field];
425
- if (typeof raw !== "string") return null;
426
- const normalized = normalizeAuthored(raw);
427
- return normalized.length === 0 ? null : normalized;
428
- };
429
- return { commitMessage: read("commitMessage"), summary: read("summary") };
430
- }
431
- function validateDebugger(contract, output) {
432
- const parsed = parseJson(output);
433
- if (!parsed.ok) return failure(contract, "unmeasured", parsed.reason);
434
- const value = parsed.value;
435
- if (!hasOnlyKeys(value, ["diagnosis", "reproduction", "evidence"]) || !string(value.diagnosis) || value.reproduction !== "reproduced" && value.reproduction !== "not-reproduced" && value.reproduction !== "unknown" || !Array.isArray(value.evidence) || value.evidence.some((entry) => !string(entry))) {
436
- return failure(
437
- contract,
438
- "unmeasured",
439
- "Debugger result must carry diagnosis, reproduction status, and evidence without a verdict"
440
- );
441
- }
442
- return success(contract, "unmeasured", value);
443
- }
444
- function validateResearch(contract, output, networkAllowed) {
445
- const parsed = parseJson(output);
446
- if (!parsed.ok) return failure(contract, "unmeasured", parsed.reason);
447
- const value = parsed.value;
448
- if (!hasOnlyKeys(value, ["source", "findings"]) || value.source !== "local" && value.source !== "external" || !Array.isArray(value.findings)) {
449
- return failure(
450
- contract,
451
- "unmeasured",
452
- "Research result must distinguish local or external sources and carry findings"
453
- );
454
- }
455
- if (value.source === "external" && !networkAllowed) {
456
- return failure(contract, "unmeasured", "external research requires an allowed network posture");
457
- }
458
- for (const finding of value.findings) {
459
- if (finding === null || typeof finding !== "object" || Array.isArray(finding)) {
460
- return failure(contract, "unmeasured", "Research findings must be objects");
461
- }
462
- const record = finding;
463
- if (!hasOnlyKeys(record, ["claim", "evidence"]) || !string(record.claim) || !string(record.evidence)) {
464
- return failure(contract, "unmeasured", "Research findings must carry claim and evidence");
465
- }
466
- }
467
- return success(contract, "unmeasured", value);
468
- }
469
- function describeWriteSet(effects, cwd) {
470
- if (effects.mutatedPaths.size === 0) return "this run wrote nothing";
471
- const written = [...effects.mutatedPaths].map((target) => path.relative(cwd, target) || target).sort().slice(0, MUTATION_WRITE_SET_REASON_LIMIT);
472
- const more = effects.mutatedPaths.size - written.length;
473
- return `this run wrote ${written.join(", ")}${more > 0 ? ` (+${more} more)` : ""}`;
474
- }
475
- var MUTATION_WRITE_SET_REASON_LIMIT = 8;
476
- function pathIsPresent(filesystem, target) {
477
- if (filesystem.pathExists === void 0) return true;
478
- return filesystem.pathExists(target);
479
- }
480
- var MUTATION_VALIDATION_EXAMPLE = '{"name":"npm test","passed":true,"evidence":"exit 0"}';
481
- function mutationValidationsReason(value) {
482
- const empty = Array.isArray(value) && value.length === 0;
483
- if (empty) {
484
- return `Mutation result must carry typed validation results: validations was empty. Emit one entry per check this run actually made, each shaped like ${MUTATION_VALIDATION_EXAMPLE}. A run that only read files still names the read and cites what it saw.`;
485
- }
486
- return `Mutation result must carry typed validation results: every validations entry is shaped like ${MUTATION_VALIDATION_EXAMPLE}, with a string name, a boolean passed, a string evidence, and no other keys.`;
487
- }
488
- function validateMutation(contract, input) {
489
- const parsed = parseJson(input.output);
490
- if (!parsed.ok) return failure(contract, "unmeasured", parsed.reason);
491
- const value = parsed.value;
492
- if (!hasOnlyKeys(value, ["mutatedPaths", "validations", "commitMessage", "summary"]) || !Array.isArray(value.mutatedPaths) || value.mutatedPaths.some((entry) => !string(entry))) {
493
- return failure(contract, "unmeasured", "Mutation result must carry mutatedPaths and validations");
494
- }
495
- const authorship = validateAuthorship(value);
496
- if (authorship !== null) return failure(contract, "unmeasured", authorship);
497
- const validations = parseChecks(value.validations);
498
- if (validations === null) return failure(contract, "unmeasured", mutationValidationsReason(value.validations));
499
- const reportedFailure = !validations.every((check) => check.passed);
500
- const effects = input.observedRunEffects;
501
- if (effects === void 0) return success(contract, reportedFailure ? "fail" : "pass", value);
502
- const cwd = path.resolve(input.cwd);
503
- let unverifiedMutation = false;
504
- for (const reported of value.mutatedPaths) {
505
- const target = path.resolve(cwd, reported);
506
- if (effects.mutatedPaths.has(target)) continue;
507
- if (effects.failedMutationPaths.has(target)) {
508
- return failure(
509
- contract,
510
- "unmeasured",
511
- `Mutation result names a path whose only write this run attempted was refused: ${reported} (${describeWriteSet(effects, cwd)})`
512
- );
513
- }
514
- if (pathIsPresent(input.filesystem, target)) {
515
- unverifiedMutation = true;
516
- continue;
517
- }
518
- return failure(
519
- contract,
520
- "unmeasured",
521
- `Mutation result names a path this run never wrote and that does not exist: ${reported} (${describeWriteSet(effects, cwd)})`
522
- );
523
- }
524
- if (reportedFailure) return success(contract, "fail", value);
525
- const measured = !unverifiedMutation && effects.validationCommands.size > 0;
526
- return success(contract, measured ? "pass" : "unmeasured", value);
527
- }
528
- function validateProvenance(contract, output) {
529
- const parsed = parseJson(output);
530
- if (!parsed.ok) return failure(contract, "unmeasured", parsed.reason);
531
- const value = parsed.value;
532
- if (!hasOnlyKeys(value, ["confirmedFacts", "missingEvidence", "nextInspections"]) || ![value.confirmedFacts, value.missingEvidence, value.nextInspections].every(
533
- (entry) => Array.isArray(entry) && entry.every((item) => string(item))
534
- )) {
535
- return failure(
536
- contract,
537
- "unmeasured",
538
- "Provenance result must carry confirmedFacts, missingEvidence, and nextInspections"
539
- );
540
- }
541
- return success(contract, "unmeasured", value);
542
- }
543
- function validateArchitect(contract, input) {
544
- const artifactPath = path.resolve(input.cwd, contract.path);
545
- const content = input.filesystem.readFile(artifactPath);
546
- if (content === null || content.trim().length === 0) {
547
- return failure(contract, "unmeasured", `required plan artifact is missing or empty: ${contract.path}`);
548
- }
549
- return success(contract, "unmeasured", {
550
- path: contract.path,
551
- artifactDigest: createHash("sha256").update(content, "utf8").digest("hex")
552
- });
553
- }
554
- function parseScoutResult(output) {
555
- const validation = validateScout({ kind: "scout-report" }, output);
556
- if (validation.conformance !== "pass" || validation.scout === void 0) return null;
557
- return validation.scout.degradedReason === void 0 ? validation.scout : null;
558
- }
559
- function validateResultContract(input) {
560
- switch (input.contract.kind) {
561
- case "architect-plan":
562
- return validateArchitect(input.contract, input);
563
- case "scout-report": {
564
- const validation = validateScout(input.contract, input.output);
565
- if (validation.scout === void 0) return validation;
566
- const degradedReason = validation.scout.degradedReason;
567
- if (degradedReason !== void 0) {
568
- return groundDegradedScout(input.contract, input, validation.scout, degradedReason);
569
- }
570
- const citations = validateScoutCitations(input, validation.scout.citations);
571
- return citations.ok ? success(
572
- input.contract,
573
- "pass",
574
- { scout: validation.scout, evidence: citations.evidence },
575
- { scout: validation.scout }
576
- ) : failure(input.contract, "fail", citations.reason);
577
- }
578
- case "verifier-report":
579
- return validateVerifier(input.contract, input.output);
580
- case "debugger-report":
581
- return validateDebugger(input.contract, input.output);
582
- case "research-report":
583
- return validateResearch(input.contract, input.output, input.networkAllowed);
584
- case "mutation-report":
585
- return validateMutation(input.contract, input);
586
- case "provenance-report":
587
- return validateProvenance(input.contract, input.output);
588
- case "external-delegation":
589
- return success(input.contract, "unmeasured", { external: true });
590
- case "artifact-report":
591
- return success(input.contract, "unmeasured", { artifact: true });
592
- case "context-handbook":
593
- return validateContextHandbook(input.contract, input.output);
594
- case "code-report":
595
- return validateCodeReport(input.contract, input.output);
596
- }
597
- }
598
- function validateRecipeResult(input) {
599
- if (input.contract === null) return null;
600
- if (!input.reachedTerminalResult) {
601
- return {
602
- applicable: false,
603
- fact: {
604
- sourceId: resultContractSourceId(input.contract),
605
- validatorDigest: digest({ contract: input.contract, reached: false }),
606
- conformance: "not-reached",
607
- quality: "unmeasured"
608
- }
609
- };
610
- }
611
- const validation = validateResultContract({
612
- contract: input.contract,
613
- output: input.output,
614
- cwd: input.cwd,
615
- networkAllowed: input.networkAllowed,
616
- filesystem: input.filesystem,
617
- ...input.observedRunEffects !== void 0 ? { observedRunEffects: input.observedRunEffects } : {}
618
- });
619
- return {
620
- applicable: true,
621
- validation,
622
- fact: {
623
- sourceId: validation.sourceId,
624
- validatorDigest: validation.validatorDigest,
625
- conformance: validation.conformance,
626
- quality: validation.quality
627
- }
628
- };
629
- }
630
- var RESULT_CONTRACT_REPAIR_LIMIT = 2;
631
- var RESULT_CONTRACT_ANCHOR_LIMIT = 12;
632
- function resultContractShape(contract) {
633
- switch (contract.kind) {
634
- case "architect-plan":
635
- return `a plan artifact written to ${contract.path}, then optionally {"commitMessage":"...","summary":"..."} describing it`;
636
- case "scout-report":
637
- return '{"findings":[{"claim":"what you observed","path":"src/file.ts","line":1}],"needsSplit":false,"proposedSubtasks":[]} or {"findings":[],"needsSplit":true,"proposedSubtasks":[{"id":"inspect","task":"Inspect the boundary","dependencies":[],"expectedResultContract":"scout-report","requestedAuthority":"read-only"}]} or, if you cannot produce a citation you are sure of, at least {"findings":[{"claim":"what you observed"}]}, which is accepted as an ungrounded lead rather than losing the run';
638
- case "verifier-report":
639
- return '{"verdict":"pass","checks":[{"name":"npm run typecheck","passed":true,"evidence":"exit 0"}]}';
640
- case "debugger-report":
641
- return '{"diagnosis":"...","reproduction":"reproduced","evidence":["..."]}';
642
- case "research-report":
643
- return '{"source":"local","findings":[{"claim":"...","evidence":"..."}]}';
644
- case "mutation-report":
645
- return '{"mutatedPaths":["src/file.ts"],"validations":[{"name":"npm test","passed":true,"evidence":"exit 0"}],"commitMessage":"optional: the commit message for this change","summary":"optional: one line"}';
646
- case "provenance-report":
647
- return '{"confirmedFacts":["..."],"missingEvidence":["..."],"nextInspections":["..."]}';
648
- case "external-delegation":
649
- return "any final text";
650
- case "artifact-report":
651
- return "any final text; the artifact you wrote at the location the task named is the result";
652
- case "context-handbook":
653
- return '{"projectName":"string","identity":"one sentence","conventions":[],"invariants":[],"sections":[{"title":"Architecture","body":"markdown that cites `real/path.ts` tokens"}]}';
654
- case "code-report":
655
- return '{"passed":false,"exitCode":1,"checks":[{"name":"test","passed":false,"evidence":"exit 1"}],"artifactPaths":["/path/command.log"],"outputExcerpt":"..."}';
656
- }
657
- }
658
- function resultContractRepairMessage(input) {
659
- const last = input.attempt >= RESULT_CONTRACT_REPAIR_LIMIT;
660
- const lines = [
661
- last ? "FINAL RESULT REQUIRED IN THIS RESPONSE. Your previous response still did not satisfy this run's result contract." : "Your previous response did not satisfy this run's result contract.",
662
- `Validator reason: ${input.reason}`,
663
- input.toolsAvailable === true ? "You may use the admitted tools to repair this validator failure, then emit the required terminal result." : "Tool use is over. Answer from the evidence you already gathered.",
664
- `Emit exactly this shape and nothing else: ${resultContractShape(input.contract)}`,
665
- "Do not add prose, code fences, or commentary around it. Do not describe work you intend to do next."
666
- ];
667
- if (input.anchors.length > 0) {
668
- lines.push(
669
- "",
670
- "Locations you read successfully in this run (use these exact path:line values):",
671
- ...input.anchors.slice(-RESULT_CONTRACT_ANCHOR_LIMIT).map((anchor) => `- ${anchor}`)
672
- );
673
- }
674
- return lines.join("\n");
675
- }
676
- var RESULT_CONTRACT_REPAIR_TOOL = "result_contract";
677
- function resultContractRepairMessages(input, origin) {
678
- const id = `clio-result-contract-repair-${input.attempt}`;
679
- const timestamp = Date.now();
680
- return [
681
- {
682
- role: "assistant",
683
- content: [{ type: "toolCall", id, name: RESULT_CONTRACT_REPAIR_TOOL, arguments: {} }],
684
- stopReason: "toolUse",
685
- usage: {
686
- input: 0,
687
- output: 0,
688
- cacheRead: 0,
689
- cacheWrite: 0,
690
- totalTokens: 0,
691
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
692
- },
693
- ...origin,
694
- timestamp
695
- },
696
- {
697
- role: "toolResult",
698
- toolCallId: id,
699
- toolName: RESULT_CONTRACT_REPAIR_TOOL,
700
- content: [{ type: "text", text: resultContractRepairMessage(input) }],
701
- isError: true,
702
- timestamp
703
- }
704
- ];
705
- }
706
- function parseResultContract(value, sourcePath) {
707
- if (value === null || typeof value !== "object" || Array.isArray(value)) {
708
- throw new Error(`agent recipe: ${sourcePath}: resultContract must be an object`);
709
- }
710
- const record = value;
711
- if (typeof record.kind !== "string") throw new Error(`agent recipe: ${sourcePath}: resultContract.kind is required`);
712
- const keys = Object.keys(record);
713
- const only = (...allowed) => keys.every((key) => allowed.includes(key));
714
- if (record.kind === "architect-plan") {
715
- if (!only("kind", "path") || !string(record.path)) {
716
- throw new Error(`agent recipe: ${sourcePath}: architect-plan requires only non-empty path`);
717
- }
718
- if (path.isAbsolute(record.path) || record.path.split(/[\\/]/u).includes("..")) {
719
- throw new Error(`agent recipe: ${sourcePath}: architect-plan path must be workspace-relative`);
720
- }
721
- return { kind: "architect-plan", path: record.path };
722
- }
723
- const kinds = [
724
- "scout-report",
725
- "verifier-report",
726
- "debugger-report",
727
- "research-report",
728
- "mutation-report",
729
- "provenance-report",
730
- "external-delegation",
731
- "artifact-report",
732
- "context-handbook"
733
- ];
734
- if (!kinds.includes(record.kind) || !only("kind")) {
735
- throw new Error(`agent recipe: ${sourcePath}: resultContract.kind is unsupported or has unknown keys`);
736
- }
737
- return { kind: record.kind };
738
- }
739
-
740
48
  // src/domains/safety/finish-contract.ts
741
49
  init_esm_shims();
742
50
  var FINISH_CONTRACT_ADVISORY_MESSAGE = "[Clio Coder] finish-contract advisory: you changed files this turn without recording validation evidence or an explicit limitation. Run a verification command or state what could not be verified.";
@@ -786,7 +94,7 @@ function mutatingReceipts(recent) {
786
94
  for (const entry of recent) {
787
95
  const bashMutation = bashExecutionMutationPaths(entry);
788
96
  if (bashMutation !== null) {
789
- for (const path5 of bashMutation) pushPath(paths, seen, path5);
97
+ for (const path4 of bashMutation) pushPath(paths, seen, path4);
790
98
  continue;
791
99
  }
792
100
  const call = mutatingToolCall(entry);
@@ -798,7 +106,7 @@ function mutatingReceipts(recent) {
798
106
  if (resultId !== null) {
799
107
  const candidate = mutationCalls.get(resultId);
800
108
  if (candidate !== void 0) {
801
- for (const path5 of candidate.paths) pushPath(paths, seen, path5);
109
+ for (const path4 of candidate.paths) pushPath(paths, seen, path4);
802
110
  }
803
111
  }
804
112
  }
@@ -833,10 +141,10 @@ function bashExecutionMutationPaths(entry) {
833
141
  if (record.cancelled === true || record.exitCode !== 0) return null;
834
142
  return [...extractCommandWriteTargets(record.command), ...extractCommandDeleteTargets(record.command)];
835
143
  }
836
- function pushPath(paths, seen, path5) {
837
- if (path5.length === 0 || seen.has(path5)) return;
838
- seen.add(path5);
839
- paths.push(path5);
144
+ function pushPath(paths, seen, path4) {
145
+ if (path4.length === 0 || seen.has(path4)) return;
146
+ seen.add(path4);
147
+ paths.push(path4);
840
148
  }
841
149
  function collectValidationEvidence(recent) {
842
150
  const evidence = [];
@@ -977,8 +285,8 @@ function typedValidationSummary(toolName, payload) {
977
285
  if (toolName === "verify") {
978
286
  const check = typeof args?.check === "string" ? args.check.trim() : "";
979
287
  if (check === "frontend") {
980
- const path5 = typeof args?.path === "string" && args.path.trim().length > 0 ? args.path.trim() : "artifact";
981
- return `verify frontend ${path5}`;
288
+ const path4 = typeof args?.path === "string" && args.path.trim().length > 0 ? args.path.trim() : "artifact";
289
+ return `verify frontend ${path4}`;
982
290
  }
983
291
  if (isVerificationScriptName(check)) return `npm run ${check}`;
984
292
  if (isProjectVerifierCheckId(check)) return `verify ${check}`;
@@ -1059,11 +367,11 @@ function protectedArtifactEvidence(entry) {
1059
367
  const record = asRecord(entry);
1060
368
  if (record?.kind !== "protectedArtifact" || record.action !== "protect") return null;
1061
369
  const artifact = asRecord(record.artifact);
1062
- const path5 = typeof artifact?.path === "string" && artifact.path.trim().length > 0 ? artifact.path.trim() : null;
1063
- if (path5 === null) return null;
370
+ const path4 = typeof artifact?.path === "string" && artifact.path.trim().length > 0 ? artifact.path.trim() : null;
371
+ if (path4 === null) return null;
1064
372
  const evidence = {
1065
373
  kind: "protected_artifact",
1066
- summary: `protected artifact recorded: ${path5}`
374
+ summary: `protected artifact recorded: ${path4}`
1067
375
  };
1068
376
  const turnId = turnIdOf(entry);
1069
377
  if (turnId !== null) evidence.turnId = turnId;
@@ -1107,22 +415,22 @@ function asRecord(value) {
1107
415
  // src/domains/safety/path-policy.ts
1108
416
  init_esm_shims();
1109
417
  import { homedir } from "node:os";
1110
- import path2 from "node:path";
418
+ import path from "node:path";
1111
419
  var ORDERED_KINDS = ["zeroAccessPaths", "readOnlyPaths", "noWritePaths", "noDeletePaths"];
1112
420
  function isSameOrDescendant(candidatePath, policyPath) {
1113
- const candidate = path2.resolve(candidatePath);
1114
- const policy = path2.resolve(policyPath);
1115
- const relative = path2.relative(policy, candidate);
1116
- return relative === "" || !relative.startsWith("..") && !path2.isAbsolute(relative);
421
+ const candidate = path.resolve(candidatePath);
422
+ const policy = path.resolve(policyPath);
423
+ const relative = path.relative(policy, candidate);
424
+ return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
1117
425
  }
1118
426
  function expandTilde(rawPath) {
1119
427
  if (rawPath === "~") return homedir();
1120
- if (rawPath.startsWith("~/")) return path2.join(homedir(), rawPath.slice(2));
428
+ if (rawPath.startsWith("~/")) return path.join(homedir(), rawPath.slice(2));
1121
429
  return rawPath;
1122
430
  }
1123
431
  function normalizePolicyEntry(rawPath, root) {
1124
432
  const expanded = expandTilde(rawPath.trim());
1125
- const resolved = path2.isAbsolute(expanded) ? path2.resolve(expanded) : path2.resolve(root, expanded);
433
+ const resolved = path.isAbsolute(expanded) ? path.resolve(expanded) : path.resolve(root, expanded);
1126
434
  return canonicalizeExistingPath(resolved);
1127
435
  }
1128
436
  function blocksOperation(kind, operation) {
@@ -1131,7 +439,7 @@ function blocksOperation(kind, operation) {
1131
439
  return operation === "delete";
1132
440
  }
1133
441
  function compilePathPolicy(input, root = process.cwd()) {
1134
- const resolvedRoot = canonicalizeExistingPath(path2.resolve(root));
442
+ const resolvedRoot = canonicalizeExistingPath(path.resolve(root));
1135
443
  const entries = [];
1136
444
  const diagnostics = [];
1137
445
  for (const kind of ORDERED_KINDS) {
@@ -1155,10 +463,10 @@ function compilePathPolicy(input, root = process.cwd()) {
1155
463
  }
1156
464
  function evaluatePathPolicy(policy, operation, targetPath, cwd = policy.root) {
1157
465
  const expanded = expandTilde(targetPath);
1158
- const lexicalTarget = path2.isAbsolute(expanded) ? path2.resolve(expanded) : path2.resolve(cwd, expanded);
466
+ const lexicalTarget = path.isAbsolute(expanded) ? path.resolve(expanded) : path.resolve(cwd, expanded);
1159
467
  const resolvedTarget = canonicalizeExistingPath(lexicalTarget);
1160
468
  const normalizedResolvedTarget = normalizeSeparators(resolvedTarget);
1161
- const normalizedRelativeTarget = normalizeSeparators(path2.relative(policy.root, resolvedTarget));
469
+ const normalizedRelativeTarget = normalizeSeparators(path.relative(policy.root, resolvedTarget));
1162
470
  const normalizedRawTarget = normalizeSeparators(targetPath);
1163
471
  for (const entry of policy.entries) {
1164
472
  if (!blocksOperation(entry.kind, operation)) continue;
@@ -1182,9 +490,9 @@ function matchesEntry(entry, resolvedTarget, normalizedResolvedTarget, normalize
1182
490
  function compilePathPattern(rawPath, root) {
1183
491
  if (!rawPath.includes("*")) return null;
1184
492
  const expanded = expandTilde(rawPath.trim());
1185
- const source = path2.isAbsolute(expanded) ? expanded : path2.join(root, expanded);
493
+ const source = path.isAbsolute(expanded) ? expanded : path.join(root, expanded);
1186
494
  const normalized = normalizeSeparators(canonicalizePatternSource(source));
1187
- const relative = normalizeSeparators(path2.isAbsolute(expanded) ? expanded : expanded);
495
+ const relative = normalizeSeparators(path.isAbsolute(expanded) ? expanded : expanded);
1188
496
  const absolutePattern = segmentPattern(normalized);
1189
497
  const relativePattern = segmentPattern(relative);
1190
498
  return new RegExp(`(?:${absolutePattern})|(?:${relativePattern})`);
@@ -1193,24 +501,24 @@ function canonicalizePatternSource(patternPath) {
1193
501
  const wildcardIndex = patternPath.indexOf("*");
1194
502
  if (wildcardIndex === -1) return canonicalizeExistingPath(patternPath);
1195
503
  const fixedPrefix = patternPath.slice(0, wildcardIndex);
1196
- const separatorIndex = fixedPrefix.lastIndexOf(path2.sep);
504
+ const separatorIndex = fixedPrefix.lastIndexOf(path.sep);
1197
505
  if (separatorIndex === -1) return patternPath;
1198
506
  const prefix = patternPath.slice(0, separatorIndex + 1);
1199
507
  const suffix = patternPath.slice(separatorIndex + 1);
1200
- return path2.join(canonicalizeExistingPath(prefix), suffix);
508
+ return path.join(canonicalizeExistingPath(prefix), suffix);
1201
509
  }
1202
510
  function segmentPattern(rawPath) {
1203
511
  const escaped = rawPath.split("*").map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("[^/]*");
1204
512
  return `(?:^|/)${escaped}(?:$|/)`;
1205
513
  }
1206
514
  function normalizeSeparators(value) {
1207
- return value.split(path2.sep).join("/");
515
+ return value.split(path.sep).join("/");
1208
516
  }
1209
517
 
1210
518
  // src/domains/safety/policy-engine.ts
1211
519
  init_esm_shims();
1212
- import { createHash as createHash3 } from "node:crypto";
1213
- import path4 from "node:path";
520
+ import { createHash as createHash2 } from "node:crypto";
521
+ import path3 from "node:path";
1214
522
 
1215
523
  // src/domains/safety/default-path-policy.ts
1216
524
  init_esm_shims();
@@ -1332,10 +640,10 @@ function mergePathPolicyInputs(base, override) {
1332
640
  // src/domains/safety/project-policy.ts
1333
641
  init_esm_shims();
1334
642
  var import_yaml = __toESM(require_dist(), 1);
1335
- import { createHash as createHash2 } from "node:crypto";
643
+ import { createHash } from "node:crypto";
1336
644
  import { existsSync, readFileSync } from "node:fs";
1337
- import path3 from "node:path";
1338
- var POLICY_RELATIVE_PATH = path3.join(".clio-coder", "safety.yaml");
645
+ import path2 from "node:path";
646
+ var POLICY_RELATIVE_PATH = path2.join(".clio-coder", "safety.yaml");
1339
647
  var ACTION_CLASSES = /* @__PURE__ */ new Set([
1340
648
  "read",
1341
649
  "write",
@@ -1364,11 +672,11 @@ var COMMAND_KEYS = /* @__PURE__ */ new Set([
1364
672
  var ENV_KEYS = /* @__PURE__ */ new Set(["mode", "allow"]);
1365
673
  var ID_RE = /^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/;
1366
674
  function projectSafetyPolicyPath(cwd = process.cwd()) {
1367
- let cursor = path3.resolve(cwd);
675
+ let cursor = path2.resolve(cwd);
1368
676
  while (true) {
1369
- const candidate = path3.join(cursor, POLICY_RELATIVE_PATH);
677
+ const candidate = path2.join(cursor, POLICY_RELATIVE_PATH);
1370
678
  if (existsSync(candidate)) return candidate;
1371
- const parent = path3.dirname(cursor);
679
+ const parent = path2.dirname(cursor);
1372
680
  if (parent === cursor) return null;
1373
681
  cursor = parent;
1374
682
  }
@@ -1476,12 +784,12 @@ function parsePathList(value, key, errors) {
1476
784
  continue;
1477
785
  }
1478
786
  const trimmed = item.trim();
1479
- if (path3.isAbsolute(trimmed)) {
787
+ if (path2.isAbsolute(trimmed)) {
1480
788
  errors.push(`${label} must be relative to the policy root`);
1481
789
  continue;
1482
790
  }
1483
- const normalized = path3.normalize(trimmed);
1484
- const segments = normalized.split(path3.sep).filter((segment) => segment.length > 0);
791
+ const normalized = path2.normalize(trimmed);
792
+ const segments = normalized.split(path2.sep).filter((segment) => segment.length > 0);
1485
793
  if (segments.some((segment) => segment === "..")) {
1486
794
  errors.push(`${label} must not escape the policy root with '..'`);
1487
795
  continue;
@@ -1526,11 +834,11 @@ function parseCommandPolicy(value, label) {
1526
834
  if (id && !ID_RE.test(id)) errors.push(`${label}.id must match ${ID_RE}`);
1527
835
  if (command && command.trim().length === 0) errors.push(`${label}.command must not be empty`);
1528
836
  if (cwd !== void 0) {
1529
- if (path3.isAbsolute(cwd)) {
837
+ if (path2.isAbsolute(cwd)) {
1530
838
  errors.push(`${label}.cwd must be relative to the policy root`);
1531
839
  } else {
1532
- const normalized = path3.normalize(cwd);
1533
- const segments = normalized.split(path3.sep).filter((segment) => segment.length > 0);
840
+ const normalized = path2.normalize(cwd);
841
+ const segments = normalized.split(path2.sep).filter((segment) => segment.length > 0);
1534
842
  if (segments.some((segment) => segment === "..")) {
1535
843
  errors.push(`${label}.cwd must not escape the policy root with '..'`);
1536
844
  }
@@ -1634,7 +942,7 @@ function isPlainRecord(value) {
1634
942
  return typeof value === "object" && value !== null && !Array.isArray(value);
1635
943
  }
1636
944
  function sha256(raw) {
1637
- return createHash2("sha256").update(raw, "utf8").digest("hex");
945
+ return createHash("sha256").update(raw, "utf8").digest("hex");
1638
946
  }
1639
947
 
1640
948
  // src/domains/safety/rejection-feedback.ts
@@ -1836,19 +1144,17 @@ function evaluateWriteRoots(roots, writeRootCwd, call) {
1836
1144
  if (roots.length === 0) return null;
1837
1145
  const target = writeRootTargetPath(call);
1838
1146
  if (target === null) return null;
1839
- const resolved = path4.resolve(writeRootCwd, target);
1840
- for (const root of roots) {
1841
- if (resolved === root || resolved.startsWith(`${root}${path4.sep}`)) return null;
1842
- }
1147
+ const resolved = path3.resolve(writeRootCwd, target);
1148
+ if (pathBoundaryCovers(roots, resolved)) return null;
1843
1149
  return `write target '${target}' resolves to '${resolved}', which is outside the permitted write roots for this run: ${roots.join(", ")}`;
1844
1150
  }
1845
1151
  function createSafetyPolicyEngine(options = {}) {
1846
- const cwd = canonicalizeExistingPath(path4.resolve(options.cwd ?? process.cwd()));
1847
- const writeRootCwd = path4.resolve(options.cwd ?? process.cwd());
1848
- const writeRoots = (options.writeRoots ?? []).map((root) => path4.resolve(root));
1152
+ const cwd = canonicalizeExistingPath(path3.resolve(options.cwd ?? process.cwd()));
1153
+ const writeRootCwd = path3.resolve(options.cwd ?? process.cwd());
1154
+ const writeRoots = (options.writeRoots ?? []).map((root) => resolvePathBoundary(writeRootCwd, root));
1849
1155
  const packs = options.rulePacks ?? getCachedDefaultRulePacks();
1850
1156
  const projectPolicy = options.projectPolicy ?? loadProjectSafetyPolicy(cwd);
1851
- const projectPolicyRoot = projectPolicy.path === null ? cwd : path4.dirname(path4.dirname(canonicalizeExistingPath(projectPolicy.path)));
1157
+ const projectPolicyRoot = projectPolicy.path === null ? cwd : path3.dirname(path3.dirname(canonicalizeExistingPath(projectPolicy.path)));
1852
1158
  const pathPolicyInput = projectPolicy.disableDefaultPathPolicy ? projectPolicy.pathPolicy : mergePathPolicyInputs(DEFAULT_DAMAGE_CONTROL_PATH_POLICY, projectPolicy.pathPolicy);
1853
1159
  const expandedDefaults = projectPolicy.disableDefaultPathPolicy ? pathPolicyInput : mergePathPolicyInputs(pathPolicyInput, { zeroAccessPaths: clioCredentialStorePaths() });
1854
1160
  const pathPolicy = compilePathPolicy(expandedDefaults, projectPolicyRoot);
@@ -2007,7 +1313,7 @@ function createSafetyPolicyEngine(options = {}) {
2007
1313
  }
2008
1314
  function clioCredentialStorePaths() {
2009
1315
  try {
2010
- return [path4.join(clioConfigDir(), "credentials.yaml")];
1316
+ return [path3.join(clioConfigDir(), "credentials.yaml")];
2011
1317
  } catch {
2012
1318
  return [];
2013
1319
  }
@@ -2272,11 +1578,11 @@ function effectiveClassification(classification, match) {
2272
1578
  }
2273
1579
  function matchingProjectCommand(policy, command, cwd) {
2274
1580
  if (!policy.valid || policy.path === null) return null;
2275
- const policyRoot = path4.dirname(path4.dirname(policy.path));
1581
+ const policyRoot = path3.dirname(path3.dirname(policy.path));
2276
1582
  for (const entry of policy.commands) {
2277
1583
  if (entry.command !== command) continue;
2278
1584
  if (entry.shellOperators === "deny" && hasShellOperators(command)) continue;
2279
- const allowedCwd = entry.cwd !== void 0 ? path4.resolve(policyRoot, entry.cwd) : policyRoot;
1585
+ const allowedCwd = entry.cwd !== void 0 ? path3.resolve(policyRoot, entry.cwd) : policyRoot;
2280
1586
  if (!isUnderOrSame(cwd, allowedCwd)) continue;
2281
1587
  return entry;
2282
1588
  }
@@ -2305,7 +1611,7 @@ function recognizeCommandChain(command, callCwd, workspaceRoot, policy) {
2305
1611
  if (segment[0] === "cd") {
2306
1612
  if (segment.length !== 2) return null;
2307
1613
  const target = segment[1] ?? "";
2308
- if (target.startsWith("~") || !isUnderOrSame(path4.resolve(callCwd, target), workspaceRoot)) return null;
1614
+ if (target.startsWith("~") || !isUnderOrSame(path3.resolve(callCwd, target), workspaceRoot)) return null;
2309
1615
  ruleIds.push("builtin:cd-workspace");
2310
1616
  continue;
2311
1617
  }
@@ -2332,11 +1638,11 @@ function hasShellOperators(command) {
2332
1638
  return hasSequencingOperators(command) || hasCommandSubstitution(command);
2333
1639
  }
2334
1640
  function isUnderOrSame(child, parent) {
2335
- const rel = path4.relative(
2336
- canonicalizeExistingPath(path4.resolve(parent)),
2337
- canonicalizeExistingPath(path4.resolve(child))
1641
+ const rel = path3.relative(
1642
+ canonicalizeExistingPath(path3.resolve(parent)),
1643
+ canonicalizeExistingPath(path3.resolve(child))
2338
1644
  );
2339
- return rel === "" || !rel.startsWith("..") && !path4.isAbsolute(rel);
1645
+ return rel === "" || !rel.startsWith("..") && !path3.isAbsolute(rel);
2340
1646
  }
2341
1647
  function commandArg(args) {
2342
1648
  return typeof args?.command === "string" ? args.command : null;
@@ -2347,7 +1653,7 @@ function pathArg(args) {
2347
1653
  return typeof candidate === "string" && candidate.length > 0 ? candidate : null;
2348
1654
  }
2349
1655
  function cwdArg(args, fallback) {
2350
- const resolved = typeof args?.cwd === "string" && args.cwd.length > 0 ? path4.resolve(fallback, args.cwd) : fallback;
1656
+ const resolved = typeof args?.cwd === "string" && args.cwd.length > 0 ? path3.resolve(fallback, args.cwd) : fallback;
2351
1657
  return canonicalizeExistingPath(resolved);
2352
1658
  }
2353
1659
  var CONTENT_BEARING_TOOLS = /* @__PURE__ */ new Set([ToolNames.Write, ToolNames.Edit, ToolNames.Artifact]);
@@ -2389,7 +1695,7 @@ function rulePackHash(packs) {
2389
1695
  const payload = {
2390
1696
  base: packPayload(packs.base.rules)
2391
1697
  };
2392
- return createHash3("sha256").update(JSON.stringify(payload), "utf8").digest("hex");
1698
+ return createHash2("sha256").update(JSON.stringify(payload), "utf8").digest("hex");
2393
1699
  }
2394
1700
  function packPayload(rules) {
2395
1701
  return rules.map((rule) => ({
@@ -2403,16 +1709,6 @@ function packPayload(rules) {
2403
1709
  }
2404
1710
 
2405
1711
  export {
2406
- parseJsonObjectPayload,
2407
- resultContractSourceId,
2408
- parseVerifierResult,
2409
- resultContractAuthorship,
2410
- parseScoutResult,
2411
- validateResultContract,
2412
- validateRecipeResult,
2413
- RESULT_CONTRACT_REPAIR_LIMIT,
2414
- resultContractRepairMessages,
2415
- parseResultContract,
2416
1712
  DEFAULT_RECENT_ENTRY_LIMIT,
2417
1713
  assessFinishContract,
2418
1714
  typedValidationSummary,
@@ -2420,4 +1716,4 @@ export {
2420
1716
  WRITE_ROOT_REFUSED_TOOLS,
2421
1717
  createSafetyPolicyEngine
2422
1718
  };
2423
- //# sourceMappingURL=chunk-EKY57CSP.js.map
1719
+ //# sourceMappingURL=chunk-5H3GB5BO.js.map