@intentius/chant 0.80.0 → 0.81.0

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 (414) hide show
  1. package/dist/audit/discover.d.ts +8 -16
  2. package/dist/audit/discover.d.ts.map +1 -1
  3. package/dist/audit/report-html.d.ts +5 -0
  4. package/dist/audit/report-html.d.ts.map +1 -1
  5. package/dist/audit/report-model.d.ts +13 -0
  6. package/dist/audit/report-model.d.ts.map +1 -1
  7. package/dist/audit/terraform-state.d.ts +4 -5
  8. package/dist/audit/terraform-state.d.ts.map +1 -1
  9. package/dist/cli/commands/audit.d.ts +25 -9
  10. package/dist/cli/commands/audit.d.ts.map +1 -1
  11. package/dist/cli/commands/check-lexicon.d.ts +8 -0
  12. package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
  13. package/dist/cli/commands/doctor.d.ts.map +1 -1
  14. package/dist/cli/commands/import-agents.d.ts.map +1 -1
  15. package/dist/cli/commands/init.d.ts.map +1 -1
  16. package/dist/cli/commands/lint.d.ts.map +1 -1
  17. package/dist/cli/commands/update.d.ts +6 -0
  18. package/dist/cli/commands/update.d.ts.map +1 -1
  19. package/dist/cli/commands/vendor.d.ts +5 -0
  20. package/dist/cli/commands/vendor.d.ts.map +1 -1
  21. package/dist/cli/handlers/build.d.ts.map +1 -1
  22. package/dist/cli/handlers/components.d.ts.map +1 -1
  23. package/dist/cli/handlers/dev.d.ts.map +1 -1
  24. package/dist/cli/handlers/fan-out.d.ts.map +1 -1
  25. package/dist/cli/handlers/init.d.ts.map +1 -1
  26. package/dist/cli/handlers/operator.d.ts +7 -0
  27. package/dist/cli/handlers/operator.d.ts.map +1 -1
  28. package/dist/cli/handlers/promote.d.ts +7 -4
  29. package/dist/cli/handlers/promote.d.ts.map +1 -1
  30. package/dist/cli/handlers/run-generate.d.ts.map +1 -1
  31. package/dist/cli/handlers/run.d.ts +4 -1
  32. package/dist/cli/handlers/run.d.ts.map +1 -1
  33. package/dist/cli/handlers/vendor.d.ts +8 -3
  34. package/dist/cli/handlers/vendor.d.ts.map +1 -1
  35. package/dist/cli/main.d.ts +12 -0
  36. package/dist/cli/main.d.ts.map +1 -1
  37. package/dist/cli/plugins.d.ts +12 -7
  38. package/dist/cli/plugins.d.ts.map +1 -1
  39. package/dist/cli/registry.d.ts +32 -0
  40. package/dist/cli/registry.d.ts.map +1 -1
  41. package/dist/codegen/fetch.d.ts +10 -0
  42. package/dist/codegen/fetch.d.ts.map +1 -1
  43. package/dist/components/cli-support.d.ts +3 -1
  44. package/dist/components/cli-support.d.ts.map +1 -1
  45. package/dist/components/discover.d.ts.map +1 -1
  46. package/dist/components/driver.d.ts +16 -2
  47. package/dist/components/driver.d.ts.map +1 -1
  48. package/dist/components/gate-plan.d.ts +40 -0
  49. package/dist/components/gate-plan.d.ts.map +1 -0
  50. package/dist/components/promote.d.ts +60 -7
  51. package/dist/components/promote.d.ts.map +1 -1
  52. package/dist/components/sandbox/driver.d.ts.map +1 -1
  53. package/dist/components/sandbox/run.d.ts.map +1 -1
  54. package/dist/components/verbs/build-archive.d.ts +22 -11
  55. package/dist/components/verbs/build-archive.d.ts.map +1 -1
  56. package/dist/components/verbs/run-agent.d.ts.map +1 -1
  57. package/dist/config-static.d.ts +59 -0
  58. package/dist/config-static.d.ts.map +1 -0
  59. package/dist/config.d.ts +32 -10
  60. package/dist/config.d.ts.map +1 -1
  61. package/dist/content-digest.d.ts +17 -0
  62. package/dist/content-digest.d.ts.map +1 -0
  63. package/dist/discovery/files.d.ts +10 -5
  64. package/dist/discovery/files.d.ts.map +1 -1
  65. package/dist/discovery/fold-import.d.ts +20 -4
  66. package/dist/discovery/fold-import.d.ts.map +1 -1
  67. package/dist/discovery/index.d.ts.map +1 -1
  68. package/dist/discovery/sandbox/driver.d.ts +20 -0
  69. package/dist/discovery/sandbox/driver.d.ts.map +1 -1
  70. package/dist/discovery/sandbox/fork.d.ts +20 -0
  71. package/dist/discovery/sandbox/fork.d.ts.map +1 -1
  72. package/dist/discovery/walk.d.ts +119 -0
  73. package/dist/discovery/walk.d.ts.map +1 -0
  74. package/dist/graph-ir.d.ts +4 -1
  75. package/dist/graph-ir.d.ts.map +1 -1
  76. package/dist/join-key.d.ts +31 -0
  77. package/dist/join-key.d.ts.map +1 -0
  78. package/dist/lexicon-module.d.ts +51 -6
  79. package/dist/lexicon-module.d.ts.map +1 -1
  80. package/dist/lexicon.d.ts +58 -1
  81. package/dist/lexicon.d.ts.map +1 -1
  82. package/dist/lifecycle/build-ledger-store.d.ts.map +1 -1
  83. package/dist/lifecycle/digest.d.ts +5 -1
  84. package/dist/lifecycle/digest.d.ts.map +1 -1
  85. package/dist/lifecycle/gate-ledger.d.ts +20 -5
  86. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  87. package/dist/lifecycle/git.d.ts +64 -0
  88. package/dist/lifecycle/git.d.ts.map +1 -1
  89. package/dist/lifecycle/lease.d.ts +8 -1
  90. package/dist/lifecycle/lease.d.ts.map +1 -1
  91. package/dist/lifecycle/legacy-digest.d.ts +41 -8
  92. package/dist/lifecycle/legacy-digest.d.ts.map +1 -1
  93. package/dist/lifecycle/member-ledger.d.ts +67 -0
  94. package/dist/lifecycle/member-ledger.d.ts.map +1 -0
  95. package/dist/lifecycle/plan-digest.d.ts +4 -3
  96. package/dist/lifecycle/plan-digest.d.ts.map +1 -1
  97. package/dist/lifecycle/release-ledger.d.ts +18 -2
  98. package/dist/lifecycle/release-ledger.d.ts.map +1 -1
  99. package/dist/lifecycle/status.d.ts +90 -5
  100. package/dist/lifecycle/status.d.ts.map +1 -1
  101. package/dist/op/activities/activity-contracts.d.ts +32 -0
  102. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  103. package/dist/op/activities/index.d.ts +2 -0
  104. package/dist/op/activities/index.d.ts.map +1 -1
  105. package/dist/op/activities/propose-upgrade.d.ts +75 -0
  106. package/dist/op/activities/propose-upgrade.d.ts.map +1 -0
  107. package/dist/op/discover.d.ts.map +1 -1
  108. package/dist/op/gate-name.d.ts +7 -0
  109. package/dist/op/gate-name.d.ts.map +1 -1
  110. package/dist/op/gate-summary.d.ts +16 -0
  111. package/dist/op/gate-summary.d.ts.map +1 -1
  112. package/dist/op/gate.d.ts +16 -2
  113. package/dist/op/gate.d.ts.map +1 -1
  114. package/dist/project-root.d.ts +26 -0
  115. package/dist/project-root.d.ts.map +1 -1
  116. package/dist/workspace/__fixtures__/contract-repo.d.ts +37 -0
  117. package/dist/workspace/__fixtures__/contract-repo.d.ts.map +1 -0
  118. package/dist/workspace/__fixtures__/two-member-workspace.d.ts +11 -0
  119. package/dist/workspace/__fixtures__/two-member-workspace.d.ts.map +1 -0
  120. package/dist/workspace/checks/generated.d.ts +156 -0
  121. package/dist/workspace/checks/generated.d.ts.map +1 -0
  122. package/dist/workspace/checks/ledgers.d.ts +78 -0
  123. package/dist/workspace/checks/ledgers.d.ts.map +1 -0
  124. package/dist/workspace/checks/links.d.ts +25 -0
  125. package/dist/workspace/checks/links.d.ts.map +1 -0
  126. package/dist/workspace/checks/pipelines.d.ts +76 -0
  127. package/dist/workspace/checks/pipelines.d.ts.map +1 -0
  128. package/dist/workspace/checks.d.ts +161 -0
  129. package/dist/workspace/checks.d.ts.map +1 -0
  130. package/dist/workspace/compose-graph.d.ts +115 -0
  131. package/dist/workspace/compose-graph.d.ts.map +1 -0
  132. package/dist/workspace/compose-reports.d.ts +68 -0
  133. package/dist/workspace/compose-reports.d.ts.map +1 -0
  134. package/dist/workspace/declaration.d.ts +220 -0
  135. package/dist/workspace/declaration.d.ts.map +1 -0
  136. package/dist/workspace/declaration.schema.json +434 -0
  137. package/dist/workspace/generated-files.d.ts +65 -0
  138. package/dist/workspace/generated-files.d.ts.map +1 -0
  139. package/dist/workspace/glob.d.ts +13 -0
  140. package/dist/workspace/glob.d.ts.map +1 -0
  141. package/dist/workspace/graph-cli.d.ts +75 -0
  142. package/dist/workspace/graph-cli.d.ts.map +1 -0
  143. package/dist/workspace/init.d.ts +96 -0
  144. package/dist/workspace/init.d.ts.map +1 -0
  145. package/dist/workspace/jsonc.d.ts +38 -0
  146. package/dist/workspace/jsonc.d.ts.map +1 -0
  147. package/dist/workspace/kinds.d.ts +192 -0
  148. package/dist/workspace/kinds.d.ts.map +1 -0
  149. package/dist/workspace/lineage-check.d.ts +84 -0
  150. package/dist/workspace/lineage-check.d.ts.map +1 -0
  151. package/dist/workspace/lineage-cli.d.ts +31 -0
  152. package/dist/workspace/lineage-cli.d.ts.map +1 -0
  153. package/dist/workspace/lineage-init.d.ts +101 -0
  154. package/dist/workspace/lineage-init.d.ts.map +1 -0
  155. package/dist/workspace/lineage-lock.d.ts +258 -0
  156. package/dist/workspace/lineage-lock.d.ts.map +1 -0
  157. package/dist/workspace/lineage-merge.d.ts +14 -0
  158. package/dist/workspace/lineage-merge.d.ts.map +1 -0
  159. package/dist/workspace/lineage-migrations.d.ts +178 -0
  160. package/dist/workspace/lineage-migrations.d.ts.map +1 -0
  161. package/dist/workspace/lineage-update.d.ts +59 -0
  162. package/dist/workspace/lineage-update.d.ts.map +1 -0
  163. package/dist/workspace/lineage-upgrade-cli.d.ts +40 -0
  164. package/dist/workspace/lineage-upgrade-cli.d.ts.map +1 -0
  165. package/dist/workspace/lineage-upgrade.d.ts +146 -0
  166. package/dist/workspace/lineage-upgrade.d.ts.map +1 -0
  167. package/dist/workspace/lineage-vendor.d.ts +63 -0
  168. package/dist/workspace/lineage-vendor.d.ts.map +1 -0
  169. package/dist/workspace/lineage-version.d.ts +32 -0
  170. package/dist/workspace/lineage-version.d.ts.map +1 -0
  171. package/dist/workspace/links.d.ts +150 -0
  172. package/dist/workspace/links.d.ts.map +1 -0
  173. package/dist/workspace/ls.d.ts +99 -0
  174. package/dist/workspace/ls.d.ts.map +1 -0
  175. package/dist/workspace/member-commands.d.ts +139 -0
  176. package/dist/workspace/member-commands.d.ts.map +1 -0
  177. package/dist/workspace/member-handles.d.ts +54 -0
  178. package/dist/workspace/member-handles.d.ts.map +1 -0
  179. package/dist/workspace/member-pipeline.d.ts +143 -0
  180. package/dist/workspace/member-pipeline.d.ts.map +1 -0
  181. package/dist/workspace/member-run.d.ts +67 -0
  182. package/dist/workspace/member-run.d.ts.map +1 -0
  183. package/dist/workspace/reason-codes.d.ts +65 -0
  184. package/dist/workspace/reason-codes.d.ts.map +1 -0
  185. package/dist/workspace/records-cli.d.ts +28 -4
  186. package/dist/workspace/records-cli.d.ts.map +1 -1
  187. package/dist/workspace/records.d.ts.map +1 -1
  188. package/dist/workspace/root-refusal.d.ts +53 -0
  189. package/dist/workspace/root-refusal.d.ts.map +1 -0
  190. package/dist/workspace/status.d.ts +150 -0
  191. package/dist/workspace/status.d.ts.map +1 -0
  192. package/dist/workspace/template-manifest.d.ts +90 -0
  193. package/dist/workspace/template-manifest.d.ts.map +1 -0
  194. package/dist/workspace/tree.d.ts +36 -0
  195. package/dist/workspace/tree.d.ts.map +1 -0
  196. package/dist/workspace/trust/attestor.d.ts +67 -0
  197. package/dist/workspace/trust/attestor.d.ts.map +1 -0
  198. package/dist/workspace/trust/policy.d.ts +111 -0
  199. package/dist/workspace/trust/policy.d.ts.map +1 -0
  200. package/dist/workspace/trust/provenance.d.ts +67 -0
  201. package/dist/workspace/trust/provenance.d.ts.map +1 -0
  202. package/dist/workspace/trust/ssh-commit.d.ts +43 -0
  203. package/dist/workspace/trust/ssh-commit.d.ts.map +1 -0
  204. package/dist/workspace/trust/test-repo.d.ts +42 -0
  205. package/dist/workspace/trust/test-repo.d.ts.map +1 -0
  206. package/dist/workspace/trust/verify-cli.d.ts +9 -0
  207. package/dist/workspace/trust/verify-cli.d.ts.map +1 -0
  208. package/dist/workspace/trust/verify.d.ts +66 -0
  209. package/dist/workspace/trust/verify.d.ts.map +1 -0
  210. package/dist/workspace/which-chant.d.ts +58 -0
  211. package/dist/workspace/which-chant.d.ts.map +1 -0
  212. package/dist/workspace/workspace-kinds.schema.json +133 -0
  213. package/package.json +2 -1
  214. package/src/audit/discover.ts +66 -78
  215. package/src/audit/report-html.ts +3 -1
  216. package/src/audit/report-model.ts +14 -1
  217. package/src/audit/terraform-state.test.ts +4 -9
  218. package/src/audit/terraform-state.ts +4 -5
  219. package/src/cli/commands/audit-truncation.test.ts +167 -0
  220. package/src/cli/commands/audit.ts +89 -60
  221. package/src/cli/commands/check-lexicon.ts +24 -0
  222. package/src/cli/commands/doctor.test.ts +30 -0
  223. package/src/cli/commands/doctor.ts +18 -0
  224. package/src/cli/commands/import-agents.ts +6 -2
  225. package/src/cli/commands/init.ts +22 -3
  226. package/src/cli/commands/lint.test.ts +17 -23
  227. package/src/cli/commands/lint.ts +24 -84
  228. package/src/cli/commands/update.ts +13 -4
  229. package/src/cli/commands/vendor.ts +11 -6
  230. package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +38 -0
  231. package/src/cli/handlers/build-member.test.ts +127 -0
  232. package/src/cli/handlers/build.ts +35 -1
  233. package/src/cli/handlers/components.test.ts +127 -0
  234. package/src/cli/handlers/components.ts +70 -8
  235. package/src/cli/handlers/dev.ts +5 -3
  236. package/src/cli/handlers/fan-out.ts +9 -2
  237. package/src/cli/handlers/init.ts +54 -1
  238. package/src/cli/handlers/operator.test.ts +68 -0
  239. package/src/cli/handlers/operator.ts +37 -9
  240. package/src/cli/handlers/promote.test.ts +118 -2
  241. package/src/cli/handlers/promote.ts +82 -16
  242. package/src/cli/handlers/run-generate-member.test.ts +83 -0
  243. package/src/cli/handlers/run-generate.test.ts +6 -8
  244. package/src/cli/handlers/run-generate.ts +36 -1
  245. package/src/cli/handlers/run.test.ts +47 -0
  246. package/src/cli/handlers/run.ts +28 -5
  247. package/src/cli/handlers/vendor.ts +147 -43
  248. package/src/cli/main.test.ts +105 -1
  249. package/src/cli/main.ts +230 -17
  250. package/src/cli/plugins.ts +17 -17
  251. package/src/cli/registry.ts +32 -0
  252. package/src/cli/static-config-read.test.ts +208 -0
  253. package/src/codegen/fetch.test.ts +63 -1
  254. package/src/codegen/fetch.ts +30 -1
  255. package/src/components/cli-support.ts +6 -1
  256. package/src/components/discover.test.ts +27 -57
  257. package/src/components/discover.ts +13 -68
  258. package/src/components/driver.test.ts +78 -1
  259. package/src/components/driver.ts +43 -7
  260. package/src/components/gate-plan.ts +53 -0
  261. package/src/components/promote.test.ts +276 -2
  262. package/src/components/promote.ts +119 -15
  263. package/src/components/sandbox/driver.ts +8 -8
  264. package/src/components/sandbox/run.ts +4 -1
  265. package/src/components/verbs/build-archive.ts +27 -21
  266. package/src/components/verbs/run-agent.ts +3 -5
  267. package/src/config-static.test.ts +136 -0
  268. package/src/config-static.ts +232 -0
  269. package/src/config.test.ts +2 -2
  270. package/src/config.ts +48 -15
  271. package/src/content-digest.test.ts +120 -0
  272. package/src/content-digest.ts +21 -0
  273. package/src/discovery/files.test.ts +10 -10
  274. package/src/discovery/files.ts +25 -81
  275. package/src/discovery/fold-import.ts +49 -5
  276. package/src/discovery/index.ts +1 -0
  277. package/src/discovery/sandbox/driver.ts +73 -35
  278. package/src/discovery/sandbox/fork-diagnostic.test.ts +136 -13
  279. package/src/discovery/sandbox/fork.ts +83 -43
  280. package/src/discovery/sandbox/path-lexicon-multifile.test.ts +285 -0
  281. package/src/discovery/walk.test.ts +263 -0
  282. package/src/discovery/walk.ts +334 -0
  283. package/src/effect-receipt.ts +2 -2
  284. package/src/graph-ir.ts +4 -1
  285. package/src/join-key.test.ts +25 -0
  286. package/src/join-key.ts +39 -0
  287. package/src/lexicon-module.ts +108 -10
  288. package/src/lexicon.ts +79 -1
  289. package/src/lifecycle/build-ledger-store.ts +11 -10
  290. package/src/lifecycle/digest.ts +9 -5
  291. package/src/lifecycle/gate-ledger.test.ts +20 -0
  292. package/src/lifecycle/gate-ledger.ts +28 -6
  293. package/src/lifecycle/git.test.ts +13 -1
  294. package/src/lifecycle/git.ts +221 -176
  295. package/src/lifecycle/lease.ts +25 -10
  296. package/src/lifecycle/legacy-digest.test.ts +115 -23
  297. package/src/lifecycle/legacy-digest.ts +60 -19
  298. package/src/lifecycle/member-ledger.test.ts +319 -0
  299. package/src/lifecycle/member-ledger.ts +145 -0
  300. package/src/lifecycle/plan-digest.ts +7 -7
  301. package/src/lifecycle/release-ledger.test.ts +20 -0
  302. package/src/lifecycle/release-ledger.ts +23 -7
  303. package/src/lifecycle/status.test.ts +151 -1
  304. package/src/lifecycle/status.ts +228 -7
  305. package/src/op/activities/activity-contracts.ts +37 -0
  306. package/src/op/activities/index.ts +10 -0
  307. package/src/op/activities/propose-upgrade.ts +206 -0
  308. package/src/op/discover.test.ts +14 -4
  309. package/src/op/discover.ts +19 -27
  310. package/src/op/gate-name.ts +8 -0
  311. package/src/op/gate-summary.test.ts +14 -0
  312. package/src/op/gate-summary.ts +25 -2
  313. package/src/op/gate.ts +36 -7
  314. package/src/op/generate-pipeline.test.ts +14 -5
  315. package/src/project-root.test.ts +66 -1
  316. package/src/project-root.ts +48 -0
  317. package/src/workspace/__fixtures__/contract-repo.ts +100 -0
  318. package/src/workspace/__fixtures__/two-member-workspace.ts +35 -0
  319. package/src/workspace/behold-kinds.test.ts +162 -0
  320. package/src/workspace/check-contract.test.ts +127 -0
  321. package/src/workspace/check.schema.json +347 -0
  322. package/src/workspace/checks/generated.test.ts +287 -0
  323. package/src/workspace/checks/generated.ts +475 -0
  324. package/src/workspace/checks/ledgers.test.ts +139 -0
  325. package/src/workspace/checks/ledgers.ts +246 -0
  326. package/src/workspace/checks/links.ts +183 -0
  327. package/src/workspace/checks/pipelines.test.ts +133 -0
  328. package/src/workspace/checks/pipelines.ts +225 -0
  329. package/src/workspace/checks-repo.test.ts +71 -0
  330. package/src/workspace/checks.test.ts +450 -0
  331. package/src/workspace/checks.ts +461 -0
  332. package/src/workspace/compose-graph.test.ts +146 -0
  333. package/src/workspace/compose-graph.ts +228 -0
  334. package/src/workspace/compose-reports.test.ts +109 -0
  335. package/src/workspace/compose-reports.ts +186 -0
  336. package/src/workspace/declaration.schema.json +434 -0
  337. package/src/workspace/declaration.test.ts +347 -0
  338. package/src/workspace/declaration.ts +623 -0
  339. package/src/workspace/generated-files.test.ts +114 -0
  340. package/src/workspace/generated-files.ts +94 -0
  341. package/src/workspace/glob.ts +49 -0
  342. package/src/workspace/graph-cli.ts +220 -0
  343. package/src/workspace/graph-contract.test.ts +204 -0
  344. package/src/workspace/graph.schema.json +662 -0
  345. package/src/workspace/init.test.ts +223 -0
  346. package/src/workspace/init.ts +585 -0
  347. package/src/workspace/jsonc.test.ts +65 -0
  348. package/src/workspace/jsonc.ts +231 -0
  349. package/src/workspace/kinds.test.ts +288 -0
  350. package/src/workspace/kinds.ts +506 -0
  351. package/src/workspace/lineage-check.ts +264 -0
  352. package/src/workspace/lineage-cli.ts +114 -0
  353. package/src/workspace/lineage-init.test.ts +231 -0
  354. package/src/workspace/lineage-init.ts +365 -0
  355. package/src/workspace/lineage-lock.test.ts +224 -0
  356. package/src/workspace/lineage-lock.ts +357 -0
  357. package/src/workspace/lineage-merge.ts +44 -0
  358. package/src/workspace/lineage-migrations.test.ts +178 -0
  359. package/src/workspace/lineage-migrations.ts +343 -0
  360. package/src/workspace/lineage-update.ts +160 -0
  361. package/src/workspace/lineage-upgrade-cli.ts +151 -0
  362. package/src/workspace/lineage-upgrade.test.ts +474 -0
  363. package/src/workspace/lineage-upgrade.ts +624 -0
  364. package/src/workspace/lineage-vendor.test.ts +126 -0
  365. package/src/workspace/lineage-vendor.ts +215 -0
  366. package/src/workspace/lineage-version.ts +127 -0
  367. package/src/workspace/links.test.ts +344 -0
  368. package/src/workspace/links.ts +331 -0
  369. package/src/workspace/ls-contract.test.ts +200 -0
  370. package/src/workspace/ls.schema.json +190 -0
  371. package/src/workspace/ls.ts +254 -0
  372. package/src/workspace/member-commands.e2e.test.ts +244 -0
  373. package/src/workspace/member-commands.test.ts +217 -0
  374. package/src/workspace/member-commands.ts +540 -0
  375. package/src/workspace/member-handles.test.ts +76 -0
  376. package/src/workspace/member-handles.ts +228 -0
  377. package/src/workspace/member-pipeline.test.ts +135 -0
  378. package/src/workspace/member-pipeline.ts +317 -0
  379. package/src/workspace/member-run.ts +146 -0
  380. package/src/workspace/read-contract.test.ts +129 -0
  381. package/src/workspace/reason-codes.test.ts +113 -0
  382. package/src/workspace/reason-codes.ts +81 -0
  383. package/src/workspace/records-cli.ts +86 -14
  384. package/src/workspace/records-contract.test.ts +5 -0
  385. package/src/workspace/records.schema.json +32 -2
  386. package/src/workspace/records.ts +3 -2
  387. package/src/workspace/root-refusal.ts +97 -0
  388. package/src/workspace/status-contract.test.ts +308 -0
  389. package/src/workspace/status.schema.json +210 -0
  390. package/src/workspace/status.ts +412 -0
  391. package/src/workspace/template-manifest.test.ts +79 -0
  392. package/src/workspace/template-manifest.ts +221 -0
  393. package/src/workspace/tree.ts +132 -0
  394. package/src/workspace/trust/attestor.ts +93 -0
  395. package/src/workspace/trust/policy.ts +306 -0
  396. package/src/workspace/trust/provenance.ts +181 -0
  397. package/src/workspace/trust/ssh-commit.ts +138 -0
  398. package/src/workspace/trust/test-repo.ts +138 -0
  399. package/src/workspace/trust/trust.test.ts +397 -0
  400. package/src/workspace/trust/verify-cli.ts +56 -0
  401. package/src/workspace/trust/verify.ts +194 -0
  402. package/src/workspace/which-chant.test.ts +117 -0
  403. package/src/workspace/which-chant.ts +151 -0
  404. package/src/workspace/workspace-kinds.schema.json +133 -0
  405. package/dist/components/unbound-gate-approval.d.ts +0 -24
  406. package/dist/components/unbound-gate-approval.d.ts.map +0 -1
  407. package/dist/discovery/convergence.d.ts +0 -97
  408. package/dist/discovery/convergence.d.ts.map +0 -1
  409. package/src/cli/commands/audit-walk-warnings.test.ts +0 -156
  410. package/src/components/unbound-gate-approval.test.ts +0 -82
  411. package/src/components/unbound-gate-approval.ts +0 -51
  412. package/src/discovery/convergence.test.ts +0 -231
  413. package/src/discovery/convergence.ts +0 -399
  414. package/src/op/discover-convergence.test.ts +0 -70
