@iowarp/clio-coder 0.4.3 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (340) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +1 -1
  3. package/dist/{acp-H2NGRPWO.js → acp-WNAYYF4F.js} +4 -5
  4. package/dist/{agents-TL5LLUQP.js → agents-3OKXHLOI.js} +33 -31
  5. package/dist/assets/codewiki.json +1 -1
  6. package/dist/{auth-E5SW4HMS.js → auth-VKNNMGPU.js} +10 -11
  7. package/dist/{builtins-IA7V7FUC.js → builtins-WGALA46I.js} +4 -4
  8. package/dist/{chunk-F5JHEYZM.js → chunk-23L32XTI.js} +10 -7
  9. package/dist/{chunk-DWUOQKRU.js → chunk-25QBEXRS.js} +2 -2
  10. package/dist/{chunk-LLDJM5XK.js → chunk-26QSH3EJ.js} +2 -2
  11. package/dist/{chunk-N2Z7HLVY.js → chunk-2ASED4PZ.js} +10 -10
  12. package/dist/{chunk-MCEPRMZW.js → chunk-2CU2H6KE.js} +2 -2
  13. package/dist/chunk-2DSOYNFC.js +108 -0
  14. package/dist/{chunk-LDJG7DW3.js → chunk-2ZSONWVL.js} +4 -4
  15. package/dist/{chunk-GI7YYQ3F.js → chunk-36CT5VVL.js} +324 -41
  16. package/dist/{chunk-4UVU7BJ5.js → chunk-3GY4F45V.js} +2 -2
  17. package/dist/{chunk-PUVDKJ2Y.js → chunk-3ODX73FK.js} +3 -5
  18. package/dist/{chunk-IUE3Y34X.js → chunk-3UNOLWNZ.js} +2 -2
  19. package/dist/{chunk-6PTFB5VS.js → chunk-3UUXNFEX.js} +8 -4
  20. package/dist/{chunk-2APPQIER.js → chunk-4M6Z5QVF.js} +4 -4
  21. package/dist/{chunk-K6BSR66V.js → chunk-4NSRCOYP.js} +4 -1
  22. package/dist/{chunk-JGRC33J2.js → chunk-54X7T7DK.js} +12 -3
  23. package/dist/{chunk-YQWYVTMC.js → chunk-5636DCO5.js} +4 -4
  24. package/dist/{chunk-7E7I3WLS.js → chunk-57XXR6DR.js} +23 -22
  25. package/dist/{chunk-7ZYNNDKC.js → chunk-5TUB6SLS.js} +2 -2
  26. package/dist/{chunk-VW6DOEDG.js → chunk-6OSVSQL5.js} +11 -2
  27. package/dist/{chunk-L47TF46W.js → chunk-6PAZTBPA.js} +14 -2
  28. package/dist/{chunk-XIVNBFZS.js → chunk-6Q3CYFD3.js} +34 -16
  29. package/dist/{chunk-RSJ25QSL.js → chunk-6QOTUPRG.js} +155 -36
  30. package/dist/{chunk-JKKCYP3C.js → chunk-6UINWWS6.js} +10 -4
  31. package/dist/{chunk-WBKFA554.js → chunk-72YIHOZQ.js} +2 -2
  32. package/dist/{chunk-PAJQJ7BS.js → chunk-75W7L2E2.js} +246 -697
  33. package/dist/{chunk-RRNP2ANY.js → chunk-7UGL4MB5.js} +4 -4
  34. package/dist/{chunk-EKCHAPYA.js → chunk-AUPNRN7C.js} +2 -2
  35. package/dist/{chunk-ZDN3Y73Y.js → chunk-BJVFZO5U.js} +6 -48
  36. package/dist/{chunk-IWT4SF4R.js → chunk-CUSRQKPU.js} +64 -2
  37. package/dist/{chunk-SKHCAU7K.js → chunk-DQOVN6KV.js} +3 -2
  38. package/dist/{chunk-ZWPRK62N.js → chunk-DT3LWJOB.js} +4 -4
  39. package/dist/chunk-DXKJURES.js +671 -0
  40. package/dist/{chunk-BEPZRGGU.js → chunk-EL24TAU4.js} +2 -2
  41. package/dist/{chunk-OML5D5V5.js → chunk-ELWDPP3Y.js} +5 -5
  42. package/dist/{chunk-NDINPTJ4.js → chunk-ELZVTCGV.js} +5 -4
  43. package/dist/chunk-EXLD33WO.js +381 -0
  44. package/dist/{chunk-IJNZMHLA.js → chunk-FEAXX7B6.js} +2 -2
  45. package/dist/{chunk-TM6LQDI3.js → chunk-FFUPXJC4.js} +74 -323
  46. package/dist/chunk-GX5WYQO4.js +59 -0
  47. package/dist/chunk-I2DWJ4GM.js +390 -0
  48. package/dist/{chunk-TXOTCRLG.js → chunk-I5FWO7L5.js} +5 -5
  49. package/dist/chunk-IRXAATOX.js +539 -0
  50. package/dist/chunk-IXIY2H4R.js +44 -0
  51. package/dist/{chunk-KK4JZPBQ.js → chunk-IZXGRF7P.js} +76 -10
  52. package/dist/{chunk-5TSRNF4G.js → chunk-JCI2ROMZ.js} +164 -6
  53. package/dist/{chunk-INY6HTFL.js → chunk-JEIYHLOR.js} +2 -2
  54. package/dist/{chunk-MUW2BDDH.js → chunk-JQLNNIKT.js} +2 -2
  55. package/dist/{chunk-XPWWI35G.js → chunk-JSD46VO2.js} +19 -8
  56. package/dist/{chunk-VA5FNYMT.js → chunk-JT2RFCC5.js} +39 -2
  57. package/dist/{chunk-V2ANDPVT.js → chunk-K6T2ZAMZ.js} +168 -6
  58. package/dist/{chunk-B4OAX3SI.js → chunk-KFV5L5SK.js} +13 -6
  59. package/dist/{chunk-JEQ3XTHC.js → chunk-LLXSDWXS.js} +2 -2
  60. package/dist/{chunk-E3TPLWFX.js → chunk-LTIKRKFL.js} +3 -3
  61. package/dist/{chunk-NIQJ66N4.js → chunk-N56KALIC.js} +17 -17
  62. package/dist/{chunk-JDAY6FIL.js → chunk-NAI6ZFCY.js} +13 -9
  63. package/dist/{chunk-AF4YM7Z4.js → chunk-NRO2BJRH.js} +2490 -2182
  64. package/dist/{chunk-WRBAGUNF.js → chunk-NXIMQY5W.js} +2 -2
  65. package/dist/{chunk-I7ZPNEJM.js → chunk-NXYCB2VD.js} +5 -5
  66. package/dist/chunk-ODGTEFFI.js +50 -0
  67. package/dist/{chunk-2VIKGWFZ.js → chunk-OEJSLEPW.js} +2 -2
  68. package/dist/{chunk-KKOJXO6R.js → chunk-OMQNJVKW.js} +4 -2
  69. package/dist/{chunk-54CBCGIR.js → chunk-Q4WO54TA.js} +132 -77
  70. package/dist/{chunk-B4VEBZKF.js → chunk-QUFRYSWI.js} +12 -6
  71. package/dist/{chunk-42FMPA75.js → chunk-QZWQA4DE.js} +2 -2
  72. package/dist/{chunk-HEQY7ZFI.js → chunk-RAY4OVGZ.js} +2 -2
  73. package/dist/{chunk-G76U63X4.js → chunk-RQCKCSRL.js} +7 -7
  74. package/dist/{chunk-64I3JVYM.js → chunk-RXTN6AKH.js} +2 -2
  75. package/dist/{chunk-UPZU6GE4.js → chunk-RZDWV63N.js} +3 -3
  76. package/dist/{chunk-2UH2KFUP.js → chunk-S6PYF2XF.js} +2 -2
  77. package/dist/{chunk-JSC3U7TI.js → chunk-TOIVGRUX.js} +2 -2
  78. package/dist/{chunk-7DRAWPTZ.js → chunk-TQAHXW6Y.js} +1 -1
  79. package/dist/{chunk-JIEGK6UF.js → chunk-U6TMQNSI.js} +48 -4
  80. package/dist/{chunk-AX2THNSA.js → chunk-UEPWCCTY.js} +4 -4
  81. package/dist/{chunk-QWGDJJYJ.js → chunk-USR47QNF.js} +4 -4
  82. package/dist/{chunk-Y3CBHOR6.js → chunk-V6HJFQZE.js} +2 -2
  83. package/dist/chunk-V76WTFTW.js +318 -0
  84. package/dist/{chunk-NMJXSHBJ.js → chunk-W54I7H25.js} +2 -2
  85. package/dist/{chunk-2UG5F4C5.js → chunk-XULDXHTN.js} +24 -12
  86. package/dist/chunk-XXYSBZIQ.js +283 -0
  87. package/dist/{chunk-MWUZBSAQ.js → chunk-Y55JBDO5.js} +331 -51
  88. package/dist/{chunk-W6RRQCPQ.js → chunk-YD5GIKET.js} +4 -4
  89. package/dist/{chunk-CE5AX47J.js → chunk-YECAMM3D.js} +2 -2
  90. package/dist/{chunk-WCXUNS7U.js → chunk-YNFKXPEC.js} +6 -6
  91. package/dist/cli/index.js +36 -35
  92. package/dist/{clio-CMMK4KRR.js → clio-QLICPCF5.js} +2 -2
  93. package/dist/{code-nav-MDZNQS33.js → code-nav-IJR2DBPR.js} +6 -6
  94. package/dist/{components-UCUQ4QXW.js → components-2TGAI2RC.js} +3 -4
  95. package/dist/{config-SVM5P5YI.js → config-IUA6OYNS.js} +52 -47
  96. package/dist/{configure-LE3IK2TJ.js → configure-VEPX4NMX.js} +14 -15
  97. package/dist/{context-VNCR7KAG.js → context-2DKHWH2T.js} +23 -23
  98. package/dist/{context-2OHRKS42.js → context-4MPR7WKB.js} +48 -42
  99. package/dist/{context-E3VC7RX5.js → context-BOYF5EJM.js} +11 -11
  100. package/dist/{context-clear-BW4O37TG.js → context-clear-S4ZJCQUX.js} +48 -42
  101. package/dist/{context-working-set-VDS25HXZ.js → context-working-set-3I3FYX6Y.js} +8 -8
  102. package/dist/detail-A7JAVSIG.js +98 -0
  103. package/dist/{dispatch-runner-5AHT53RF.js → dispatch-runner-RJ5I2F2O.js} +71 -58
  104. package/dist/{docs-PD3EXDKU.js → docs-SPOV3BAN.js} +3 -5
  105. package/dist/{doctor-WNNVO6FY.js → doctor-DKICC2SN.js} +54 -31
  106. package/dist/{eval-7G7SGAYO.js → eval-OQOQUDHK.js} +47 -56
  107. package/dist/{evidence-VD6736FQ.js → evidence-4DQ25GUQ.js} +53 -150
  108. package/dist/evidence-4F5USFKH.js +208 -0
  109. package/dist/{evolve-AL3NGVRL.js → evolve-GSS52E5J.js} +44 -41
  110. package/dist/{extensions-MOVJ32NM.js → extensions-G7MFLYHT.js} +4 -5
  111. package/dist/{fleet-QZHUMAGI.js → fleet-Q37YHHAQ.js} +74 -68
  112. package/dist/{fleet-commands-BAYT5FJZ.js → fleet-commands-G7E4N7SM.js} +14 -11
  113. package/dist/{fleet-decisions-IREVMRU4.js → fleet-decisions-O7M6QBA2.js} +6 -6
  114. package/dist/{fleet-graph-YCTT3HTI.js → fleet-graph-TOUBW6OW.js} +13 -13
  115. package/dist/{fleet-inspect-QVJTDAVB.js → fleet-inspect-SW33JJNI.js} +43 -39
  116. package/dist/{fleet-preflight-25QAFPK4.js → fleet-preflight-CV2655TW.js} +2 -3
  117. package/dist/{fleet-validate-5O57AAJ7.js → fleet-validate-KESZX2YH.js} +16 -16
  118. package/dist/{fleet-verify-CPH2W2T6.js → fleet-verify-UQPMTVE3.js} +42 -38
  119. package/dist/{fleet-view-SWBR3VGQ.js → fleet-view-MN2VG4MR.js} +43 -39
  120. package/dist/{init-J477LKZH.js → init-PXEXQSBF.js} +60 -54
  121. package/dist/{interop-3FCM6XLG.js → interop-ZG5T62U3.js} +6 -7
  122. package/dist/inventory-C26CFDRR.js +101 -0
  123. package/dist/{library-QUQEIUG6.js → library-B2W4N74O.js} +16 -17
  124. package/dist/{memory-SGGSEP65.js → memory-YCANYS5A.js} +45 -42
  125. package/dist/{models-HEKUAXXK.js → models-GERTU3YI.js} +20 -22
  126. package/dist/{monitor-HKU57TYQ.js → monitor-CPNIUULB.js} +50 -44
  127. package/dist/{orchestrator-VDFAEFAI.js → orchestrator-J4BSH4WQ.js} +491 -1182
  128. package/dist/{panes-DN2SSFOH.js → panes-BOHAEGYC.js} +3 -3
  129. package/dist/{panes-TALGNPZT.js → panes-NXSLDQZ2.js} +5 -6
  130. package/dist/{paths-NBMFAIEZ.js → paths-VSUWNC22.js} +3 -4
  131. package/dist/{reset-EAJFFJVB.js → reset-TNWTB5LU.js} +5 -6
  132. package/dist/{resources-OVKSEFVE.js → resources-4PXNMD5G.js} +14 -14
  133. package/dist/{run-7DP7ZF2J.js → run-D6XJ34CN.js} +79 -83
  134. package/dist/{share-WML67FT3.js → share-2NWMJJEE.js} +14 -15
  135. package/dist/{skills-SG662R2K.js → skills-KR7WON5G.js} +18 -19
  136. package/dist/{skills-eval-VVZEUU46.js → skills-eval-O2ZNOLDS.js} +49 -46
  137. package/dist/{skills-inventory-I2E23GET.js → skills-inventory-ZZOUBK7O.js} +14 -14
  138. package/dist/{slash-commands-S7MBJDQK.js → slash-commands-ZXPJD64J.js} +32 -23
  139. package/dist/{steer-2LQOMCPB.js → steer-XA25PSCS.js} +3 -3
  140. package/dist/{support-CC2UJBJ6.js → support-7EMVWYG2.js} +2 -2
  141. package/dist/{targets-4QC3HIEW.js → targets-OMH2XCSN.js} +25 -27
  142. package/dist/tasks-IPAGMEIX.js +36 -0
  143. package/dist/{terminal-lease-TUHIJ6Y2.js → terminal-lease-C2J3JYRE.js} +4 -4
  144. package/dist/{tools-TFGJICCU.js → tools-EFFEAIDP.js} +5 -6
  145. package/dist/{uninstall-5PEVOE5B.js → uninstall-HALS6BLF.js} +7 -8
  146. package/dist/{upgrade-M4WXY6KN.js → upgrade-MS72RJEP.js} +14 -11
  147. package/dist/{usage-N7ZNVLEM.js → usage-NHG6MCJM.js} +60 -51
  148. package/dist/{verifiers-DJTP4XX6.js → verifiers-7AUNVXDY.js} +150 -17
  149. package/dist/{verify-RWE4PPEK.js → verify-FWYGPKMR.js} +12 -10
  150. package/dist/{web-fetch-MPARV2K7.js → web-fetch-V4FKSDAV.js} +4 -4
  151. package/dist/{wiki-generate-C7IQOXSP.js → wiki-generate-743CIGJW.js} +63 -56
  152. package/dist/{with-panes-4GCGSL7J.js → with-panes-BDQEWBRT.js} +2 -2
  153. package/dist/worker/entry.js +36 -33
  154. package/docs/README.md +3 -2
  155. package/docs/architecture/acp.md +17 -0
  156. package/docs/architecture/artifact-versions.md +1 -1
  157. package/docs/architecture/dispatch-typed-intent.md +1 -1
  158. package/docs/architecture/evidence-and-memory.md +1 -1
  159. package/docs/architecture/observability.md +7 -1
  160. package/docs/architecture/prompt-envelope-and-tools.md +15 -5
  161. package/docs/architecture/safety-model.md +10 -17
  162. package/docs/architecture/tui-design.md +1 -1
  163. package/docs/guide/built-in-agents.md +8 -8
  164. package/docs/guide/commands-and-modes.md +17 -2
  165. package/docs/guide/configuration-and-targets.md +3 -1
  166. package/docs/guide/configuration-reference.md +10 -5
  167. package/docs/guide/environment-variables.md +2 -2
  168. package/docs/guide/tool-usage.md +78 -3
  169. package/docs/history/config-knobs-audit.md +2 -2
  170. package/docs/process/development-pipeline.md +6 -1
  171. package/docs/process/git-commit-provenance.md +15 -0
  172. package/docs/process/release-cut-checklist.md +207 -0
  173. package/docs/process/scientific-validation.md +18 -17
  174. package/evals/behavioral-machinery-support.ts +1 -0
  175. package/evals/behavioral-machinery.yaml +1 -1
  176. package/package.json +1 -1
  177. package/skills/coding/coding-standards/SKILL.md +14 -4
  178. package/skills/context/context-handoff/SKILL.md +3 -3
  179. package/skills/context/context-prime/SKILL.md +3 -3
  180. package/skills/planning/architecture/SKILL.md +5 -5
  181. package/skills/planning/backlog/SKILL.md +4 -4
  182. package/skills/planning/prd/SKILL.md +4 -3
  183. package/skills/planning/product-intent/SKILL.md +8 -8
  184. package/skills/planning/tech-spec/SKILL.md +4 -4
  185. package/skills/registry.yaml +32 -32
  186. package/skills/research/arxiv-literature/SKILL.md +3 -3
  187. package/skills/research/experiment-protocol/SKILL.md +3 -3
  188. package/skills/research/scientific-debugging/SKILL.md +3 -2
  189. package/skills/research/scientific-modernization/SKILL.md +3 -3
  190. package/skills/skill-marketplace.json +16 -16
  191. package/skills/workflow/cut-it/SKILL.md +3 -4
  192. package/skills/workflow/design-council/SKILL.md +5 -10
  193. package/skills/workflow/grill-me/SKILL.md +14 -15
  194. package/skills/workflow/workflow-distiller/SKILL.md +4 -4
  195. package/src/cli/args.ts +0 -8
  196. package/src/cli/configure.ts +2 -1
  197. package/src/cli/doctor-state-size.ts +1 -12
  198. package/src/cli/doctor-validation-contract.ts +28 -0
  199. package/src/cli/doctor.ts +5 -0
  200. package/src/cli/evidence-detail.ts +1 -75
  201. package/src/cli/evidence-inventory.ts +1 -167
  202. package/src/cli/index.ts +2 -0
  203. package/src/cli/run.ts +0 -2
  204. package/src/cli/targets.ts +1 -1
  205. package/src/cli/tasks.ts +84 -0
  206. package/src/cli/upgrade.ts +10 -5
  207. package/src/cli/usage.ts +6 -0
  208. package/src/cli/verifiers.ts +147 -1
  209. package/src/cli/wiki-generate.ts +1 -0
  210. package/src/core/commit-attribution.ts +41 -1
  211. package/src/core/git-commit-attribution.ts +46 -3
  212. package/src/core/run-overrides.ts +0 -5
  213. package/src/core/skill-activation.ts +3 -0
  214. package/src/core/tool-names.ts +5 -2
  215. package/src/domains/agents/builtins/architect.md +1 -1
  216. package/src/domains/agents/builtins/coder.md +1 -1
  217. package/src/domains/agents/builtins/documenter.md +1 -1
  218. package/src/domains/agents/builtins/git-master.md +1 -1
  219. package/src/domains/agents/builtins/provenance.md +7 -7
  220. package/src/domains/agents/builtins/tester.md +1 -1
  221. package/src/domains/agents/builtins/verifier.md +2 -2
  222. package/src/domains/agents/builtins/wiki-writer.md +4 -3
  223. package/src/domains/context/extension.ts +31 -7
  224. package/src/domains/context/refresh.ts +3 -0
  225. package/src/domains/context/wiki/frontmatter.ts +5 -2
  226. package/src/domains/context/wiki/generate.ts +6 -0
  227. package/src/domains/context/wiki/prompts.ts +43 -0
  228. package/src/domains/dispatch/active-route-planner.ts +4 -0
  229. package/src/domains/dispatch/code-step.ts +11 -4
  230. package/src/domains/dispatch/contract.ts +31 -7
  231. package/src/domains/dispatch/execution-scheduler.ts +2 -0
  232. package/src/domains/dispatch/extension.ts +50 -27
  233. package/src/domains/dispatch/fleet-commit-attribution.ts +5 -0
  234. package/src/domains/dispatch/fleet-run.ts +1 -0
  235. package/src/domains/dispatch/host-verification.ts +114 -13
  236. package/src/domains/dispatch/intent.ts +28 -18
  237. package/src/domains/dispatch/orphan-recovery.ts +2 -0
  238. package/src/domains/dispatch/receipt-integrity.ts +4 -0
  239. package/src/domains/dispatch/reservation-store.ts +5 -3
  240. package/src/domains/dispatch/state.ts +15 -2
  241. package/src/domains/dispatch/types.ts +17 -2
  242. package/src/domains/eval/runners/clio-run.ts +12 -9
  243. package/src/domains/eval/runners/context-index.ts +2 -7
  244. package/src/domains/eval/runners/context-init.ts +3 -6
  245. package/src/domains/eval/runners/external-command.ts +29 -11
  246. package/src/domains/evidence/build.ts +102 -15
  247. package/src/domains/evidence/detail.ts +69 -0
  248. package/src/domains/evidence/eval.ts +13 -1
  249. package/src/domains/evidence/finish-contract-map.ts +5 -1
  250. package/src/domains/evidence/inventory.ts +167 -0
  251. package/src/domains/evidence/store.ts +16 -0
  252. package/src/domains/evidence/types.ts +12 -0
  253. package/src/domains/extensions/resources.ts +7 -0
  254. package/src/domains/middleware/marketplace-offer.ts +20 -1
  255. package/src/domains/middleware/runtime.ts +7 -3
  256. package/src/domains/mux/detect.ts +3 -6
  257. package/src/domains/observability/accountability.ts +15 -1
  258. package/src/domains/observability/contract.ts +52 -7
  259. package/src/domains/observability/evidence-index.ts +10 -0
  260. package/src/domains/observability/extension.ts +9 -5
  261. package/src/domains/observability/projection.ts +394 -45
  262. package/src/{interactive → domains/observability}/worker-progress.ts +3 -3
  263. package/src/domains/prompts/fragments/operating/contract.md +2 -0
  264. package/src/domains/prompts/fragments/wiki/page.md +8 -0
  265. package/src/domains/providers/model-discovery.ts +1 -4
  266. package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +16 -14
  267. package/src/domains/providers/runtimes/claude/claude-code.ts +9 -0
  268. package/src/domains/providers/support.ts +1 -1
  269. package/src/domains/providers/types/runtime-descriptor.ts +1 -1
  270. package/src/domains/safety/action-classifier.ts +7 -0
  271. package/src/domains/safety/default-path-policy.ts +2 -0
  272. package/src/domains/safety/finish-contract-registration.ts +29 -14
  273. package/src/domains/safety/finish-contract.ts +252 -40
  274. package/src/domains/safety/index.ts +20 -1
  275. package/src/domains/safety/policy-engine.ts +26 -6
  276. package/src/domains/safety/rigor.ts +53 -39
  277. package/src/domains/safety/validation-contract.ts +388 -0
  278. package/src/domains/session/archive-readers.ts +10 -1
  279. package/src/domains/session/decision-board.ts +101 -2
  280. package/src/domains/session/entries.ts +44 -7
  281. package/src/domains/session/extension.ts +4 -4
  282. package/src/domains/session/handoff.ts +2 -1
  283. package/src/domains/session/manager.ts +2 -3
  284. package/src/domains/session/task-board.ts +14 -1
  285. package/src/domains/session/tree/fork.ts +1 -2
  286. package/src/domains/session/tree/navigator.ts +1 -1
  287. package/src/domains/user-tasks/acceptance.ts +56 -0
  288. package/src/domains/user-tasks/active-acceptance.ts +40 -0
  289. package/src/domains/user-tasks/store.ts +34 -3
  290. package/src/engine/acp/adapter.ts +24 -6
  291. package/src/engine/acp/server.ts +21 -4
  292. package/src/engine/acp/transport.ts +53 -8
  293. package/src/engine/acp/types.ts +4 -0
  294. package/src/engine/apis/ollama-native.ts +15 -0
  295. package/src/engine/claude/subprocess-runtime.ts +107 -60
  296. package/src/engine/external-subprocess.ts +12 -4
  297. package/src/entry/orchestrator.ts +11 -2
  298. package/src/interactive/dispatch-board.ts +46 -717
  299. package/src/interactive/fleet-run-preview.ts +2 -1
  300. package/src/interactive/interactive-application.ts +3 -2
  301. package/src/interactive/interactive-presentation.ts +55 -12
  302. package/src/interactive/interactive-slash-runtime.ts +2 -1
  303. package/src/interactive/oracle.ts +5 -2
  304. package/src/interactive/overlays/fleet-run-approval.ts +3 -2
  305. package/src/interactive/overlays/message-picker.ts +2 -2
  306. package/src/interactive/overlays/settings.ts +2 -2
  307. package/src/interactive/overlays/tree-selector.ts +2 -2
  308. package/src/interactive/renderers/branch-summary.ts +1 -1
  309. package/src/interactive/slash-autocomplete.ts +4 -6
  310. package/src/interactive/slash-commands.ts +25 -39
  311. package/src/interactive/slash-spec.ts +28 -0
  312. package/src/interactive/view/artifacts.ts +2 -0
  313. package/src/interactive/worker-stream.ts +7 -3
  314. package/src/tools/bootstrap.ts +4 -0
  315. package/src/tools/builtin-tool-catalog.ts +31 -0
  316. package/src/tools/compete-worktrees.ts +7 -1
  317. package/src/tools/core-bootstrap.ts +16 -0
  318. package/src/tools/decide.ts +136 -0
  319. package/src/tools/dispatch-admission.ts +21 -0
  320. package/src/tools/dispatch-plan.ts +5 -2
  321. package/src/tools/dispatch-runner.ts +15 -1
  322. package/src/tools/dispatch-types.ts +6 -0
  323. package/src/tools/evidence.ts +96 -0
  324. package/src/tools/limitation.ts +76 -0
  325. package/src/tools/policy.ts +9 -0
  326. package/src/tools/presentation.ts +3 -0
  327. package/src/tools/registry.ts +1 -1
  328. package/src/tools/result-shaping.ts +17 -5
  329. package/src/tools/task-worktree.ts +13 -3
  330. package/src/tools/tasks.ts +10 -1
  331. package/src/tools/verify/authoring.ts +170 -83
  332. package/src/tools/verify/catalog.ts +122 -5
  333. package/src/tools/verify/index.ts +2 -1
  334. package/src/tools/verify/numeric.ts +298 -0
  335. package/src/tools/verify/perf.ts +143 -0
  336. package/src/tools/verify/scripts.ts +229 -2
  337. package/dist/chunk-7DICMOS6.js +0 -313
  338. package/dist/chunk-RVG5JXAL.js +0 -41
  339. package/dist/chunk-T56WDKA5.js +0 -183
  340. package/dist/chunk-VPKWYKEY.js +0 -169
