@intentius/chant 0.124.30 → 0.124.32

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 (346) hide show
  1. package/bin/chant +7 -2
  2. package/dist/cli/commands/check-lexicon-plugin.d.ts +7 -4
  3. package/dist/cli/commands/check-lexicon-plugin.d.ts.map +1 -1
  4. package/dist/cli/commands/check-lexicon-plugin.js +10 -7
  5. package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
  6. package/dist/cli/commands/check-lexicon.js +18 -12
  7. package/dist/cli/commands/import.d.ts +10 -0
  8. package/dist/cli/commands/import.d.ts.map +1 -1
  9. package/dist/cli/commands/import.js +37 -0
  10. package/dist/cli/commands/init-lexicon/templates/project.d.ts.map +1 -1
  11. package/dist/cli/commands/init-lexicon/templates/project.js +4 -3
  12. package/dist/cli/commands/onboard.d.ts.map +1 -1
  13. package/dist/cli/commands/onboard.js +8 -4
  14. package/dist/cli/commands/update.d.ts.map +1 -1
  15. package/dist/cli/commands/update.js +2 -1
  16. package/dist/cli/dependencies.d.ts +18 -0
  17. package/dist/cli/dependencies.d.ts.map +1 -0
  18. package/dist/cli/dependencies.js +120 -0
  19. package/dist/cli/handlers/build.d.ts.map +1 -1
  20. package/dist/cli/handlers/build.js +23 -4
  21. package/dist/cli/handlers/fan-out.d.ts.map +1 -1
  22. package/dist/cli/handlers/fan-out.js +12 -4
  23. package/dist/cli/handlers/graph.d.ts.map +1 -1
  24. package/dist/cli/handlers/graph.js +16 -6
  25. package/dist/cli/handlers/lint.d.ts.map +1 -1
  26. package/dist/cli/handlers/lint.js +6 -0
  27. package/dist/cli/handlers/operator.d.ts +2 -2
  28. package/dist/cli/handlers/operator.js +3 -3
  29. package/dist/cli/handlers/pr.d.ts +14 -0
  30. package/dist/cli/handlers/pr.d.ts.map +1 -1
  31. package/dist/cli/handlers/pr.js +488 -32
  32. package/dist/cli/handlers/promote.d.ts.map +1 -1
  33. package/dist/cli/handlers/promote.js +3 -1
  34. package/dist/cli/handlers/run.d.ts +13 -1
  35. package/dist/cli/handlers/run.d.ts.map +1 -1
  36. package/dist/cli/handlers/run.js +38 -15
  37. package/dist/cli/main.d.ts.map +1 -1
  38. package/dist/cli/main.js +74 -12
  39. package/dist/cli/parse-args.d.ts.map +1 -1
  40. package/dist/cli/parse-args.js +65 -0
  41. package/dist/cli/registry.d.ts +29 -2
  42. package/dist/cli/registry.d.ts.map +1 -1
  43. package/dist/cli/registry.js +6 -2
  44. package/dist/codegen/generate-post-synth-barrel.js +2 -2
  45. package/dist/codegen/lexicon-regen.d.ts +4 -0
  46. package/dist/codegen/lexicon-regen.d.ts.map +1 -1
  47. package/dist/codegen/lexicon-regen.js +1 -1
  48. package/dist/codegen/pinned-upgrade.js +2 -2
  49. package/dist/components/capability.d.ts +44 -3
  50. package/dist/components/capability.d.ts.map +1 -1
  51. package/dist/components/capability.js +21 -0
  52. package/dist/components/changed-files.d.ts +7 -1
  53. package/dist/components/changed-files.d.ts.map +1 -1
  54. package/dist/components/changed-files.js +9 -1
  55. package/dist/components/driver.d.ts +38 -0
  56. package/dist/components/driver.d.ts.map +1 -1
  57. package/dist/components/driver.js +47 -6
  58. package/dist/components/fan-out-record.d.ts +6 -1
  59. package/dist/components/fan-out-record.d.ts.map +1 -1
  60. package/dist/components/fan-out-record.js +24 -0
  61. package/dist/components/fan-out-run.d.ts +20 -0
  62. package/dist/components/fan-out-run.d.ts.map +1 -1
  63. package/dist/components/fan-out-run.js +21 -1
  64. package/dist/components/pr-pipeline.d.ts +65 -2
  65. package/dist/components/pr-pipeline.d.ts.map +1 -1
  66. package/dist/components/pr-pipeline.js +107 -15
  67. package/dist/components/pr-run.d.ts +127 -29
  68. package/dist/components/pr-run.d.ts.map +1 -1
  69. package/dist/components/pr-run.js +290 -70
  70. package/dist/components/wave-plan.d.ts +5 -2
  71. package/dist/components/wave-plan.d.ts.map +1 -1
  72. package/dist/components/wave-plan.js +12 -1
  73. package/dist/discovery/fold-import.d.ts.map +1 -1
  74. package/dist/discovery/fold-import.js +16 -6
  75. package/dist/discovery/sandbox/bundle.d.ts.map +1 -1
  76. package/dist/discovery/sandbox/bundle.js +6 -0
  77. package/dist/discovery/specifier-resolve.d.ts.map +1 -1
  78. package/dist/discovery/specifier-resolve.js +8 -2
  79. package/dist/fold/fold.d.ts.map +1 -1
  80. package/dist/fold/fold.js +68 -1
  81. package/dist/fold/subset.d.ts +37 -0
  82. package/dist/fold/subset.d.ts.map +1 -1
  83. package/dist/fold/subset.js +88 -0
  84. package/dist/lexicon-module.d.ts +10 -0
  85. package/dist/lexicon-module.d.ts.map +1 -1
  86. package/dist/lexicon-module.js +53 -8
  87. package/dist/lexicon-plugin-helpers.d.ts.map +1 -1
  88. package/dist/lexicon-plugin-helpers.js +6 -4
  89. package/dist/lexicon.d.ts +2 -0
  90. package/dist/lexicon.d.ts.map +1 -1
  91. package/dist/lifecycle/affected.d.ts.map +1 -1
  92. package/dist/lifecycle/affected.js +7 -1
  93. package/dist/lifecycle/release-ledger.d.ts +21 -0
  94. package/dist/lifecycle/release-ledger.d.ts.map +1 -1
  95. package/dist/lifecycle/release-ledger.js +24 -0
  96. package/dist/lifecycle/work-dir.d.ts +45 -0
  97. package/dist/lifecycle/work-dir.d.ts.map +1 -0
  98. package/dist/lifecycle/work-dir.js +78 -0
  99. package/dist/lint/discover.d.ts +17 -9
  100. package/dist/lint/discover.d.ts.map +1 -1
  101. package/dist/lint/discover.js +62 -54
  102. package/dist/module-source.d.ts +57 -0
  103. package/dist/module-source.d.ts.map +1 -0
  104. package/dist/module-source.js +104 -0
  105. package/dist/op/activities/factory.js +1 -1
  106. package/dist/op/discover.d.ts.map +1 -1
  107. package/dist/op/discover.js +13 -3
  108. package/dist/op/gate.d.ts.map +1 -1
  109. package/dist/op/gate.js +3 -0
  110. package/dist/op/local-executor.d.ts +12 -0
  111. package/dist/op/local-executor.d.ts.map +1 -1
  112. package/dist/op/local-executor.js +22 -3
  113. package/dist/op/op-waves-run.d.ts.map +1 -1
  114. package/dist/op/op-waves-run.js +20 -5
  115. package/dist/op/operator.d.ts +2 -2
  116. package/dist/op/operator.js +2 -2
  117. package/dist/op/redact.d.ts +34 -0
  118. package/dist/op/redact.d.ts.map +1 -0
  119. package/dist/op/redact.js +94 -0
  120. package/dist/op/step-console.d.ts +2 -0
  121. package/dist/op/step-console.d.ts.map +1 -1
  122. package/dist/op/step-console.js +5 -2
  123. package/dist/op/steward.d.ts +6 -4
  124. package/dist/op/steward.d.ts.map +1 -1
  125. package/dist/op/steward.js +5 -3
  126. package/dist/op/work-lease-run.d.ts +20 -7
  127. package/dist/op/work-lease-run.d.ts.map +1 -1
  128. package/dist/op/work-lease-run.js +56 -12
  129. package/dist/pr-forge.d.ts +27 -0
  130. package/dist/pr-forge.d.ts.map +1 -1
  131. package/dist/pr-forge.js +51 -6
  132. package/dist/pr-loop.d.ts +141 -4
  133. package/dist/pr-loop.d.ts.map +1 -1
  134. package/dist/pr-loop.js +122 -6
  135. package/dist/pr-report-url.d.ts +10 -2
  136. package/dist/pr-report-url.d.ts.map +1 -1
  137. package/dist/pr-report-url.js +52 -6
  138. package/dist/ts-loader.d.ts +38 -4
  139. package/dist/ts-loader.d.ts.map +1 -1
  140. package/dist/ts-loader.js +190 -16
  141. package/dist/wave-runtime.mjs +208 -208
  142. package/dist/workspace/chant-migrations/fountain-retired-kinds.d.ts +34 -0
  143. package/dist/workspace/chant-migrations/fountain-retired-kinds.d.ts.map +1 -0
  144. package/dist/workspace/chant-migrations/fountain-retired-kinds.js +176 -0
  145. package/dist/workspace/chant-migrations.d.ts.map +1 -1
  146. package/dist/workspace/chant-migrations.js +2 -0
  147. package/dist/workspace/checks/boxes.d.ts +6 -6
  148. package/dist/workspace/checks/boxes.js +9 -9
  149. package/dist/workspace/ci-green-forge.d.ts +6 -4
  150. package/dist/workspace/ci-green-forge.d.ts.map +1 -1
  151. package/dist/workspace/ci-green.d.ts +28 -12
  152. package/dist/workspace/ci-green.d.ts.map +1 -1
  153. package/dist/workspace/ci-green.js +49 -21
  154. package/dist/workspace/ci-list.schema.json +12 -6
  155. package/dist/workspace/ci-report-url.d.ts +18 -0
  156. package/dist/workspace/ci-report-url.d.ts.map +1 -0
  157. package/dist/workspace/ci-report-url.js +33 -0
  158. package/dist/workspace/ci-run-index.d.ts +108 -0
  159. package/dist/workspace/ci-run-index.d.ts.map +1 -0
  160. package/dist/workspace/ci-run-index.js +164 -0
  161. package/dist/workspace/ci-run-index.schema.json +52 -0
  162. package/dist/workspace/ci-run.d.ts +159 -9
  163. package/dist/workspace/ci-run.d.ts.map +1 -1
  164. package/dist/workspace/ci-run.js +419 -50
  165. package/dist/workspace/ci-runner-key.d.ts +133 -0
  166. package/dist/workspace/ci-runner-key.d.ts.map +1 -0
  167. package/dist/workspace/ci-runner-key.js +237 -0
  168. package/dist/workspace/ci-secrets.d.ts +65 -0
  169. package/dist/workspace/ci-secrets.d.ts.map +1 -0
  170. package/dist/workspace/ci-secrets.js +211 -0
  171. package/dist/workspace/ci-serve.d.ts +67 -4
  172. package/dist/workspace/ci-serve.d.ts.map +1 -1
  173. package/dist/workspace/ci-serve.js +240 -35
  174. package/dist/workspace/declaration.d.ts +8 -0
  175. package/dist/workspace/declaration.d.ts.map +1 -1
  176. package/dist/workspace/declaration.js +11 -2
  177. package/dist/workspace/declaration.schema.json +7 -2
  178. package/dist/workspace/export.d.ts +1 -1
  179. package/dist/workspace/export.d.ts.map +1 -1
  180. package/dist/workspace/export.js +7 -3
  181. package/dist/workspace/ls.d.ts +6 -1
  182. package/dist/workspace/ls.d.ts.map +1 -1
  183. package/dist/workspace/ls.js +1 -0
  184. package/dist/workspace/ls.schema.json +7 -1
  185. package/dist/workspace/pin-integrity.d.ts.map +1 -1
  186. package/dist/workspace/pin-integrity.js +3 -2
  187. package/dist/workspace/pr-report.schema.json +74 -7
  188. package/dist/workspace/reason-codes.d.ts +7 -3
  189. package/dist/workspace/reason-codes.d.ts.map +1 -1
  190. package/dist/workspace/reason-codes.js +9 -4
  191. package/dist/workspace/run-event.schema.json +3 -1
  192. package/dist/workspace/status.schema.json +3 -1
  193. package/dist/workspace/trust/trust-write.d.ts +109 -0
  194. package/dist/workspace/trust/trust-write.d.ts.map +1 -0
  195. package/dist/workspace/trust/trust-write.js +320 -0
  196. package/dist/workspace/trust-write.schema.json +265 -0
  197. package/dist/workspace/write-scope.d.ts +9 -0
  198. package/dist/workspace/write-scope.d.ts.map +1 -1
  199. package/dist/workspace/write-scope.js +11 -1
  200. package/package.json +1 -1
  201. package/src/__fixtures__/pr-loop/pr-apply-wave-waiting.note.golden.md +48 -0
  202. package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +3 -3
  203. package/src/cli/commands/audit.test.ts +2 -2
  204. package/src/cli/commands/check-lexicon-plugin.test.ts +9 -0
  205. package/src/cli/commands/check-lexicon-plugin.ts +11 -8
  206. package/src/cli/commands/check-lexicon.test.ts +1 -1
  207. package/src/cli/commands/check-lexicon.ts +16 -11
  208. package/src/cli/commands/import.ts +40 -0
  209. package/src/cli/commands/init-lexicon/templates/project.ts +4 -3
  210. package/src/cli/commands/init-lexicon.test.ts +8 -5
  211. package/src/cli/commands/onboard.test.ts +45 -0
  212. package/src/cli/commands/onboard.ts +8 -4
  213. package/src/cli/commands/update.test.ts +6 -0
  214. package/src/cli/commands/update.ts +4 -1
  215. package/src/cli/compiled-cli.e2e.test.ts +76 -11
  216. package/src/cli/dependencies.e2e.test.ts +101 -0
  217. package/src/cli/dependencies.test.ts +93 -0
  218. package/src/cli/dependencies.ts +122 -0
  219. package/src/cli/handlers/build.test.ts +69 -0
  220. package/src/cli/handlers/build.ts +20 -4
  221. package/src/cli/handlers/fan-out.test.ts +73 -0
  222. package/src/cli/handlers/fan-out.ts +11 -4
  223. package/src/cli/handlers/graph.test.ts +76 -0
  224. package/src/cli/handlers/graph.ts +19 -12
  225. package/src/cli/handlers/lint.test.ts +42 -0
  226. package/src/cli/handlers/lint.ts +6 -0
  227. package/src/cli/handlers/operator.ts +3 -3
  228. package/src/cli/handlers/pr-waves.test.ts +449 -0
  229. package/src/cli/handlers/pr.test.ts +134 -0
  230. package/src/cli/handlers/pr.ts +523 -31
  231. package/src/cli/handlers/promote.test.ts +26 -1
  232. package/src/cli/handlers/promote.ts +3 -2
  233. package/src/cli/handlers/run-components-exit.test.ts +99 -0
  234. package/src/cli/handlers/run-signer.test.ts +79 -0
  235. package/src/cli/handlers/run.ts +34 -16
  236. package/src/cli/main.test.ts +19 -0
  237. package/src/cli/main.ts +73 -12
  238. package/src/cli/parse-args.ts +48 -0
  239. package/src/cli/registry.ts +35 -4
  240. package/src/codegen/generate-post-synth-barrel.ts +2 -2
  241. package/src/codegen/lexicon-regen.ts +1 -1
  242. package/src/codegen/pinned-upgrade.ts +2 -2
  243. package/src/codegen/post-synth-barrel-guards.test.ts +6 -11
  244. package/src/components/capability.ts +51 -3
  245. package/src/components/changed-files.test.ts +16 -1
  246. package/src/components/changed-files.ts +9 -1
  247. package/src/components/driver.test.ts +36 -1
  248. package/src/components/driver.ts +76 -4
  249. package/src/components/fan-out-record.ts +29 -1
  250. package/src/components/fan-out-run.test.ts +35 -0
  251. package/src/components/fan-out-run.ts +40 -1
  252. package/src/components/pr-pipeline.test.ts +100 -0
  253. package/src/components/pr-pipeline.ts +132 -17
  254. package/src/components/pr-run.test.ts +323 -18
  255. package/src/components/pr-run.ts +354 -75
  256. package/src/components/wave-plan.ts +16 -4
  257. package/src/discovery/fold-host-method.test.ts +87 -0
  258. package/src/discovery/fold-import.ts +15 -5
  259. package/src/discovery/fold-package-composite.test.ts +27 -0
  260. package/src/discovery/fold-specifiers.test.ts +8 -0
  261. package/src/discovery/sandbox/bundle.ts +6 -0
  262. package/src/discovery/specifier-resolve.ts +8 -2
  263. package/src/fold/fold.test.ts +72 -0
  264. package/src/fold/fold.ts +71 -0
  265. package/src/fold/subset.test.ts +31 -0
  266. package/src/fold/subset.ts +99 -0
  267. package/src/lexicon-dist.e2e.test.ts +254 -0
  268. package/src/lexicon-module.test.ts +47 -0
  269. package/src/lexicon-module.ts +49 -7
  270. package/src/lexicon-plugin-helpers.ts +6 -4
  271. package/src/lexicon.ts +2 -0
  272. package/src/lifecycle/affected.test.ts +7 -0
  273. package/src/lifecycle/affected.ts +6 -1
  274. package/src/lifecycle/release-ledger.ts +34 -0
  275. package/src/lifecycle/work-dir.test.ts +77 -0
  276. package/src/lifecycle/work-dir.ts +82 -0
  277. package/src/lint/discover.test.ts +46 -2
  278. package/src/lint/discover.ts +55 -49
  279. package/src/module-source.test.ts +85 -0
  280. package/src/module-source.ts +112 -0
  281. package/src/op/activities/factory.ts +1 -1
  282. package/src/op/discover-root.test.ts +31 -2
  283. package/src/op/discover.ts +14 -4
  284. package/src/op/gate.test.ts +30 -0
  285. package/src/op/gate.ts +3 -0
  286. package/src/op/local-executor.ts +31 -3
  287. package/src/op/op-waves-run.ts +20 -5
  288. package/src/op/op-waves.test.ts +49 -0
  289. package/src/op/operator.ts +2 -2
  290. package/src/op/redact.ts +93 -0
  291. package/src/op/step-console.ts +7 -2
  292. package/src/op/steward.ts +6 -4
  293. package/src/op/work-lease-run.test.ts +88 -2
  294. package/src/op/work-lease-run.ts +52 -12
  295. package/src/pr-forge-bundle.test.ts +2 -2
  296. package/src/pr-forge.test.ts +71 -0
  297. package/src/pr-forge.ts +70 -6
  298. package/src/pr-loop-bundle.test.ts +2 -1
  299. package/src/pr-loop.test.ts +117 -1
  300. package/src/pr-loop.ts +252 -10
  301. package/src/pr-report-url.ts +58 -6
  302. package/src/terraform/__fixtures__/advise.test.ts +21 -2
  303. package/src/ts-loader.test.ts +89 -1
  304. package/src/ts-loader.ts +180 -13
  305. package/src/workspace/changes.test.ts +1 -1
  306. package/src/workspace/chant-migrations/fountain-retired-kinds.test.ts +33 -0
  307. package/src/workspace/chant-migrations/fountain-retired-kinds.ts +190 -0
  308. package/src/workspace/chant-migrations.e2e.test.ts +5 -0
  309. package/src/workspace/chant-migrations.ts +2 -0
  310. package/src/workspace/checks/boxes.ts +9 -9
  311. package/src/workspace/ci-green-forge.ts +6 -4
  312. package/src/workspace/ci-green-runs.test.ts +53 -11
  313. package/src/workspace/ci-green.test.ts +1 -1
  314. package/src/workspace/ci-green.ts +50 -22
  315. package/src/workspace/ci-list.schema.json +12 -6
  316. package/src/workspace/ci-report-url.test.ts +220 -0
  317. package/src/workspace/ci-report-url.ts +33 -0
  318. package/src/workspace/ci-run-index.schema.json +52 -0
  319. package/src/workspace/ci-run-index.test.ts +392 -0
  320. package/src/workspace/ci-run-index.ts +206 -0
  321. package/src/workspace/ci-run.test.ts +520 -42
  322. package/src/workspace/ci-run.ts +483 -51
  323. package/src/workspace/ci-runner-key.test.ts +204 -0
  324. package/src/workspace/ci-runner-key.ts +275 -0
  325. package/src/workspace/ci-secrets.test.ts +106 -0
  326. package/src/workspace/ci-secrets.ts +213 -0
  327. package/src/workspace/ci-serve.test.ts +282 -39
  328. package/src/workspace/ci-serve.ts +231 -34
  329. package/src/workspace/declaration.schema.json +7 -2
  330. package/src/workspace/declaration.test.ts +23 -0
  331. package/src/workspace/declaration.ts +19 -3
  332. package/src/workspace/export.ts +6 -3
  333. package/src/workspace/ls.schema.json +7 -1
  334. package/src/workspace/ls.ts +7 -2
  335. package/src/workspace/pin-integrity.test.ts +5 -0
  336. package/src/workspace/pin-integrity.ts +3 -2
  337. package/src/workspace/pr-report.schema.json +74 -7
  338. package/src/workspace/reason-codes.test.ts +2 -0
  339. package/src/workspace/reason-codes.ts +9 -4
  340. package/src/workspace/run-event.schema.json +3 -1
  341. package/src/workspace/status.schema.json +3 -1
  342. package/src/workspace/trust/trust-write.test.ts +179 -0
  343. package/src/workspace/trust/trust-write.ts +377 -0
  344. package/src/workspace/trust-write.schema.json +265 -0
  345. package/src/workspace/write-scope.test.ts +29 -1
  346. package/src/workspace/write-scope.ts +12 -1