@@ -1,10 +1,9 @@
1
- import { readdir, stat, open } from "node:fs/promises";
2
- import { existsSync } from "node:fs";
3
- import { join, relative, sep, isAbsolute } from "node:path";
1
+ import { open } from "node:fs/promises";
2
+ import { relative, sep, isAbsolute } from "node:path";
4
3
  // @ts-ignore — picomatch has no types declaration
5
4
  import picomatch from "picomatch";
6
5
  import { resolveDiscoveryGlobs, type DiscoveryGlobs } from "../config";
7
- import { warnDiscoveryChanges } from "./convergence";
6
+ import { readHead, walkDiscovery, workspaceMemberDirs } from "./walk";
8
7
 
9
8
  /**
10
9
  * Marker chant writes at the top of files it generates (a hosting lexicon's
@@ -55,6 +54,12 @@ export async function hasDiscoveryMarker(file: string): Promise<boolean> {
55
54
  }
56
55
  }
57
56
 
57
+ /** Whether a file's head carries the {@link GENERATED_MARKER} or the {@link SKIP_MARKER}. The synchronous form of {@link hasDiscoveryMarker}. */
58
+ export function hasDiscoveryMarkerSync(file: string): boolean {
59
+ const head = readHead(file, SKIP_MARKER_HEAD_BYTES);
60
+ return head.slice(0, 256).includes(GENERATED_MARKER) || hasSkipMarker(head);
61
+ }
62
+
58
63
  /**
59
64
  * Compile a project's `exclude`/`include` globs (#2519) into a predicate that
60
65
  * is true for a file discovery must skip, or `undefined` when there is nothing
@@ -65,7 +70,8 @@ export async function hasDiscoveryMarker(file: string): Promise<boolean> {
65
70
  * of every directory above it, so a pattern naming a directory covers
66
71
  * everything under it. A file is skipped when some `exclude` pattern matches
67
72
  * and no `include` pattern does: `include` always wins. Files outside
68
- * `globs.root` are never skipped.
73
+ * `globs.root` are never skipped. The discovery walk (`./walk.ts`) applies the
74
+ * same rule, and also lets `include` re-admit what its default rules skip.
69
75
  */