@@ -1,17 +1,30 @@
1
- import { existsSync, readFileSync } from "node:fs";
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
2
  import path from "node:path";
3
- import { resolveSafeCwd } from "../../core/safe-exec.js";
3
+ import { resolveSafeCwd, runCommandVector, type SafeCommandResult } from "../../core/safe-exec.js";
4
4
  import { declaredVerificationScripts, VERIFICATION_SCRIPT_FAMILY_HINT } from "../../core/verification-scripts.js";
5
5
  import type { ToolResult } from "../registry.js";
6
6
  import { runVectorTool } from "../safe-exec.js";
7
7
  import {
8
8
  type DeclaredCheck,
9
9
  type DeclaredCheckSource,
10
+ type DeclaredNumericCompare,
11
+ type DeclaredPerfBudget,
10
12
  loadProjectVerifierCatalog,
11
13
  PROJECT_VERIFIER_CATALOG_RELATIVE_PATH,
12
14
  packageDeclaredCheck,
13
15
  resolveProjectVerifierExecutionCwd,
14
16
  } from "./catalog.js";
17
+ import { compareNumeric, type NumericCompareReport, parseNumericPayload, renderNumericReport } from "./numeric.js";
18
+ import {
19
+ evaluatePerfBudget,
20
+ type PerfBaseline,
21
+ type PerfBudgetReport,
22
+ parsePerfBaseline,
23
+ renderPerfBaseline,
24
+ } from "./perf.js";
25
+
26
+ /** The structured verdict a numeric-compare or perf-budget check records beside the command facts. */
27
+ export type DeclaredCheckReport = NumericCompareReport | PerfBudgetReport;
15
28
 