@@ -8,26 +8,42 @@
8
8
  * everything before applying anything is what makes the two digests
9
9
  * comparable: each member is planned against the same state both times.
10
10
  *
11
- * ## Dependents read the outputs standing now
11
+ * ## What a dependent is planned against
12
12
  *
13
13
  * A member that reads another one's output through `stackOutput()` is
14
- * planned with the value that output has now, read through the capability's
15
- * `outputs` (`readComponentOutputs`). When the change moves that output, the
16
- * dependent's approved plan still carries the old value; the apply applies
17
- * it as approved and marks the member `inputsMoved`, and the next run plans
18
- * it against the new value. A change that must carry a moved output through
19
- * its dependents in one rollout is what gated waves are for (#3049): each
20
- * wave is planned after the one before it applied.
14
+ * planned with one of three values (#3999):
21
15
  *
22
- * A dependency the change did not select is read the same way (#4104), so
23
- * a change to one cluster plans it against the network it sits on. That is
24
- * why `components` is every component in the project and not the selection.
25
- * `--seed-outputs` wins over a read, and a dependency whose steps cannot say
26
- * leaves its dependents' references unresolved. The apply stage's plan reads
27
- * the same dependencies, so on the same estate it gets the digest the plan
28
- * stage showed, and it applies against the outputs its plans read
29
- * (`set.outputs`). A resume plans against the outputs the approved plans
30
- * read, from the record (`planOutputs`), and reads nothing those cover.
16
+ * - the upstream is in the change too: the value its plan says it will
17
+ * expose (`CapabilityPlan.outputs`). The report lists these under
18
+ * `plannedOutputs`.
19
+ * - the upstream is not in the change (#4104): the value it has now, read
20
+ * through its capability's `outputs` (`readComponentOutputs`). The report
21
+ * lists these under `deployedOutputs`. A change to one cluster is planned
22
+ * against the network it sits on, which is why `components` is every
23
+ * component in the project and not the selection.
24
+ * - the upstream is in the change and its plan cannot say, or says the value
25
+ * is known only after apply: no value. The dependent's members list the
26
+ * reference under `unknownInputs`, and the approval does not cover what
27
+ * it will do with it.
28
+ *
29
+ * `--seed-outputs` wins over both. The apply stage's plan reads the same
30
+ * values, so on the same estate it gets the digest the plan stage showed.
31
+ * A resume plans against the outputs the approved plans read, from the
32
+ * record (`planOutputs`), and reads nothing those cover.
33
+ *
34
+ * ## Planning again once an upstream applied
35
+ *
36
+ * The apply runs each member's approved plan, except a member whose plan
37
+ * read an upstream output that is not the value standing when its turn
38
+ * comes (`movedWiringReferences`): the upstream applied as another value
39
+ * than its plan said, or the value was unknown. That member, and what is
40
+ * downstream of it, is held back. Once the rest settled, the held members
41
+ * are planned again against the outputs the apply left, and that set's
42
+ * digest is decided at its own gate, `<gate>-round-<n>` (`prRoundGate`), as
43
+ * a gated wave decides each wave (#3049). Approved, it applies, and a member
44
+ * that is held again goes to the next round. Not approved, the apply stops
45
+ * `waiting` with the new digest named, and the same apply with its
46
+ * `--resume` record carries on from there.
31
47
  *
32
48
  * ## Finishing an apply that failed partway
33
49
  *
@@ -41,15 +57,24 @@
41
57
  * the rest applies. Planning everything again would give the applied members
42
58
  * empty plans and the set a new digest, and so ask for a second approval of
43
59
  * work already approved.
60
+ *
61
+ * ## A gate per wave on merge
62
+ *
63
+ * `pr-apply --wave-gate` (#4003) applies the approved set a wave at a time.
64
+ * {@link prWavePlan} narrows the derivation to one wave, which is planned
65
+ * against the outputs the waves before it left, and {@link waveNotCovered}
66
+ * says whether the approved change set covers what it planned, by the same
67
+ * test a resume uses ({@link planCoveredBy}). Covered, the wave applies under
68
+ * the pull request's approval; not covered, it needs its own.
44
69
  */
45
70
  import { composeChangeSet, verifyChangeSetDigest } from "../change-set.js";
46
71
  import { evaluateGate } from "../op/gate.js";
47
- import { memberCounts, PR_REPORT_CONTRACT, PR_REPORT_SCHEMA_ID, } from "../pr-loop.js";
48
- import { deployContext } from "./driver.js";
72
+ import { memberCounts, PR_APPLY_GATE, prRoundGate, PR_REPORT_CONTRACT, PR_REPORT_SCHEMA_ID, } from "../pr-loop.js";
73
+ import { deployContext, movedWiringReferences, unresolvedWiringReferences, } from "./driver.js";
49
74
  import { deployUnits } from "./deploy-units.js";
50
75
  import { runFanOut } from "./fan-out-run.js";
51
76
  import { remainingFanOut } from "./fan-out.js";
52
- import { planWaveComponent, readDeployedOutputs } from "./wave-plan.js";
77
+ import { capabilitySteps, planWaveComponent, readDeployedOutputs } from "./wave-plan.js";
53
78
  /** The phase a pull request's planning is, in its run's events. */
54
79
  export const PR_PLAN_PHASE = "plan";
55
80
  /** A failed component's members: the units its steps target, else the component itself. */
@@ -61,36 +86,51 @@ function failedParts(component, error) {
61
86
  }));
62
87
  }
63
88
  /**
64
- * Plan every component in `plan.order`, a wave at a time, each against the
65
- * outputs its dependencies have now. Never throws for a component that fails
66
- * to plan: it becomes a failed member, and `failed` is set. Throws when a
67
- * planned member's dependency is not among `components`, which means the
68
- * caller passed the selection where the whole graph belongs.
89
+ * Plan every component in `plan.order`, a wave at a time, each against its
90
+ * dependencies' planned outputs when the change plans them too, and against
91
+ * the outputs they have now otherwise. Never throws for a component that
92
+ * fails to plan: it becomes a failed member, and `failed` is set. Throws
93
+ * when a planned member's dependency is not among `components`, which means
94
+ * the caller passed the selection where the whole graph belongs.
69
95
  */
70
96
  export async function planPrSet(options) {
71
97
  const byName = new Map(options.components.map((c) => [c.name, c]));
72
98
  const outputs = { ...(options.seededOutputs ?? {}) };
73
99
  const read = new Set(Object.keys(outputs));
100
+ const inChange = new Set(options.plan.order);
101
+ /** What each component of the change planned to expose, once its wave planned. */
102
+ const plannedBy = new Map();
74
103
  const deployed = {};
104
+ const planned = {};
75
105
  const parts = [];
76
106
  const componentOf = new Map();
107
+ const unknownOf = new Map();
77
108
  const plans = {};
78
109
  let failed = false;
79
110
  const emit = options.onRunEvent;
80
111
  emit?.({ type: "phase-start", component: null, phase: PR_PLAN_PHASE });
81
112
  for (const wave of options.plan.waves) {
82
- // The dependencies' outputs first, each read once. A dependency that
83
- // cannot say leaves its references unresolved, which its dependent's
84
- // plan reports if it needs them. A dependency outside the selection is
85
- // read the same way (#4104).
113
+ // The dependencies' outputs first, each once. One the change plans is
114
+ // read from its plan, which an earlier wave made (#3999). Any other is
115
+ // read from the deployed estate (#4104). A dependency that cannot say
116
+ // leaves its references unresolved, which its dependent's plan reports
117
+ // if it needs them.
86
118
  const deps = [...new Set(wave.flatMap((name) => byName.get(name)?.dependsOn ?? []))].filter((dep) => !read.has(dep));
119
+ const fromEstate = [];
87
120
  for (const dep of deps) {
88
121
  read.add(dep);
89
122
  if (!byName.has(dep))
90
123
  throw new Error(`planPrSet: ${dep}, a dependency of a planned member, is not among the components; pass every component in the project`);
124
+ if (!inChange.has(dep)) {
125
+ fromEstate.push(dep);
126
+ continue;
127
+ }
128
+ const known = plannedBy.get(dep)?.known ?? {};
129
+ outputs[dep] = { ...known };
130
+ planned[dep] = Object.keys(known).sort();
91
131
  }
92
- Object.assign(deployed, await readDeployedOutputs(deps, byName, options.registry, (dep) => deployContext(options, dep), outputs));
93
- const planned = await Promise.all(wave.map(async (name) => {
132
+ Object.assign(deployed, await readDeployedOutputs(fromEstate, byName, options.registry, (dep) => deployContext(options, dep), outputs));
133
+ const results = await Promise.all(wave.map(async (name) => {
94
134
  const at = { component: name, phase: PR_PLAN_PHASE, step: "plan" };
95
135
  emit?.({ type: "step-start", ...at });
96
136
  const start = Date.now();
@@ -104,16 +144,21 @@ export async function planPrSet(options) {
104
144
  });
105
145
  return p;
106
146
  }));
107
- for (const p of planned) {
147
+ for (const p of results) {
108
148
  const component = byName.get(p.component);
149
+ const unknown = unknownInputsOf(component, outputs, inChange);
150
+ if (unknown.unknown.length > 0 || unknown.build.length > 0)
151
+ unknownOf.set(p.component, unknown);
109
152
  if ("error" in p) {
110
153
  failed = true;
154
+ plannedBy.set(p.component, undefined);
111
155
  for (const part of failedParts(component, p.error)) {
112
156
  parts.push(part);
113
157
  componentOf.set(part.member.member, p.component);
114
158
  }
115
159
  continue;
116
160
  }
161
+ plannedBy.set(p.component, p.outputs);
117
162
  plans[p.component] = p.plans;
118
163
  for (const part of p.parts) {
119
164
  parts.push(part);
@@ -123,16 +168,71 @@ export async function planPrSet(options) {
123
168
  }
124
169
  emit?.({ type: "phase-settle", component: null, phase: PR_PLAN_PHASE, status: failed ? "failed" : "ok" });
125
170
  const doc = composeChangeSet(parts);
126
- const members = doc.members.map((m) => ({
127
- member: m.member,
128
- component: componentOf.get(m.member) ?? m.member,
129
- planDigest: m.planDigest,
130
- status: m.status === "failed" ? "plan-failed" : "planned",
131
- counts: memberCounts(doc, m.member),
132
- ...(m.error ? { error: m.error } : {}),
133
- }));
134
- const deployedOutputs = Object.fromEntries(Object.entries(deployed).sort(([a], [b]) => a.localeCompare(b)));
135
- return { doc, members, plans, outputs, failed, ...(Object.keys(deployedOutputs).length > 0 ? { deployedOutputs } : {}) };
171
+ const members = doc.members.map((m) => {
172
+ const component = componentOf.get(m.member) ?? m.member;
173
+ const unknown = unknownOf.get(component);
174
+ return {
175
+ member: m.member,
176
+ component,
177
+ planDigest: m.planDigest,
178
+ status: m.status === "failed" ? "plan-failed" : "planned",
179
+ counts: memberCounts(doc, m.member),
180
+ ...(m.error ? { error: m.error } : {}),
181
+ ...(unknown?.unknown.length ? { unknownInputs: unknown.unknown } : {}),
182
+ ...(unknown?.build.length ? { buildInputs: unknown.build } : {}),
183
+ };
184
+ });
185
+ const sorted = (r) => Object.fromEntries(Object.entries(r).sort(([a], [b]) => a.localeCompare(b)));
186
+ const deployedOutputs = sorted(deployed);
187
+ const plannedOutputs = sorted(planned);
188
+ return {
189
+ doc,
190
+ members,
191
+ plans,
192
+ outputs,
193
+ failed,
194
+ ...(Object.keys(deployedOutputs).length > 0 ? { deployedOutputs } : {}),
195
+ ...(Object.keys(plannedOutputs).length > 0 ? { plannedOutputs } : {}),
196
+ };
197
+ }
198
+ /**
199
+ * The references `component`'s steps make to an output of a component in
200
+ * the change that `outputs` holds no value for (#3999), known only after
201
+ * that upstream applies, each sorted. `build` are the published artifact
202
+ * identities a build in the change produces (`WiringReference.publish`):
203
+ * the build's provenance binds those, so they are never approved again.
204
+ * `unknown` are the rest.
205
+ */
206
+ function unknownInputsOf(component, outputs, inChange) {
207
+ const unknown = new Set();
208
+ const build = new Set();
209
+ for (const step of capabilitySteps(component.deploy)) {
210
+ const { kind: _kind, ...rest } = step;
211
+ for (const r of unresolvedWiringReferences(rest, outputs)) {
212
+ if (inChange.has(r.source))
213
+ (r.publish ? build : unknown).add(r.ref);
214
+ }
215
+ }
216
+ return { unknown: [...unknown].sort(), build: [...build].sort() };
217
+ }
218
+ /**
219
+ * Why `component` cannot apply the plan that read `read` now that `now`
220
+ * stands (#3999): each reference its steps make that resolves to another
221
+ * value, said once. `undefined` when every one resolves as it did. A
222
+ * published artifact's identity from a build in `inChange` never holds a
223
+ * member back: the build's provenance binds it, not this approval.
224
+ */
225
+ export function heldReason(component, read, now, inChange = new Set()) {
226
+ const refs = new Set();
227
+ for (const step of capabilitySteps(component.deploy)) {
228
+ const { kind: _kind, ...rest } = step;
229
+ for (const r of movedWiringReferences(rest, read, now))
230
+ if (!(r.publish && inChange.has(r.source)))
231
+ refs.add(r.ref);
232
+ }
233
+ if (refs.size === 0)
234
+ return undefined;
235
+ return `its plan read ${[...refs].sort().join(", ")} before ${refs.size === 1 ? "that output" : "those outputs"} applied as another value`;
136
236
  }
137
237
  /**
138
238
  * A ledger that reads the real one and records nothing. The plan stage
@@ -178,58 +278,132 @@ export function approversWithoutReview(approvedBy, reviewers) {
178
278
  const allowed = new Set(reviewers.map(norm));
179
279
  return approvedBy.filter((by) => !allowed.has(norm(by)));
180
280
  }
181
- const sameJson = (a, b) => JSON.stringify(a ?? null) === JSON.stringify(b ?? null);
281
+ /**
282
+ * Who approved the gate but wrote the change (#4000): each approval's
283
+ * `resolvedBy` that names one of `authors`, the forge's naming of the pull
284
+ * request's author and of its commits' authors and committers. Their own
285
+ * approval never counts, whether a forge review or a ledger line backs it.
286
+ */
287
+ export function approversWhoAuthored(approvedBy, authors) {
288
+ const norm = (s) => s.trim().toLowerCase();
289
+ const wrote = new Set(authors.map(norm));
290
+ return approvedBy.filter((by) => wrote.has(norm(by)));
291
+ }
292
+ /** Two runs of one apply as one: `b` ran after `a`, against the outputs `a` left. */
293
+ function joinRuns(a, b) {
294
+ const status = a.status === "fail" || b.status === "fail" ? "fail" : a.status === "gated" || b.status === "gated" ? "gated" : "ok";
295
+ const gate = a.gate ?? b.gate;
296
+ return {
297
+ plan: a.plan,
298
+ status,
299
+ results: [...a.results, ...b.results],
300
+ completed: [...new Set([...a.completed, ...b.completed])].sort(),
301
+ failed: [...new Set([...a.failed, ...b.failed])].sort(),
302
+ blocked: [...a.blocked, ...b.blocked],
303
+ componentOutputs: b.componentOutputs,
304
+ ...(gate ? { gate } : {}),
305
+ ...(b.held ? { held: b.held } : {}),
306
+ };
307
+ }
182
308
  /**
183
309
  * Apply the approved plans in dependency order. A failed component blocks
184
- * its dependents and nothing else (`runFanOut`).
310
+ * its dependents and nothing else (`runFanOut`). A member whose plan read an
311
+ * upstream output that is not the value standing when its turn comes is held
312
+ * back with what is downstream of it, planned again once the rest settled,
313
+ * and applied when `decideRound` approves that plan (#3999).
185
314
  */
186
315
  export async function applyPrSet(options) {
187
- const before = options.set.outputs;
188
- const run = await runFanOut(options.plan, options.components, options.registry, {
316
+ const byName = new Map(options.components.map((c) => [c.name, c]));
317
+ const priorCompleted = new Set(options.resumed?.completed ?? []);
318
+ const inChange = new Set([...options.set.members.map((m) => m.component), ...options.plan.order]);
319
+ const toApply = new Set([...inChange].filter((name) => !priorCompleted.has(name)));
320
+ // The outputs standing as the apply starts: what the plans read of
321
+ // components outside the change, and what an earlier attempt's components
322
+ // left (the values the plans read, where its record kept none). A planned
323
+ // value of a component still to apply stands nowhere until it applies.
324
+ const standing = {
325
+ ...Object.fromEntries(Object.entries(options.set.outputs).filter(([name]) => !toApply.has(name))),
326
+ ...(options.resumed?.outputs ?? {}),
327
+ };
328
+ const runRound = (plan, plans, read, outputs) => runFanOut(plan, options.components, options.registry, {
189
329
  env: options.env,
190
330
  ...(options.vars ? { vars: options.vars } : {}),
191
- plans: options.set.plans,
192
- componentOutputs: { ...before },
331
+ plans,
332
+ componentOutputs: outputs,
333
+ hold: (name, now) => heldReason(byName.get(name), read, now, inChange),
193
334
  ...(options.onProgress ? { onProgress: options.onProgress } : {}),
194
335
  ...(options.onRunEvent ? { onRunEvent: options.onRunEvent } : {}),
195
336
  ...(options.onComponentSettled ? { onComponentSettled: options.onComponentSettled } : {}),
196
337
  });
338
+ let run = await runRound(options.plan, options.set.plans, options.set.outputs, { ...standing });
339
+ const rounds = [];
340
+ /** Per component, the round that applied it or holds it, and that round's set, after the first. */
341
+ const roundOf = new Map();
342
+ let stopped;
343
+ while (run.held && run.held.length > 0 && run.status === "ok" && options.decideRound) {
344
+ const round = rounds.length + 2;
345
+ const gate = prRoundGate(options.gate ?? PR_APPLY_GATE, round);
346
+ const heldNames = new Set(run.held.map((h) => h.component));
347
+ const plan = remainingFanOut(options.plan, options.components, { completed: options.plan.order.filter((name) => !heldNames.has(name)) });
348
+ const set = await planPrSet({
349
+ components: options.components,
350
+ plan,
351
+ registry: options.registry,
352
+ env: options.env,
353
+ ...(options.vars ? { vars: options.vars } : {}),
354
+ seededOutputs: run.componentOutputs,
355
+ });
356
+ for (const name of plan.order)
357
+ roundOf.set(name, { round, set });
358
+ const record = (status, approval, message) => {
359
+ rounds.push({ round, gate, digest: set.doc.digest, components: plan.order, approval, status, ...(message ? { message } : {}), changeSet: set.doc });
360
+ };
361
+ if (set.failed) {
362
+ record("plan-failed", { status: "pending" });
363
+ stopped = "plan-failed";
364
+ break;
365
+ }
366
+ const decision = await options.decideRound({ round, gate, set, plan });
367
+ if (!decision.satisfied) {
368
+ record("waiting", decision.approval, decision.message);
369
+ stopped = "waiting";
370
+ break;
371
+ }
372
+ const next = await runRound(plan, set.plans, set.outputs, run.componentOutputs);
373
+ record(next.status === "fail" ? "failed" : "applied", decision.approval);
374
+ run = joinRuns(run, next);
375
+ }
197
376
  const completed = new Set(run.completed);
198
- const priorCompleted = new Set(options.resumed?.completed ?? []);
199
- /**
200
- * Whether a dependency's outputs moved from what the plans read: by this
201
- * run's apply, or by the earlier attempt's when the record kept them.
202
- */
203
- const movedBy = (dep) => {
204
- if (completed.has(dep))
205
- return !sameJson(before[dep], run.componentOutputs[dep]);
206
- const earlier = options.resumed?.outputs;
207
- return priorCompleted.has(dep) && earlier !== undefined && dep in earlier && !sameJson(before[dep], earlier[dep]);
208
- };
377
+ const held = new Map((run.held ?? []).map((h) => [h.component, h]));
209
378
  const blocked = new Set(run.blocked.map((b) => b.component));
210
379
  const errorOf = (component) => {
211
- const result = run.results.find((r) => r.component === component);
380
+ const result = [...run.results].reverse().find((r) => r.component === component);
212
381
  if (result?.status === "gated")
213
382
  return `stopped at its own gate ${result.gate?.gate ?? ""}`.trim();
214
383
  return result?.records.find((r) => r.status === "fail")?.error;
215
384
  };
216
- const byName = new Map(options.components.map((c) => [c.name, c]));
217
385
  const members = options.set.members.map((m) => {
218
386
  if (priorCompleted.has(m.component))
219
387
  return { ...m, status: "applied" };
220
- if (completed.has(m.component)) {
221
- const moved = (byName.get(m.component)?.dependsOn ?? [])
222
- .filter(movedBy)
223
- .sort();
224
- return { ...m, status: "applied", ...(moved.length > 0 ? { inputsMoved: moved } : {}) };
225
- }
388
+ const later = roundOf.get(m.component);
389
+ const fresh = later?.set.members.find((x) => x.member === m.member);
390
+ const asPlanned = later && fresh ? { ...m, planDigest: fresh.planDigest, counts: fresh.counts, round: later.round } : m;
391
+ if (completed.has(m.component))
392
+ return { ...asPlanned, status: "applied" };
393
+ const h = held.get(m.component);
394
+ if (h)
395
+ return { ...asPlanned, status: "waiting", held: h.heldBy ? `${h.heldBy} is held: ${h.reason}` : h.reason };
396
+ if (fresh?.status === "plan-failed")
397
+ return { ...asPlanned, status: "plan-failed", ...(fresh.error ? { error: fresh.error } : {}) };
226
398
  if (blocked.has(m.component))
227
- return { ...m, status: "blocked" };
399
+ return { ...asPlanned, status: "blocked" };
228
400
  const error = errorOf(m.component);
229
- return { ...m, status: "failed", ...(error ? { error } : {}) };
401
+ return { ...asPlanned, status: "failed", ...(error ? { error } : {}) };
230
402
  });
231
- return { members, status: run.status === "ok" ? "applied" : "failed", run };
403
+ const status = run.status !== "ok" || stopped === "plan-failed" ? "failed" : held.size > 0 || stopped === "waiting" ? "waiting" : "applied";
404
+ return { members, status, run, ...(rounds.length > 0 ? { rounds } : {}) };
232
405
  }
406
+ const sameJson = (a, b) => JSON.stringify(a ?? null) === JSON.stringify(b ?? null);
233
407
  const entryKey = (e) => `${e.member}\u0000${e.address}\u0000${e.deposed ?? ""}`;
234
408
  /**
235
409
  * Why `member`'s fresh plan is not covered by the approved change set, or
@@ -361,6 +535,48 @@ export async function resumePrSet(options) {
361
535
  },
362
536
  };
363
537
  }
538
+ /**
539
+ * The fan-out narrowed to wave `wave` of `plan` (1-based), less the
540
+ * components in `completed` (#4003). Its one wave is what is left of that
541
+ * wave; a dependency outside it, an earlier wave's component among them, is
542
+ * a seed. The digest is the derivation's, as {@link remainingFanOut} keeps it.
543
+ */
544
+ export function prWavePlan(plan, components, wave, completed = []) {
545
+ const done = new Set(completed);
546
+ const order = (plan.waves[wave - 1] ?? []).filter((name) => !done.has(name));
547
+ const inWave = new Set(order);
548
+ const byName = new Map(components.map((c) => [c.name, c]));
549
+ const seeds = [
550
+ ...new Set([...plan.seeds, ...order.flatMap((name) => (byName.get(name)?.dependsOn ?? []).filter((dep) => !inWave.has(dep)))]),
551
+ ].sort();
552
+ return { order, waves: order.length > 0 ? [order] : [], skipped: [], seeds, indeterminate: plan.indeterminate, digest: plan.digest };
553
+ }
554
+ /**
555
+ * Why the approved change set does not cover a wave's new plan, one line per
556
+ * member, or `[]` when it covers every member (#4003). A member is covered
557
+ * as {@link planCoveredBy} says, with one rule more: a member whose planner
558
+ * describes no changes (chant's own empty part, for a capability that
559
+ * returns no change set) is covered only by the digest it was approved
560
+ * with, since with no entries there is nothing to compare a moved plan by.
561
+ */
562
+ export function waveNotCovered(approved, fresh, approvedMembers = []) {
563
+ // #3999: a member whose approved plan waited only on an artifact a build in
564
+ // the change publishes is covered by that build's provenance, as it is
565
+ // without --wave-gate.
566
+ const byBuild = new Set(approvedMembers.filter((m) => m.buildInputs?.length && !m.unknownInputs?.length).map((m) => m.member));
567
+ return fresh.members
568
+ .map((m) => {
569
+ if (byBuild.has(m.member))
570
+ return undefined;
571
+ const was = approved.members.find((a) => a.member === m.member);
572
+ const opaque = m.planner === "chant" && m.lexicon === "chant" && m.status === "planned";
573
+ if (opaque && was && was.planDigest !== m.planDigest) {
574
+ return `${m.member} now plans to ${m.planDigest}, not the approved ${was.planDigest ?? "(none)"}, and its planner describes no changes to compare`;
575
+ }
576
+ return planCoveredBy(approved, fresh, m.member);
577
+ })
578
+ .filter((r) => r !== undefined);
579
+ }
364
580
  /** The report a stage writes. */
365
581
  export function prReport(input) {
366
582
  const changed = new Set(input.signal.changed);
@@ -381,7 +597,11 @@ export function prReport(input) {
381
597
  ...(input.message ? { message: input.message } : {}),
382
598
  ...(input.resumed ? { resumed: { applied: [...input.resumed].sort() } } : {}),
383
599
  ...(input.set.deployedOutputs ? { deployedOutputs: input.set.deployedOutputs } : {}),
600
+ ...(input.set.plannedOutputs ? { plannedOutputs: input.set.plannedOutputs } : {}),
601
+ ...(input.rounds && input.rounds.length > 0 ? { rounds: input.rounds } : {}),
384
602
  approval: input.approval,
603
+ ...(input.waveGate ? { waveGate: input.waveGate } : {}),
604
+ ...(input.waveGate && input.waves?.length ? { waves: [...input.waves].sort((a, b) => a.wave - b.wave) } : {}),
385
605
  selection: {
386
606
  changed: input.plan.order.filter((c) => changed.has(c)),
387
607
  dependents: input.plan.order.filter((c) => !changed.has(c)),
@@ -19,20 +19,23 @@
19
19
  * `@<component>.publish.*`) resolves.
20
20
  */
21
21
  import { type DriverComponent, type DriverPhase, type DriverStep } from "./driver.js";
22
- import type { CapabilityRegistry, DeployContext } from "./capability.js";
22
+ import type { CapabilityRegistry, DeployContext, PlannedOutputs } from "./capability.js";
23
23
  import type { WaveMember } from "../gated-waves.js";
24
24
  import type { ChangeSetPart } from "../change-set.js";
25
25
  /**
26
26
  * What planning one component produced: its members, what its steps hand to
27
27
  * `run`, and each member's change-set part (#3183), or why it could not plan.
28
28
  * A member whose capability returns no part gets one with no entries, so the
29
- * parts always cover the members.
29
+ * parts always cover the members. `outputs` is what its steps' plans say the
30
+ * component will expose once applied (#3999), merged the way the driver
31
+ * merges a run's outputs; absent when no step's plan says.
30
32
  */
31
33
  export type WaveComponentPlan = {
32
34
  component: string;
33
35
  members: WaveMember[];
34
36
  plans: Record<string, unknown>;
35
37
  parts: ChangeSetPart[];
38
+ outputs?: PlannedOutputs;
36
39
  } | {
37
40
  component: string;
38
41
  error: string;
@@ -1 +1 @@
1
- {"version":3,"file":"wave-plan.d.ts","sourceRoot":"","sources":["../../src/components/wave-plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAA6C,KAAK,eAAe,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAE9H,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GACzB;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,UAAU,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,KAAK,EAAE,aAAa,EAAE,CAAA;CAAE,GACpG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAUzC,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,GAAG,UAAU,EAAE,CAc5E;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,aAAa,EAClB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxD,aAAa,CAGf;AAED,oHAAoH;AACpH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,eAAe,EAC1B,QAAQ,EAAE,kBAAkB,EAC5B,GAAG,EAAE,aAAa,EAClB,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxD,OAAO,CAAC,iBAAiB,CAAC,CAgC5B;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,eAAe,EAC1B,QAAQ,EAAE,kBAAkB,EAC5B,GAAG,EAAE,aAAa,EAClB,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxD,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,CAU9C;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,eAAe,CAAC,EAChD,QAAQ,EAAE,kBAAkB,EAC5B,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,aAAa,EAC3C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAC/C,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAYnC"}
1
+ {"version":3,"file":"wave-plan.d.ts","sourceRoot":"","sources":["../../src/components/wave-plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAA6C,KAAK,eAAe,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAE9H,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACtF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GACzB;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,UAAU,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,KAAK,EAAE,aAAa,EAAE,CAAC;IAAC,OAAO,CAAC,EAAE,cAAc,CAAA;CAAE,GAC9H;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAUzC,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,GAAG,UAAU,EAAE,CAc5E;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,aAAa,EAClB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxD,aAAa,CAGf;AAED,oHAAoH;AACpH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,eAAe,EAC1B,QAAQ,EAAE,kBAAkB,EAC5B,GAAG,EAAE,aAAa,EAClB,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxD,OAAO,CAAC,iBAAiB,CAAC,CAkC5B;AAUD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,eAAe,EAC1B,QAAQ,EAAE,kBAAkB,EAC5B,GAAG,EAAE,aAAa,EAClB,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxD,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,CAU9C;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,eAAe,CAAC,EAChD,QAAQ,EAAE,kBAAkB,EAC5B,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,aAAa,EAC3C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAC/C,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAYnC"}
@@ -59,6 +59,7 @@ export async function planWaveComponent(component, registry, ctx, componentOutpu
59
59
  const members = [];
60
60
  const plans = {};
61
61
  const parts = [];
62
+ let outputs;
62
63
  for (const step of capabilitySteps(component.deploy)) {
63
64
  const capability = registry.resolve(step.kind);
64
65
  if (!capability.plan)
@@ -71,6 +72,8 @@ export async function planWaveComponent(component, registry, ctx, componentOutpu
71
72
  parts.push(planned.changeSet ?? emptyPart(member));
72
73
  if (planned.artifact !== undefined)
73
74
  plans[planned.member] = planned.artifact;
75
+ if (planned.outputs)
76
+ outputs = mergePlannedOutputs(outputs, planned.outputs);
74
77
  }
75
78
  if (members.length === 0) {
76
79
  const member = {
@@ -84,12 +87,20 @@ export async function planWaveComponent(component, registry, ctx, componentOutpu
84
87
  members.push(member);
85
88
  parts.push(emptyPart(member));
86
89
  }
87
- return { component: component.name, members, plans, parts };
90
+ return { component: component.name, members, plans, parts, ...(outputs ? { outputs } : {}) };
88
91
  }
89
92
  catch (err) {
90
93
  return { component: component.name, error: err instanceof Error ? err.message : String(err) };
91
94
  }
92
95
  }
96
+ /** `next` over `prior`, as a later step's outputs win over an earlier one's in a run. */
97
+ function mergePlannedOutputs(prior, next) {
98
+ const known = { ...(prior?.known ?? {}), ...next.known };
99
+ const unknown = new Set([...(prior?.unknown ?? []).filter((n) => !(n in next.known)), ...next.unknown]);
100
+ for (const n of unknown)
101
+ delete known[n];
102
+ return { known, unknown: [...unknown].sort() };
103
+ }
93
104
  /**
94
105
  * The outputs `component` exposes now, read from each step whose capability
95
106
  * has `outputs` (#3183), merged the way the driver merges a run's outputs.
@@ -1 +1 @@
1
- {"version":3,"file":"fold-import.d.ts","sourceRoot":"","sources":["../../src/discovery/fold-import.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fold-import.d.ts","sourceRoot":"","sources":["../../src/discovery/fold-import.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,7 @@ import { isIntrinsic } from "../intrinsic.js";
11
11
  import { collectConsts, foldResource, fold, propName, FoldError, isFoldableFunction, locate, collectSameFileFunctions, constResolvesToResource, } from "../fold/fold.js";
12
12
  import { isChantOwnedSpecifier, isFoldableHelperName } from "../fold/foldable-helpers.js";
13
13
  import { lexiconModulePath, lexiconModuleRoot } from "../lexicon-module.js";
14
+ import { compiledModuleSource } from "../module-source.js";
14
15
  import { isFile, packageExportsTarget, probeModuleFile, splitBareSpecifier, tsconfigPathsMatch, } from "./specifier-resolve.js";
15
16
  import { briefNodeText, callExpressionMessage, computedPropertyNameMessage, isLiteralElementKey, unsupportedBinaryMessage, unsupportedExpressionMessage, UNSUPPORTED_OBJECT_MEMBER_MESSAGE, UNSUPPORTED_UNARY_MESSAGE, SUPPORTED_BINARY_OPERATORS, SUPPORTED_UNARY_OPERATORS, } from "../fold/subset.js";
16
17
  import { importModule } from "./import.js";
@@ -1375,10 +1376,11 @@ function isUnfoldableSameFileCall(name, ctx) {
1375
1376
  // specifier, or its package root for a subpath, against
1376
1377
  // {@link FoldSession.lexiconPackages}, exactly as
1377
1378
  // {@link isTrustedExecutableBinding}'s arm 1 matches it — and only then
1378
- // resolved; a module that resolves to compiled JavaScript or a declaration
1379
- // file is not interpreted, so a package that ships only `dist` keeps
1380
- // invoking. Every chant lexicon routes its exports at `./src/*.ts`
1381
- // (check-lexicon tier 1), so in practice the source is always there.
1379
+ // resolved; a module that resolves to a declaration file, or to compiled
1380
+ // JavaScript with no `src/` source beside its `dist/`, is not interpreted,
1381
+ // so a package that ships only `dist` keeps invoking. Every chant lexicon
1382
+ // publishes `src/` beside the `dist/*.js` its exports name (#3981), and
1383
+ // a compiled module is read from that source.
1382
1384
  // Interpreting buys provenance: the run path cannot say which parameter
1383
1385
  // fed a field, and interpretation can (#2161, #3246).
1384
1386
  //
@@ -1713,8 +1715,16 @@ function factoryOrigin(specifier, fromFile, ctx) {
1713
1715
  catch {
1714
1716
  return undefined;
1715
1717
  }
1716
- if (!isTypeScriptSource(modulePath))
1717
- return undefined;
1718
+ if (!isTypeScriptSource(modulePath)) {
1719
+ // #3981 — a lexicon's exports resolve to the compiled dist/*.js it
1720
+ // publishes, beside the src/ it was built from. The source is what is
1721
+ // read; an import the body makes still loads the compiled module, since
1722
+ // the compiled CLI points a lexicon's src/*.ts at its dist/*.js.
1723
+ const source = compiledModuleSource(modulePath);
1724
+ if (source === undefined || !isFile(source))
1725
+ return undefined;
1726
+ modulePath = source;
1727
+ }
1718
1728
  const packageRoot = lexiconPackageDirectory(modulePath, packageName);
1719
1729
  return packageRoot === undefined ? undefined : { modulePath, packageRoot };
1720
1730
  }
@@ -1 +1 @@
1
- {"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../../../src/discovery/sandbox/bundle.ts"],"names":[],"mappings":"AA0LA,MAAM,WAAW,YAAY;IAC3B,uSAAuS;IACvS,UAAU,EAAE,MAAM,CAAC;IACnB,kJAAkJ;IAClJ,SAAS,EAAE,MAAM,CAAC;IAClB,uQAAuQ;IACvQ,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,uGAAuG;IACvG,UAAU,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA4B9E"}
1
+ {"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../../../src/discovery/sandbox/bundle.ts"],"names":[],"mappings":"AA2LA,MAAM,WAAW,YAAY;IAC3B,uSAAuS;IACvS,UAAU,EAAE,MAAM,CAAC;IACnB,kJAAkJ;IAClJ,SAAS,EAAE,MAAM,CAAC;IAClB,uQAAuQ;IACvQ,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,uGAAuG;IACvG,UAAU,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAiC9E"}