70
76
  export function compileDiscoveryFilter(globs: DiscoveryGlobs | undefined): ((file: string) => boolean) | undefined {
71
77
  if (!globs || globs.exclude.length === 0) return undefined;
@@ -89,86 +95,24 @@ export interface FindInfraFilesOptions {
89
95
  globs?: DiscoveryGlobs | null;
90
96
  }
91
97
 
98
+ /** A TypeScript source file by name: `.ts`, not a test or spec. */
99
+ export function isSourceFileName(name: string): boolean {
100
+ return name.endsWith(".ts") && !name.endsWith(".test.ts") && !name.endsWith(".spec.ts");
101
+ }
102
+
92
103
  /**
93
- * Recursively find all TypeScript infrastructure files in a directory
94
- * @param path - The directory path to search
95
- * @returns Array of file paths to .ts files (excluding test files, chant-generated
96
- * files, files carrying the skip marker, and files the project's `exclude` globs name)
104
+ * Find every TypeScript infrastructure file under `path`, through the one
105
+ * discovery walk (`./walk.ts`, #2527): test and spec files, chant-generated
106
+ * files, skip-marked files and whatever the walk's rules and the project's
107
+ * globs skip are left out.
97
108
  */
98
109
  export async function findInfraFiles(path: string, options?: FindInfraFilesOptions): Promise<string[]> {
99
- const files: string[] = [];
100
- const skip = compileDiscoveryFilter(
101
- options?.globs === null ? undefined : (options?.globs ?? (await resolveDiscoveryGlobs(path))),
102
- );
103
- let sourceRoot: string | null = null;
104
- // Child projects skipped because the source root was already set: the
105
- // next release reads them when `path` is outside a project (#2527).
106
- const skippedChildren: string[] = [];
107
-
108
- async function scanDirectory(dir: string): Promise<void> {
109
- let entries;
110
-
111
- try {
112
- entries = await readdir(dir, { withFileTypes: true });
113
- } catch (error) {
114
- // Skip directories we can't read
115
- return;
116
- }
117
-
118
- for (const entry of entries) {
119
- const fullPath = join(dir, entry.name);
120
-
121
- // Skip node_modules
122
- if (entry.isDirectory() && entry.name === "node_modules") {
123
- continue;
124
- }
125
-
126
- if (entry.isDirectory()) {
127
- // Child project boundary — a directory with its own chant.config.ts
128
- // is a separate scope, but only if we've already found the project's
129
- // own source root. The first config directory is the source root, not
130
- // a child project.
131
- const configPath = join(fullPath, "chant.config.ts");
132
- if (existsSync(configPath)) {
133
- if (sourceRoot === null) {
134
- sourceRoot = fullPath;
135
- } else {
136
- skippedChildren.push(fullPath);
137
- continue;
138
- }
139
- }
140
- await scanDirectory(fullPath);
141
- } else if (entry.isFile()) {
142
- // Include only .ts files, exclude test files, files the project's
143
- // globs exclude, and chant-generated or skip-marked files
144
- if (
145
- entry.name.endsWith(".ts") &&
146
- !entry.name.endsWith(".test.ts") &&
147
- !entry.name.endsWith(".spec.ts") &&
148
- !skip?.(fullPath) &&
149
- !(await hasDiscoveryMarker(fullPath))
150
- ) {
151
- files.push(fullPath);
152
- }
153
- }
154
- }
155
- }
156
-
157
- await scanDirectory(path);
158
- // The warning release for #2527: say which files the converged walker will
159
- // read differently. The list returned is today's, unchanged.
160
- await warnDiscoveryChanges({
110
+ const globs = options?.globs === null ? undefined : (options?.globs ?? (await resolveDiscoveryGlobs(path)));
111
+ return walkDiscovery({
161
112
  walker: "source",
162
113
  root: path,
163
- files,
164
- sourceRoot,
165
- skippedChildren,
166
- fileOk: async (name, full) =>
167
- name.endsWith(".ts") &&
168
- !name.endsWith(".test.ts") &&
169
- !name.endsWith(".spec.ts") &&
170
- !skip?.(full) &&
171
- !(await hasDiscoveryMarker(full)),
114
+ globs,
115
+ excludeDirs: await workspaceMemberDirs(path),
116
+ accept: (name, full) => isSourceFileName(name) && !hasDiscoveryMarkerSync(full),
172
117
  });
173
- return files;
174
118
  }
@@ -27,7 +27,7 @@ import {
27
27
  type FoldedCompositeStepCall,
28
28
  } from "../fold/fold";
29
29
  import { isChantOwnedSpecifier, isFoldableHelperName } from "../fold/foldable-helpers";
30
- import { lexiconModulePath } from "../lexicon-module";
30
+ import { lexiconModulePath, lexiconModuleRoot } from "../lexicon-module";
31
31
  import {
32
32
  briefNodeText,
33
33
  callExpressionMessage,
@@ -258,11 +258,22 @@ export interface FoldSession {
258
258
  * under `--sandbox` it is on {@link isTrustedExecutableBinding}'s allowlist,
259
259
  * because `loadPlugins` has already imported and run it in this process.
260
260
  *
261
- * Only the declared module itself is in the set. A package has a root that
262
- * bounds its subpaths, and a module path has none, so other files beside it
263
- * stay project files.
261
+ * Only the declared module itself is in the set. The other files of a
262
+ * multi-file path lexicon are covered by {@link lexiconRoots}.
264
263
  */
265
264
  readonly lexiconModules: ReadonlySet<string>;
265
+ /**
266
+ * chant#2590 — the directory trusted for each path-declared lexicon that has
267
+ * one (`../lexicon-module.ts`'s `pathLexiconRoot`: the declared `root`, or
268
+ * the module's own directory, inside the project and not containing its
269
+ * source directory). A file under one of these gets what a subpath of an
270
+ * active lexicon package gets: a place on the `--sandbox` trust list, and
271
+ * no fold as a project file. Its data exports are not read as values,
272
+ * which is also how a package subpath is treated. A directory that holds
273
+ * any of the build's own source files is dropped, so the build's source is
274
+ * never trusted this way.
275
+ */
276
+ readonly lexiconRoots: readonly string[];
266
277
  /**
267
278
  * chant #1093 — this build asked for the #1045 sandbox
268
279
  * (`DiscoveryOptions.sandbox`, `chant build --sandbox`), so fold must not
@@ -342,15 +353,23 @@ export function createFoldSession(
342
353
  lexiconPackages: readonly string[] = [],
343
354
  /** chant#2455 — `ι = executing`. Mutually exclusive with `sandbox`. */
344
355
  executing = false,
356
+ /**
357
+ * chant#2590 — the build's own source files. A path lexicon's trusted
358
+ * directory that holds any of them is dropped (see {@link FoldSession.lexiconRoots}).
359
+ */
360
+ sourceFiles: readonly string[] = [],
345
361
  ): FoldSession {
346
362
  // chant#2577 — a lexicon declared by path is that module and no package, so
347
363
  // its name contributes the module path and not `@intentius/chant-lexicon-<name>`.
348
364
  const packages = new Set(lexiconPackages);
349
365
  const modules = new Set<string>();
366
+ const roots: string[] = [];
350
367
  for (const name of lexicons) {
351
368
  const modulePath = lexiconModulePath(name);
352
369
  if (modulePath === undefined) packages.add(lexiconPackageName(name));
353
370
  else modules.add(resolveModulePath(modulePath, modulePath));
371
+ const root = lexiconModuleRoot(name);
372
+ if (root !== undefined && !sourceFiles.some((file) => isUnderDirectory(resolvePath(file), root))) roots.push(root);
354
373
  }
355
374
  return {
356
375
  intrinsics,
@@ -361,6 +380,7 @@ export function createFoldSession(
361
380
  buildParams,
362
381
  lexiconPackages: packages,
363
382
  lexiconModules: modules,
383
+ lexiconRoots: roots,
364
384
  sandbox,
365
385
  executing,
366
386
  factoryModules: new Map(),
@@ -1153,6 +1173,16 @@ function activeLexiconModule(
1153
1173
  return lexiconModules.has(modulePath) ? modulePath : undefined;
1154
1174
  }
1155
1175
 
1176
+ /** chant#2590 — true when absolute `file` lies under absolute directory `dir`. */
1177
+ function isUnderDirectory(file: string, dir: string): boolean {
1178
+ return file.startsWith(dir.endsWith(sep) ? dir : dir + sep);
1179
+ }
1180
+
1181
+ /** chant#2590 — true when `path` lies under one of the build's trusted path-lexicon directories. */
1182
+ function inPathLexiconRoot(path: string, roots: readonly string[]): boolean {
1183
+ return roots.some((root) => isUnderDirectory(path, root));
1184
+ }
1185
+
1156
1186
  /**
1157
1187
  * chant #1995 — the package-ROOT portion of a bare subpath specifier
1158
1188
  * (`@intentius/chant-lexicon-azure/generated/index` ->
@@ -1333,6 +1363,8 @@ interface ResolveCtx {
1333
1363
  lexiconPackages: ReadonlySet<string>;
1334
1364
  /** chant#2577 — see {@link FoldSession.lexiconModules}. */
1335
1365
  lexiconModules: ReadonlySet<string>;
1366
+ /** chant#2590 — see {@link FoldSession.lexiconRoots}. */
1367
+ lexiconRoots: readonly string[];
1336
1368
  /** chant #1093 — see {@link FoldSession.sandbox}. */
1337
1369
  sandbox: boolean;
1338
1370
  /** chant#2455 — see {@link FoldSession.executing}. */
@@ -2484,6 +2516,7 @@ async function interpretCompositeFactory(
2484
2516
  resolvePathCache: ctx.resolvePathCache,
2485
2517
  lexiconPackages: ctx.lexiconPackages,
2486
2518
  lexiconModules: ctx.lexiconModules,
2519
+ lexiconRoots: ctx.lexiconRoots,
2487
2520
  sandbox: ctx.sandbox,
2488
2521
  executing: ctx.executing,
2489
2522
  session: ctx.session,
@@ -3110,6 +3143,9 @@ function isTrustedExecutableBinding(binding: ImportBinding, ctx: ResolveCtx): bo
3110
3143
  // chant#2577 — arm 1 for a lexicon declared by path: the module
3111
3144
  // `loadPlugins` already imported, reached by the path the project imports it by.
3112
3145
  if (ctx.lexiconModules.has(targetPath)) return true;
3146
+ // chant#2590 — the subpath case of the same arm: another file of a
3147
+ // multi-file path lexicon, under its trusted directory.
3148
+ if (inPathLexiconRoot(targetPath, ctx.lexiconRoots)) return true;
3113
3149
  const root = chantCoreRoot();
3114
3150
  return targetPath === root || targetPath.startsWith(root + sep);
3115
3151
  }
@@ -3677,6 +3713,12 @@ async function buildExternals(
3677
3713
  if (lexiconExport) externals.set(localName, lexiconExport.value);
3678
3714
  continue;
3679
3715
  }
3716
+ // chant#2590 — another file of a multi-file path lexicon is a lexicon
3717
+ // subpath, not a project file: it is not folded, and like a package
3718
+ // subpath (see the bare-specifier branch above) its data exports are not
3719
+ // read as values. A constructor or composite from it resolves through the
3720
+ // import path, where `isTrustedExecutableBinding` admits it.
3721
+ if (inPathLexiconRoot(targetPath, session.lexiconRoots)) continue;
3680
3722
  const result = await foldFileMemoized(targetPath, session);
3681
3723
  if (!result.ok) {
3682
3724
  failures.set(localName, locatedMessage(binding.specifierNode, result.reason));
@@ -3704,7 +3746,7 @@ async function buildExternals(
3704
3746
  }
3705
3747
  // chant#2577 — a namespace import of a lexicon is left alone, as the
3706
3748
  // bare-specifier check above leaves a package's alone.
3707
- if (session.lexiconModules.has(targetPath)) continue;
3749
+ if (session.lexiconModules.has(targetPath) || inPathLexiconRoot(targetPath, session.lexiconRoots)) continue;
3708
3750
  const result = await foldFileMemoized(targetPath, session);
3709
3751
  if (!result.ok) {
3710
3752
  failures.set(localName, locatedMessage(binding.specifierNode, result.reason));
@@ -3812,6 +3854,7 @@ async function tryFoldFileCore(file: string, session: FoldSession): Promise<Fold
3812
3854
  resolvePathCache: session.resolvePathCache,
3813
3855
  lexiconPackages: session.lexiconPackages,
3814
3856
  lexiconModules: session.lexiconModules,
3857
+ lexiconRoots: session.lexiconRoots,
3815
3858
  sandbox: session.sandbox,
3816
3859
  executing: session.executing,
3817
3860
  session,
@@ -4341,6 +4384,7 @@ export async function foldProject(
4341
4384
  options.sandbox ?? false,
4342
4385
  options.lexiconPackages ?? [],
4343
4386
  options.executing ?? false,
4387
+ files,
4344
4388
  );
4345
4389
  const attempts = new Map<string, FoldFileResult>();
4346
4390
  for (const file of files) attempts.set(file, await tryFoldFile(file, intrinsics, session));
@@ -291,6 +291,7 @@ export async function discover(path: string, options?: DiscoveryOptions): Promis
291
291
  options.sandbox === true,
292
292
  [],
293
293
  options.executing === true,
294
+ files,
294
295
  )
295
296
  : undefined;
296
297
  if (options?.fold) {
@@ -70,6 +70,49 @@ function lit(value: unknown): string {
70
70
  return JSON.stringify(value);
71
71
  }
72
72
 
73
+ /**
74
+ * chant#2461 — the `send` every driver uses, as generated source lines.
75
+ *
76
+ * `process.send` is asynchronous: it queues the message on the IPC channel and
77
+ * returns. Node's contract is that the optional callback runs once the message
78
+ * has been written, or with an error if it could not be. Without the callback a
79
+ * failed send is not reported to the caller at all, so the driver could return
80
+ * from `main()` believing it had answered.
81
+ *
82
+ * So `send` returns a promise that settles only when the write has completed,
83
+ * and every call site awaits it before `main()` returns. A send that fails, or
84
+ * throws synchronously (a payload that cannot be serialized), writes the reason
85
+ * to stderr with a synchronous `writeSync` and exits 1. That way a result that
86
+ * never left the child cannot end as exit 0 with empty stderr, which is the
87
+ * signature that looks like success went missing.
88
+ *
89
+ * `before` is spliced in at the top of the function body (the run driver marks
90
+ * itself `reported` there).
91
+ */
92
+ export function sendFunctionSource(before: readonly string[] = []): string[] {
93
+ return [
94
+ `function send(payload) {`,
95
+ ...before.map((line) => ` ${line}`),
96
+ ` if (typeof process.send !== "function") {`,
97
+ ` console.log(JSON.stringify(payload));`,
98
+ ` return Promise.resolve();`,
99
+ ` }`,
100
+ ` return new Promise((resolve) => {`,
101
+ ` const lost = (err) => {`,
102
+ ` writeSync(2, "chant: the sandboxed child could not hand its result to the parent: " +`,
103
+ ` (err && err.message ? err.message : String(err)) + " (chant#2461)\\n");`,
104
+ ` process.exit(1);`,
105
+ ` };`,
106
+ ` try {`,
107
+ ` process.send(payload, (err) => (err ? lost(err) : resolve()));`,
108
+ ` } catch (err) {`,
109
+ ` lost(err);`,
110
+ ` }`,
111
+ ` });`,
112
+ `}`,
113
+ ];
114
+ }
115
+
73
116
  /**
74
117
  * Generate the driver module's full TypeScript source. Written to a tmp file
75
118
  * and bundled (see `./bundle.ts`) before being handed to a sandboxed child —
@@ -117,11 +160,7 @@ export function generateDriverSource(options: GenerateDriverOptions): string {
117
160
  ` "Nothing is thrown, so nothing else can name it (chant#2461).\\n");`,
118
161
  `});`,
119
162
  ``,
120
- `function send(payload) {`,
121
- ` reported = true;`,
122
- ` if (typeof process.send === "function") process.send(payload);`,
123
- ` else console.log(JSON.stringify(payload));`,
124
- `}`,
163
+ ...sendFunctionSource([`reported = true;`]),
125
164
  ``,
126
165
  // collectEntities (bundled, real DiscoveryError instances) already names
127
166
  // the exact offending file on a same-directory duplicate — reuse that
@@ -156,7 +195,7 @@ export function generateDriverSource(options: GenerateDriverOptions): string {
156
195
  ` entities = collectEntities(modules, BUILD_ROOT);`,
157
196
  ` } catch (err) {`,
158
197
  ` errors.push(classifyChildError(errFile(err), err, "resolution").toJSON());`,
159
- ` send({ entitySet: { entities: [] }, errors, provenanceByName: {} });`,
198
+ ` await send({ entitySet: { entities: [] }, errors, provenanceByName: {} });`,
160
199
  ` return;`,
161
200
  ` }`,
162
201
  ``,
@@ -178,18 +217,20 @@ export function generateDriverSource(options: GenerateDriverOptions): string {
178
217
  ` errors.push(classifyChildError("", err, "resolution").toJSON());`,
179
218
  ` }`,
180
219
  ``,
220
+ ` let entitySet;`,
181
221
  ` try {`,
182
- ` const entitySet = encodeEntitySet(entities);`,
183
- ` send({ entitySet, errors, provenanceByName });`,
222
+ ` entitySet = encodeEntitySet(entities);`,
184
223
  ` } catch (err) {`,
185
224
  ` errors.push(classifyChildError("", err, "resolution").toJSON());`,
186
- ` send({ entitySet: { entities: [] }, errors, provenanceByName });`,
225
+ ` await send({ entitySet: { entities: [] }, errors, provenanceByName });`,
226
+ ` return;`,
187
227
  ` }`,
228
+ ` await send({ entitySet, errors, provenanceByName });`,
188
229
  `}`,
189
230
  ``,
190
- `main().catch((err) => {`,
191
- ` send({ entitySet: { entities: [] }, errors: [classifyChildError("", err).toJSON()], provenanceByName: {}, fatal: true });`,
192
- `});`,
231
+ `main().catch((err) =>`,
232
+ ` send({ entitySet: { entities: [] }, errors: [classifyChildError("", err).toJSON()], provenanceByName: {}, fatal: true }),`,
233
+ `);`,
193
234
  );
194
235
 
195
236
  return lines.join("\n");
@@ -218,18 +259,16 @@ export function generateConfigDriverSource(configPath: string): string {
218
259
  return [
219
260
  `import { classifyChildError } from ${lit(CHILD_ERRORS_MODULE)};`,
220
261
  `import { scanConfigWireSafety } from ${lit(CONFIG_WIRE_MODULE)};`,
262
+ `import { writeSync } from "node:fs";`,
221
263
  ``,
222
- `function send(payload) {`,
223
- ` if (typeof process.send === "function") process.send(payload);`,
224
- ` else console.log(JSON.stringify(payload));`,
225
- `}`,
264
+ ...sendFunctionSource(),
226
265
  ``,
227
266
  `async function main() {`,
228
267
  ` let namespace;`,
229
268
  ` try {`,
230
269
  ` namespace = await import(${lit(configPath)});`,
231
270
  ` } catch (err) {`,
232
- ` send({ kind: "chant-config", ok: false, error: classifyChildError(${lit(configPath)}, err).toJSON() });`,
271
+ ` await send({ kind: "chant-config", ok: false, error: classifyChildError(${lit(configPath)}, err).toJSON() });`,
233
272
  ` return;`,
234
273
  ` }`,
235
274
  ``,
@@ -240,24 +279,26 @@ export function generateConfigDriverSource(configPath: string): string {
240
279
  ``,
241
280
  ` const offenders = scanConfigWireSafety(selected);`,
242
281
  ` if (offenders.length > 0) {`,
243
- ` send({ kind: "chant-config", ok: false, offenders });`,
282
+ ` await send({ kind: "chant-config", ok: false, offenders });`,
244
283
  ` return;`,
245
284
  ` }`,
246
285
  ``,
286
+ ` let config;`,
247
287
  ` try {`,
248
288
  // Round-trip here, not just at the IPC boundary: this is what proves the
249
289
  // payload really is JSON before it leaves the child, and turns anything
250
290
  // the scan somehow missed into a named error instead of a quiet drop.
251
- ` const config = JSON.parse(JSON.stringify(selected ?? {}));`,
252
- ` send({ kind: "chant-config", ok: true, config });`,
291
+ ` config = JSON.parse(JSON.stringify(selected ?? {}));`,
253
292
  ` } catch (err) {`,
254
- ` send({ kind: "chant-config", ok: false, error: classifyChildError(${lit(configPath)}, err, "resolution").toJSON() });`,
293
+ ` await send({ kind: "chant-config", ok: false, error: classifyChildError(${lit(configPath)}, err, "resolution").toJSON() });`,
294
+ ` return;`,
255
295
  ` }`,
296
+ ` await send({ kind: "chant-config", ok: true, config });`,
256
297
  `}`,
257
298
  ``,
258
- `main().catch((err) => {`,
259
- ` send({ kind: "chant-config", ok: false, error: classifyChildError(${lit(configPath)}, err).toJSON() });`,
260
- `});`,
299
+ `main().catch((err) =>`,
300
+ ` send({ kind: "chant-config", ok: false, error: classifyChildError(${lit(configPath)}, err).toJSON() }),`,
301
+ `);`,
261
302
  ].join("\n");
262
303
  }
263
304
 
@@ -294,18 +335,15 @@ export function generatePolicyDriverSource(policyPaths: readonly string[]): stri
294
335
  `import { classifyChildError } from ${lit(CHILD_ERRORS_MODULE)};`,
295
336
  `import { decodePolicyBuildResult, scanPolicyDiagnostics, PolicyWireError } from ${lit(POLICY_WIRE_MODULE)};`,
296
337
  `import { runPostSynthChecks, isPostSynthCheck } from ${lit(POST_SYNTH_MODULE)};`,
338
+ `import { writeSync } from "node:fs";`,
297
339
  ``,
298
- `function send(payload) {`,
299
- ` if (typeof process.send === "function") process.send(payload);`,
300
- ` else console.log(JSON.stringify(payload));`,
301
- `}`,
340
+ ...sendFunctionSource(),
302
341
  ``,
303
342
  `function fail(file, err, type) {`,
304
343
  ` if (err instanceof PolicyWireError) {`,
305
- ` send({ kind: "chant-policy", ok: false, offenders: err.offenders });`,
306
- ` return;`,
344
+ ` return send({ kind: "chant-policy", ok: false, offenders: err.offenders });`,
307
345
  ` }`,
308
- ` send({ kind: "chant-policy", ok: false, error: classifyChildError(file, err, type).toJSON() });`,
346
+ ` return send({ kind: "chant-policy", ok: false, error: classifyChildError(file, err, type).toJSON() });`,
309
347
  `}`,
310
348
  ``,
311
349
  // The wrapper described in the doc above: same id/description so any
@@ -329,7 +367,7 @@ export function generatePolicyDriverSource(policyPaths: readonly string[]): stri
329
367
  ` try {`,
330
368
  ` buildResult = decodePolicyBuildResult(request.buildResult);`,
331
369
  ` } catch (err) {`,
332
- ` fail("", err, "resolution");`,
370
+ ` await fail("", err, "resolution");`,
333
371
  ` return;`,
334
372
  ` }`,
335
373
  ``,
@@ -347,7 +385,7 @@ export function generatePolicyDriverSource(policyPaths: readonly string[]): stri
347
385
  ` if (isPostSynthCheck(value)) checks.push(guard(value, ${lit(policyPath)}));`,
348
386
  ` }`,
349
387
  ` } catch (err) {`,
350
- ` fail(${lit(policyPath)}, err, "import");`,
388
+ ` await fail(${lit(policyPath)}, err, "import");`,
351
389
  ` return;`,
352
390
  ` }`,
353
391
  );
@@ -359,11 +397,11 @@ export function generatePolicyDriverSource(policyPaths: readonly string[]): stri
359
397
  ` try {`,
360
398
  ` diagnostics = runPostSynthChecks(checks, buildResult, request.env ?? undefined);`,
361
399
  ` } catch (err) {`,
362
- ` fail("", err, "resolution");`,
400
+ ` await fail("", err, "resolution");`,
363
401
  ` return;`,
364
402
  ` }`,
365
403
  ``,
366
- ` send({ kind: "chant-policy", ok: true, diagnostics });`,
404
+ ` await send({ kind: "chant-policy", ok: true, diagnostics });`,
367
405
  `}`,
368
406
  ``,
369
407
  // Registered synchronously at module top level — see the doc above on why