16
29
  /**
17
30
  * Package scripts and the project catalog meet here as one canonical check
@@ -197,6 +210,7 @@ function withDeclaredEvidence(result: ToolResult, check: DeclaredCheck): ToolRes
197
210
  ...result.details,
198
211
  action: "verify",
199
212
  check: check.id,
213
+ kind: check.kind,
200
214
  source: { ...check.source },
201
215
  description: check.description,
202
216
  declaredCommand: [...check.command],
@@ -207,15 +221,228 @@ function withDeclaredEvidence(result: ToolResult, check: DeclaredCheck): ToolRes
207
221
  };
208
222
  }
209
223
 
224
+ /**
225
+ * The JSON object a numeric-compare command printed. The whole text is tried
226
+ * first; when the command also wrote diagnostics around it, the span from the
227
+ * first `{` to the last `}` is tried once more, so a preamble line does not
228
+ * turn a correct payload into a parse failure.
229
+ */
230
+ export function extractNumericPayloadText(output: string): string {
231
+ const trimmed = output.trim();
232
+ try {
233
+ JSON.parse(trimmed);
234
+ return trimmed;
235
+ } catch {
236
+ const start = trimmed.indexOf("{");
237
+ const end = trimmed.lastIndexOf("}");
238
+ return start >= 0 && end > start ? trimmed.slice(start, end + 1) : trimmed;
239
+ }
240
+ }
241
+
242
+ /** Read a repository-relative check file inside the workspace root, as text. */
243
+ function readCheckFile(workspaceRoot: string, relative: string, label: string): string | Error {
244
+ let resolved: string;
245
+ try {
246
+ resolved = resolveSafeCwd(relative, workspaceRoot);
247
+ } catch (error) {
248
+ return new Error(`${label} ${error instanceof Error ? error.message : String(error)}`);
249
+ }
250
+ if (!existsSync(resolved)) return new Error(`${label} '${relative}' does not exist`);
251
+ try {
252
+ return readFileSync(resolved, "utf8");
253
+ } catch (error) {
254
+ return new Error(`${label} '${relative}' cannot be read (${error instanceof Error ? error.message : String(error)})`);
255
+ }
256
+ }
257
+
258
+ /** Judge a numeric-compare command's stdout against reference text already read from disk. Pure. */
259
+ export function judgeNumericTexts(
260
+ stdout: string,
261
+ referenceText: string,
262
+ tolerance: DeclaredNumericCompare["tolerance"],
263
+ referenceLabel: string,
264
+ ): NumericCompareReport | Error {
265
+ const reference = parseNumericPayload(referenceText, referenceLabel);
266
+ if (reference instanceof Error) return reference;
267
+ const actual = parseNumericPayload(extractNumericPayloadText(stdout), "command output");
268
+ if (actual instanceof Error) return actual;
269
+ return compareNumeric(actual, reference, tolerance);
270
+ }
271
+
272
+ /** Judge a numeric-compare command's stdout against the declared reference under the workspace root. */
273
+ function judgeNumericCompare(
274
+ stdout: string,
275
+ numeric: DeclaredNumericCompare,
276
+ workspaceRoot: string,
277
+ ): NumericCompareReport | Error {
278
+ const referenceText = readCheckFile(workspaceRoot, numeric.reference, "reference");
279
+ if (referenceText instanceof Error) return referenceText;
280
+ return judgeNumericTexts(stdout, referenceText, numeric.tolerance, `reference '${numeric.reference}'`);
281
+ }
282
+
283
+ /** Judge a measured wall time against a budget, or against baseline text already read from disk. Pure. */
284
+ export function judgePerfTexts(
285
+ measuredMs: number,
286
+ perf: DeclaredPerfBudget,
287
+ baselineText: string | undefined,
288
+ baselineLabel: string,
289
+ ): PerfBudgetReport | Error {
290
+ let baseline: PerfBaseline | undefined;
291
+ if (perf.baseline !== undefined) {
292
+ if (baselineText === undefined) {
293
+ return new Error(`${baselineLabel} is missing; record it with \`clio-coder verifiers baseline <id>\``);
294
+ }
295
+ const parsed = parsePerfBaseline(baselineText, baselineLabel);
296
+ if (parsed instanceof Error) return parsed;
297
+ baseline = parsed;
298
+ }
299
+ return evaluatePerfBudget(measuredMs, {
300
+ ...(perf.budget !== undefined ? { budget: perf.budget } : {}),
301
+ ...(baseline !== undefined ? { baseline } : {}),
302
+ ...(perf.tolerance?.relative !== undefined ? { relative: perf.tolerance.relative } : {}),
303
+ });
304
+ }
305
+
306
+ /** Judge a measured wall time against the declared budget or the recorded baseline under the workspace root. */
307
+ function judgePerfBudget(
308
+ measuredMs: number,
309
+ perf: DeclaredPerfBudget,
310
+ workspaceRoot: string,
311
+ ): PerfBudgetReport | Error {
312
+ let baselineText: string | undefined;
313
+ if (perf.baseline !== undefined) {
314
+ const text = readCheckFile(workspaceRoot, perf.baseline, "baseline");
315
+ if (text instanceof Error) {
316
+ return new Error(`${text.message}; record it with \`clio-coder verifiers baseline <id>\``);
317
+ }
318
+ baselineText = text;
319
+ }
320
+ return judgePerfTexts(measuredMs, perf, baselineText, `baseline '${perf.baseline ?? ""}'`);
321
+ }
322
+
323
+ function commandFacts(result: SafeCommandResult): Record<string, unknown> {
324
+ return {
325
+ command: [result.file, ...result.args].join(" "),
326
+ argv: [result.file, ...result.args],
327
+ cwd: result.cwd,
328
+ exitCode: result.exitCode,
329
+ durationMs: result.durationMs,
330
+ aborted: result.aborted,
331
+ timedOut: result.timedOut,
332
+ outputCapped: result.outputCapped,
333
+ };
334
+ }
335
+
336
+ /**
337
+ * Run a numeric-compare or perf-budget check: the command through the same
338
+ * safe-exec spine as a command check, then the pure judgement. A command that
339
+ * exits non-zero, times out, or is aborted fails before any comparison, so a
340
+ * crashed validator never reads as a tolerance verdict.
341
+ */
342
+ async function runJudgedCheck(
343
+ check: DeclaredCheck,
344
+ file: string,
345
+ vector: ReadonlyArray<string>,
346
+ cwd: string,
347
+ options?: { signal?: AbortSignal },
348
+ ): Promise<ToolResult> {
349
+ let result: SafeCommandResult;
350
+ try {
351
+ result = await runCommandVector(file, vector, {
352
+ cwd,
353
+ timeoutMs: check.timeoutMs,
354
+ ...(options?.signal !== undefined ? { signal: options.signal } : {}),
355
+ });
356
+ } catch (error) {
357
+ return { kind: "error", message: `verify: ${error instanceof Error ? error.message : String(error)}` };
358
+ }
359
+ const facts = commandFacts(result);
360
+ const tail = `${result.stdout}${result.stderr}`.trim().slice(-2_000);
361
+ if (result.aborted) return { kind: "error", message: "verify: aborted", details: facts };
362
+ if (result.timedOut) return { kind: "error", message: `verify: timed out after ${check.timeoutMs}ms`, details: facts };
363
+ if (result.exitCode !== 0) {
364
+ return {
365
+ kind: "error",
366
+ message: `verify: ${check.kind} command exited with code ${result.exitCode ?? "?"} before judgement: ${tail}`,
367
+ details: facts,
368
+ };
369
+ }
370
+ const report =
371
+ check.kind === "numeric-compare" && check.numeric !== undefined
372
+ ? judgeNumericCompare(result.stdout, check.numeric, process.cwd())
373
+ : check.kind === "perf-budget" && check.perf !== undefined
374
+ ? judgePerfBudget(result.durationMs, check.perf, process.cwd())
375
+ : new Error(`declared check '${check.id}' has kind ${check.kind} without its parameters`);
376
+ if (report instanceof Error) return { kind: "error", message: `verify: ${report.message}`, details: facts };
377
+ const rendered = report.kind === "numeric-compare" ? renderNumericReport(report) : report.summary;
378
+ const details = { ...facts, report };
379
+ if (!report.passed) return { kind: "error", message: `verify: ${rendered}`, details };
380
+ return { kind: "ok", output: `${rendered}\n`, details };
381
+ }
382
+
210
383
  export async function runProjectCheck(check: DeclaredCheck, options?: { signal?: AbortSignal }): Promise<ToolResult> {
211
384
  const [file, ...vector] = check.command;
212
385
  if (file === undefined) return { kind: "error", message: `verify: declared check '${check.id}' has empty argv` };
213
386
  const cwd = resolveProjectVerifierExecutionCwd(check.cwd, process.cwd());
214
387
  if (cwd instanceof Error) return { kind: "error", message: `verify: ${cwd.message}` };
388
+ if (check.kind !== "command") {
389
+ return withDeclaredEvidence(await runJudgedCheck(check, file, vector, cwd, options), check);
390
+ }
215
391
  const result = await runVectorTool("verify", file, vector, { cwd, timeout_ms: check.timeoutMs }, options);
216
392
  return withDeclaredEvidence(result, check);
217
393
  }
218
394
 
395
+ /**
396
+ * Run a perf-budget check once and write its wall time as the baseline the
397
+ * check's `baseline` path names. The command must exit cleanly; a failed run
398
+ * records nothing, so a baseline never encodes a broken command's timing.
399
+ */
400
+ export async function recordPerfBaseline(
401
+ check: DeclaredCheck,
402
+ options?: { signal?: AbortSignal; now?: () => Date },
403
+ ): Promise<{ ok: true; path: string; wallTimeMs: number } | { ok: false; message: string }> {
404
+ if (check.kind !== "perf-budget" || check.perf?.baseline === undefined) {
405
+ return { ok: false, message: `check '${check.id}' is not a perf-budget check with a baseline path` };
406
+ }
407
+ const [file, ...vector] = check.command;
408
+ if (file === undefined) return { ok: false, message: `declared check '${check.id}' has empty argv` };
409
+ const cwd = resolveProjectVerifierExecutionCwd(check.cwd, process.cwd());
410
+ if (cwd instanceof Error) return { ok: false, message: cwd.message };
411
+ let result: SafeCommandResult;
412
+ try {
413
+ result = await runCommandVector(file, vector, {
414
+ cwd,
415
+ timeoutMs: check.timeoutMs,
416
+ ...(options?.signal !== undefined ? { signal: options.signal } : {}),
417
+ });
418
+ } catch (error) {
419
+ return { ok: false, message: error instanceof Error ? error.message : String(error) };
420
+ }
421
+ if (result.aborted || result.timedOut || result.exitCode !== 0) {
422
+ return {
423
+ ok: false,
424
+ message: `command ${result.timedOut ? "timed out" : result.aborted ? "was aborted" : `exited with code ${result.exitCode ?? "?"}`}; no baseline recorded`,
425
+ };
426
+ }
427
+ let target: string;
428
+ try {
429
+ target = resolveSafeCwd(check.perf.baseline, process.cwd());
430
+ } catch (error) {
431
+ return { ok: false, message: `baseline ${error instanceof Error ? error.message : String(error)}` };
432
+ }
433
+ const recordedAt = (options?.now?.() ?? new Date()).toISOString();
434
+ try {
435
+ mkdirSync(path.dirname(target), { recursive: true });
436
+ writeFileSync(target, renderPerfBaseline({ wallTimeMs: result.durationMs, check: check.id, recordedAt }), "utf8");
437
+ } catch (error) {
438
+ return {
439
+ ok: false,
440
+ message: `cannot write baseline '${check.perf.baseline}' (${error instanceof Error ? error.message : String(error)})`,
441
+ };
442
+ }
443
+ return { ok: true, path: check.perf.baseline, wallTimeMs: result.durationMs };
444
+ }
445
+
219
446
  export async function runScriptCheck(
220
447
  check: string,
221
448
  args: Record<string, unknown>,
@@ -1,313 +0,0 @@
1
- import { createRequire as __clioCreateRequire } from "node:module"; const require = __clioCreateRequire(import.meta.url);
2
- import {
3
- isProjectVerifierCheckId
4
- } from "./chunk-UL3WSD3F.js";
5
- import {
6
- SAFE_EXEC_DEFAULT_TIMEOUT_MS,
7
- resolveSafeCwd
8
- } from "./chunk-JSC3U7TI.js";
9
- import {
10
- require_dist
11
- } from "./chunk-APJ265NV.js";
12
- import {
13
- __toESM,
14
- init_esm_shims
15
- } from "./chunk-3R73A4XB.js";
16
-
17
- // src/tools/verify/catalog.ts
18
- init_esm_shims();
19
- var import_yaml = __toESM(require_dist(), 1);
20
- import { existsSync, readFileSync, realpathSync, statSync } from "node:fs";
21
- import path from "node:path";
22
-
23
- // src/domains/evidence/ordering.ts
24
- init_esm_shims();
25
- function compareCodepoints(left, right) {
26
- return left < right ? -1 : left > right ? 1 : 0;
27
- }
28
-
29
- // src/tools/verify/catalog.ts
30
- var PROJECT_VERIFIER_CATALOG_RELATIVE_PATH = ".clio-coder/verifiers.yaml";
31
- var PROJECT_VERIFIER_CATALOG_VERSION = 1;
32
- var PROJECT_VERIFIER_CATALOG_CAPS = Object.freeze({
33
- fileBytes: 256 * 1024,
34
- checks: 128,
35
- idBytes: 64,
36
- descriptionBytes: 512,
37
- argvEntries: 64,
38
- argumentBytes: 4096,
39
- cwdBytes: 512,
40
- timeoutMs: 9e5,
41
- tags: 16,
42
- tagBytes: 32
43
- });
44
- var ROOT_FIELDS = /* @__PURE__ */ new Set(["version", "checks"]);
45
- var CHECK_FIELDS = /* @__PURE__ */ new Set(["id", "description", "command", "cwd", "timeoutMs", "tags"]);
46
- var TAG_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
47
- var SHELL_EXECUTABLES = /* @__PURE__ */ new Set([
48
- "bash",
49
- "cmd",
50
- "command.com",
51
- "dash",
52
- "fish",
53
- "ksh",
54
- "powershell",
55
- "pwsh",
56
- "sh",
57
- "tcsh",
58
- "zsh"
59
- ]);
60
- function isRecord(value) {
61
- return value !== null && typeof value === "object" && !Array.isArray(value);
62
- }
63
- function utf8Bytes(value) {
64
- return Buffer.byteLength(value, "utf8");
65
- }
66
- function hasControlCharacter(value) {
67
- for (let index = 0; index < value.length; index += 1) {
68
- const code = value.charCodeAt(index);
69
- if (code <= 31 || code === 127) return true;
70
- }
71
- return false;
72
- }
73
- function catalogDiagnostic(message) {
74
- return { ok: false, reason: `${PROJECT_VERIFIER_CATALOG_RELATIVE_PATH}: ${message}` };
75
- }
76
- function unknownFields(record, allowed) {
77
- return Object.keys(record).filter((key) => !allowed.has(key)).sort(compareCodepoints);
78
- }
79
- function relativeCwd(workspaceRoot, resolved) {
80
- const relative = path.relative(workspaceRoot, resolved);
81
- return relative.length === 0 ? "." : relative.split(path.sep).join("/");
82
- }
83
- function safelyResolveCatalogCwd(rawCwd, workspaceRoot, location) {
84
- if (path.isAbsolute(rawCwd) || path.win32.isAbsolute(rawCwd)) {
85
- return new Error(`${location} must be repository-relative; absolute cwd '${rawCwd}' is not allowed`);
86
- }
87
- let resolved;
88
- try {
89
- resolved = resolveSafeCwd(rawCwd, workspaceRoot);
90
- } catch {
91
- return new Error(`${location} escapes the workspace root: '${rawCwd}'`);
92
- }
93
- let realCwd;
94
- try {
95
- const cwdStat = statSync(resolved);
96
- if (!cwdStat.isDirectory()) return new Error(`${location} is not a directory: '${rawCwd}'`);
97
- const realRoot = realpathSync(workspaceRoot);
98
- realCwd = realpathSync(resolved);
99
- resolveSafeCwd(realCwd, realRoot);
100
- } catch (error) {
101
- const message = error instanceof Error ? error.message : String(error);
102
- if (message.includes("escapes workspace root")) {
103
- return new Error(`${location} escapes the workspace root through a symbolic link: '${rawCwd}'`);
104
- }
105
- return new Error(`${location} cannot be resolved as a repository directory: '${rawCwd}' (${message})`);
106
- }
107
- return { declared: relativeCwd(workspaceRoot, resolved), execution: realCwd };
108
- }
109
- function resolveProjectVerifierExecutionCwd(rawCwd, workspaceRoot) {
110
- const resolution = safelyResolveCatalogCwd(rawCwd, workspaceRoot, "project check cwd");
111
- return resolution instanceof Error ? resolution : resolution.execution;
112
- }
113
- function validateId(value, location) {
114
- if (typeof value !== "string" || value.length === 0) return new Error(`${location} must be a non-empty string`);
115
- if (utf8Bytes(value) > PROJECT_VERIFIER_CATALOG_CAPS.idBytes) {
116
- return new Error(`${location} exceeds the ${PROJECT_VERIFIER_CATALOG_CAPS.idBytes}-byte cap`);
117
- }
118
- if (!isProjectVerifierCheckId(value)) {
119
- return new Error(`${location} must match /^[a-z0-9][a-z0-9._:-]*$/`);
120
- }
121
- if (value === "frontend") return new Error(`${location} uses reserved built-in check id 'frontend'`);
122
- return value;
123
- }
124
- function validateDescription(value, location) {
125
- if (typeof value !== "string" || value.length === 0) return new Error(`${location} must be a non-empty string`);
126
- if (value.trim() !== value || hasControlCharacter(value)) {
127
- return new Error(`${location} must be trimmed, single-line text without control characters`);
128
- }
129
- if (utf8Bytes(value) > PROJECT_VERIFIER_CATALOG_CAPS.descriptionBytes) {
130
- return new Error(`${location} exceeds the ${PROJECT_VERIFIER_CATALOG_CAPS.descriptionBytes}-byte cap`);
131
- }
132
- return value;
133
- }
134
- function validateCommand(value, location) {
135
- if (!Array.isArray(value) || value.length === 0) {
136
- return new Error(`${location} must be a non-empty argv string array; shell command strings are not allowed`);
137
- }
138
- if (value.length > PROJECT_VERIFIER_CATALOG_CAPS.argvEntries) {
139
- return new Error(`${location} exceeds the ${PROJECT_VERIFIER_CATALOG_CAPS.argvEntries}-entry cap`);
140
- }
141
- const command = [];
142
- for (const [index, entry] of value.entries()) {
143
- const entryLocation = `${location}[${index}]`;
144
- if (typeof entry !== "string" || entry.length === 0) {
145
- return new Error(`${entryLocation} must be a non-empty string`);
146
- }
147
- if (entry.includes("\0")) return new Error(`${entryLocation} must not contain a NUL byte`);
148
- if (utf8Bytes(entry) > PROJECT_VERIFIER_CATALOG_CAPS.argumentBytes) {
149
- return new Error(`${entryLocation} exceeds the ${PROJECT_VERIFIER_CATALOG_CAPS.argumentBytes}-byte cap`);
150
- }
151
- command.push(entry);
152
- }
153
- const executable = command[0] ?? "";
154
- if (/\s/u.test(executable)) {
155
- return new Error(`${location}[0] must be one executable token, not a shell command string`);
156
- }
157
- const executableName = path.basename(executable).toLowerCase().replace(/\.exe$/u, "");
158
- if (SHELL_EXECUTABLES.has(executableName)) {
159
- return new Error(`${location}[0] may not invoke shell executable '${executable}'`);
160
- }
161
- return command;
162
- }
163
- function validateTimeout(value, location) {
164
- if (!Number.isInteger(value) || typeof value !== "number" || value <= 0) {
165
- return new Error(`${location} must be a positive integer number of milliseconds`);
166
- }
167
- if (value > PROJECT_VERIFIER_CATALOG_CAPS.timeoutMs) {
168
- return new Error(`${location} exceeds the ${PROJECT_VERIFIER_CATALOG_CAPS.timeoutMs}ms cap`);
169
- }
170
- return value;
171
- }
172
- function validateTags(value, location) {
173
- if (!Array.isArray(value)) return new Error(`${location} must be an array of bounded tag strings`);
174
- if (value.length > PROJECT_VERIFIER_CATALOG_CAPS.tags) {
175
- return new Error(`${location} exceeds the ${PROJECT_VERIFIER_CATALOG_CAPS.tags}-tag cap`);
176
- }
177
- const tags = [];
178
- const seen = /* @__PURE__ */ new Set();
179
- for (const [index, entry] of value.entries()) {
180
- const entryLocation = `${location}[${index}]`;
181
- if (typeof entry !== "string" || entry.length === 0) {
182
- return new Error(`${entryLocation} must be a non-empty string`);
183
- }
184
- if (utf8Bytes(entry) > PROJECT_VERIFIER_CATALOG_CAPS.tagBytes) {
185
- return new Error(`${entryLocation} exceeds the ${PROJECT_VERIFIER_CATALOG_CAPS.tagBytes}-byte cap`);
186
- }
187
- if (!TAG_PATTERN.test(entry)) return new Error(`${entryLocation} must match /^[a-z0-9][a-z0-9._-]*$/`);
188
- if (seen.has(entry)) return new Error(`${location} contains duplicate tag '${entry}'`);
189
- seen.add(entry);
190
- tags.push(entry);
191
- }
192
- return tags;
193
- }
194
- function sourcePathInsideWorkspace(catalogPath, workspaceRoot) {
195
- try {
196
- const realRoot = realpathSync(workspaceRoot);
197
- const realCatalogPath = realpathSync(catalogPath);
198
- resolveSafeCwd(realCatalogPath, realRoot);
199
- return realCatalogPath;
200
- } catch (error) {
201
- const message = error instanceof Error ? error.message : String(error);
202
- return new Error(`catalog file must resolve inside the workspace root (${message})`);
203
- }
204
- }
205
- function loadProjectVerifierCatalog(workspaceRoot) {
206
- const catalogPath = path.join(workspaceRoot, PROJECT_VERIFIER_CATALOG_RELATIVE_PATH);
207
- if (!existsSync(catalogPath)) return { ok: true, source: null };
208
- const safeSourcePath = sourcePathInsideWorkspace(catalogPath, workspaceRoot);
209
- if (safeSourcePath instanceof Error) return catalogDiagnostic(safeSourcePath.message);
210
- let text;
211
- try {
212
- const stats = statSync(safeSourcePath);
213
- if (!stats.isFile()) return catalogDiagnostic("catalog path must be a regular file");
214
- if (stats.size > PROJECT_VERIFIER_CATALOG_CAPS.fileBytes) {
215
- return catalogDiagnostic(`file exceeds the ${PROJECT_VERIFIER_CATALOG_CAPS.fileBytes}-byte cap`);
216
- }
217
- text = readFileSync(safeSourcePath, "utf8");
218
- } catch (error) {
219
- return catalogDiagnostic(`cannot read catalog (${error instanceof Error ? error.message : String(error)})`);
220
- }
221
- return parseProjectVerifierCatalogText(text, workspaceRoot, catalogPath);
222
- }
223
- function parseProjectVerifierCatalogText(text, workspaceRoot, catalogPath = path.join(workspaceRoot, PROJECT_VERIFIER_CATALOG_RELATIVE_PATH)) {
224
- const document = (0, import_yaml.parseDocument)(text, { prettyErrors: false, strict: true, uniqueKeys: true });
225
- if (document.errors.length > 0) {
226
- return catalogDiagnostic(`invalid YAML: ${document.errors.map((error) => error.message).join("; ")}`);
227
- }
228
- let parsed;
229
- try {
230
- parsed = document.toJS({ maxAliasCount: 0 });
231
- } catch (error) {
232
- return catalogDiagnostic(`invalid YAML: ${error instanceof Error ? error.message : String(error)}`);
233
- }
234
- if (!isRecord(parsed)) return catalogDiagnostic("root must be an object with version and checks fields");
235
- const rootUnknown = unknownFields(parsed, ROOT_FIELDS);
236
- if (rootUnknown.length > 0) return catalogDiagnostic(`root has unknown field(s): ${rootUnknown.join(", ")}`);
237
- if (!Object.hasOwn(parsed, "version")) return catalogDiagnostic("root.version is required");
238
- if (parsed.version !== PROJECT_VERIFIER_CATALOG_VERSION) {
239
- return catalogDiagnostic(
240
- `unsupported version ${JSON.stringify(parsed.version)}; supported version is ${PROJECT_VERIFIER_CATALOG_VERSION}`
241
- );
242
- }
243
- if (!Object.hasOwn(parsed, "checks")) return catalogDiagnostic("root.checks is required");
244
- if (!Array.isArray(parsed.checks)) return catalogDiagnostic("root.checks must be an array");
245
- if (parsed.checks.length > PROJECT_VERIFIER_CATALOG_CAPS.checks) {
246
- return catalogDiagnostic(`root.checks exceeds the ${PROJECT_VERIFIER_CATALOG_CAPS.checks}-check cap`);
247
- }
248
- const sourceRef = { kind: "project-catalog", path: catalogPath };
249
- const checks = [];
250
- const ids = /* @__PURE__ */ new Map();
251
- for (const [index, value] of parsed.checks.entries()) {
252
- const location = `checks[${index}]`;
253
- if (!isRecord(value)) return catalogDiagnostic(`${location} must be an object`);
254
- const checkUnknown = unknownFields(value, CHECK_FIELDS);
255
- if (checkUnknown.length > 0) {
256
- return catalogDiagnostic(`${location} has unknown field(s): ${checkUnknown.join(", ")}`);
257
- }
258
- for (const field of CHECK_FIELDS) {
259
- if (!Object.hasOwn(value, field)) return catalogDiagnostic(`${location}.${field} is required`);
260
- }
261
- const id = validateId(value.id, `${location}.id`);
262
- if (id instanceof Error) return catalogDiagnostic(id.message);
263
- const duplicateIndex = ids.get(id);
264
- if (duplicateIndex !== void 0) {
265
- return catalogDiagnostic(`${location}.id duplicates '${id}' from checks[${duplicateIndex}].id`);
266
- }
267
- const description = validateDescription(value.description, `${location}.description`);
268
- if (description instanceof Error) return catalogDiagnostic(description.message);
269
- const command = validateCommand(value.command, `${location}.command`);
270
- if (command instanceof Error) return catalogDiagnostic(command.message);
271
- if (typeof value.cwd !== "string" || value.cwd.length === 0) {
272
- return catalogDiagnostic(`${location}.cwd must be a non-empty repository-relative string`);
273
- }
274
- if (value.cwd.includes("\0")) return catalogDiagnostic(`${location}.cwd must not contain a NUL byte`);
275
- if (utf8Bytes(value.cwd) > PROJECT_VERIFIER_CATALOG_CAPS.cwdBytes) {
276
- return catalogDiagnostic(`${location}.cwd exceeds the ${PROJECT_VERIFIER_CATALOG_CAPS.cwdBytes}-byte cap`);
277
- }
278
- const cwdResolution = safelyResolveCatalogCwd(value.cwd, workspaceRoot, `${location}.cwd`);
279
- if (cwdResolution instanceof Error) return catalogDiagnostic(cwdResolution.message);
280
- const cwd = cwdResolution.declared;
281
- const timeoutMs = validateTimeout(value.timeoutMs, `${location}.timeoutMs`);
282
- if (timeoutMs instanceof Error) return catalogDiagnostic(timeoutMs.message);
283
- const tags = validateTags(value.tags, `${location}.tags`);
284
- if (tags instanceof Error) return catalogDiagnostic(tags.message);
285
- ids.set(id, index);
286
- checks.push({ id, description, command, cwd, timeoutMs, tags, source: { ...sourceRef } });
287
- }
288
- checks.sort((left, right) => compareCodepoints(left.id, right.id));
289
- return { ok: true, source: { ...sourceRef, checks } };
290
- }
291
- function packageDeclaredCheck(id, packagePath, cwd, tags) {
292
- return {
293
- id,
294
- description: `Run package.json script '${id}'.`,
295
- command: ["npm", "run", id],
296
- cwd,
297
- timeoutMs: SAFE_EXEC_DEFAULT_TIMEOUT_MS,
298
- tags,
299
- source: { kind: "package.json", path: packagePath }
300
- };
301
- }
302
-
303
- export {
304
- compareCodepoints,
305
- PROJECT_VERIFIER_CATALOG_RELATIVE_PATH,
306
- PROJECT_VERIFIER_CATALOG_VERSION,
307
- PROJECT_VERIFIER_CATALOG_CAPS,
308
- resolveProjectVerifierExecutionCwd,
309
- loadProjectVerifierCatalog,
310
- parseProjectVerifierCatalogText,
311
- packageDeclaredCheck
312
- };
313
- //# sourceMappingURL=chunk-7DICMOS6.js.map
@@ -1,41 +0,0 @@
1
- import { createRequire as __clioCreateRequire } from "node:module"; const require = __clioCreateRequire(import.meta.url);
2
- import {
3
- init_esm_shims
4
- } from "./chunk-3R73A4XB.js";
5
-
6
- // src/domains/safety/rigor.ts
7
- init_esm_shims();
8
- import { existsSync } from "node:fs";
9
- import path from "node:path";
10
- var VALIDATION_CONTRACT_FILES = [
11
- path.join(".clio-coder", "validation.yaml"),
12
- path.join(".clio-coder", "validation.yml"),
13
- "validation.yaml",
14
- "validation.yml",
15
- "VALIDATION.md"
16
- ];
17
- function resolveRigor(options) {
18
- if (options.override === "high" || options.override === "normal") return options.override;
19
- const cwd = options.cwd ?? process.cwd();
20
- return hasValidationContract(cwd) ? "high" : "normal";
21
- }
22
- function parseRigorOverride(value) {
23
- if (typeof value !== "string") return null;
24
- const normalized = value.trim().toLowerCase();
25
- if (normalized === "high") return "high";
26
- if (normalized === "normal") return "normal";
27
- return null;
28
- }
29
- function hasValidationContract(cwd) {
30
- try {
31
- return VALIDATION_CONTRACT_FILES.some((relative) => existsSync(path.join(cwd, relative)));
32
- } catch {
33
- return false;
34
- }
35
- }
36
-
37
- export {
38
- resolveRigor,
39
- parseRigorOverride
40
- };
41
- //# sourceMappingURL=chunk-RVG5JXAL.js.map