@intentius/chant 0.124.13 → 0.124.15

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 (991) hide show
  1. package/bin/chant +11 -0
  2. package/dist/agents/checks.js +326 -0
  3. package/dist/agents/discover.js +885 -0
  4. package/dist/agents/importer.js +17 -0
  5. package/dist/agents/index.js +12 -0
  6. package/dist/agents/types.js +19 -0
  7. package/dist/apply.js +151 -0
  8. package/dist/attrref.js +70 -0
  9. package/dist/audit/catalog.js +350 -0
  10. package/dist/audit/core.js +252 -0
  11. package/dist/audit/discover.js +633 -0
  12. package/dist/audit/fetch.js +666 -0
  13. package/dist/audit/lineage.js +91 -0
  14. package/dist/audit/nginx.js +366 -0
  15. package/dist/audit/prior-art.js +132 -0
  16. package/dist/audit/proof.js +321 -0
  17. package/dist/audit/report-html.js +194 -0
  18. package/dist/audit/report-model.js +198 -0
  19. package/dist/audit/report.js +102 -0
  20. package/dist/audit/rules-doc.js +144 -0
  21. package/dist/audit/secrets.js +405 -0
  22. package/dist/audit/terraform-state.js +140 -0
  23. package/dist/audit/wrangler.js +262 -0
  24. package/dist/behaviour-delta.js +401 -0
  25. package/dist/behaviour-engine.js +357 -0
  26. package/dist/behaviour-graph.js +83 -0
  27. package/dist/behaviour-http.js +188 -0
  28. package/dist/behaviour-kinds.js +172 -0
  29. package/dist/behaviour-overlay.js +50 -0
  30. package/dist/behaviour-predict.js +188 -0
  31. package/dist/behaviour-request.js +194 -0
  32. package/dist/behaviour.js +1325 -0
  33. package/dist/build-params.js +108 -0
  34. package/dist/build.d.ts +6 -0
  35. package/dist/build.d.ts.map +1 -1
  36. package/dist/build.js +669 -0
  37. package/dist/builder.js +44 -0
  38. package/dist/cdk/advise.js +30 -0
  39. package/dist/cdk/assembly.js +122 -0
  40. package/dist/cdk/graph.js +444 -0
  41. package/dist/cdk/tier-map.js +64 -0
  42. package/dist/cdk/types.js +24 -0
  43. package/dist/change-set.d.ts +24 -2
  44. package/dist/change-set.d.ts.map +1 -1
  45. package/dist/change-set.js +361 -0
  46. package/dist/child-project.js +21 -0
  47. package/dist/ci-jobs.d.ts +227 -0
  48. package/dist/ci-jobs.d.ts.map +1 -0
  49. package/dist/ci-jobs.js +448 -0
  50. package/dist/claimed-fields.js +135 -0
  51. package/dist/cli/build-options.js +70 -0
  52. package/dist/cli/build-params-cli.js +139 -0
  53. package/dist/cli/command-group.js +123 -0
  54. package/dist/cli/commands/audit-agents.js +326 -0
  55. package/dist/cli/commands/audit.js +571 -0
  56. package/dist/cli/commands/build.js +920 -0
  57. package/dist/cli/commands/carve-apply.js +153 -0
  58. package/dist/cli/commands/carve-bridge.js +201 -0
  59. package/dist/cli/commands/carve-emit.js +332 -0
  60. package/dist/cli/commands/carve-status.js +119 -0
  61. package/dist/cli/commands/carve.js +204 -0
  62. package/dist/cli/commands/check-lexicon-docs.js +79 -0
  63. package/dist/cli/commands/check-lexicon-examples.js +177 -0
  64. package/dist/cli/commands/check-lexicon-intrinsics.js +291 -0
  65. package/dist/cli/commands/check-lexicon-mcp.js +82 -0
  66. package/dist/cli/commands/check-lexicon-plugin.d.ts.map +1 -1
  67. package/dist/cli/commands/check-lexicon-plugin.js +104 -0
  68. package/dist/cli/commands/check-lexicon.js +766 -0
  69. package/dist/cli/commands/describe.js +85 -0
  70. package/dist/cli/commands/diff.js +175 -0
  71. package/dist/cli/commands/doctor.js +350 -0
  72. package/dist/cli/commands/import-agents.js +155 -0
  73. package/dist/cli/commands/import.js +670 -0
  74. package/dist/cli/commands/init-lexicon/templates/codegen.js +194 -0
  75. package/dist/cli/commands/init-lexicon/templates/docs.js +100 -0
  76. package/dist/cli/commands/init-lexicon/templates/examples.js +29 -0
  77. package/dist/cli/commands/init-lexicon/templates/lint.js +34 -0
  78. package/dist/cli/commands/init-lexicon/templates/lsp.js +37 -0
  79. package/dist/cli/commands/init-lexicon/templates/plugin.js +108 -0
  80. package/dist/cli/commands/init-lexicon/templates/project.js +240 -0
  81. package/dist/cli/commands/init-lexicon/templates/spec.js +56 -0
  82. package/dist/cli/commands/init-lexicon/templates/tests.js +66 -0
  83. package/dist/cli/commands/init-lexicon.js +172 -0
  84. package/dist/cli/commands/init.js +381 -0
  85. package/dist/cli/commands/lexicon-rolling-upgrade.js +145 -0
  86. package/dist/cli/commands/lexicon-surface-diff.js +145 -0
  87. package/dist/cli/commands/licenses.js +125 -0
  88. package/dist/cli/commands/lint.d.ts.map +1 -1
  89. package/dist/cli/commands/lint.js +948 -0
  90. package/dist/cli/commands/list.js +63 -0
  91. package/dist/cli/commands/migrate.d.ts.map +1 -1
  92. package/dist/cli/commands/migrate.js +423 -0
  93. package/dist/cli/commands/onboard.js +403 -0
  94. package/dist/cli/commands/pinned-upgrade.js +191 -0
  95. package/dist/cli/commands/update.js +194 -0
  96. package/dist/cli/commands/vendor.js +217 -0
  97. package/dist/cli/conflict-check.js +104 -0
  98. package/dist/cli/debug.js +8 -0
  99. package/dist/cli/format.js +104 -0
  100. package/dist/cli/handlers/build.js +267 -0
  101. package/dist/cli/handlers/carve-apply.js +30 -0
  102. package/dist/cli/handlers/carve-bridge.js +28 -0
  103. package/dist/cli/handlers/carve-emit.js +50 -0
  104. package/dist/cli/handlers/carve-status.js +26 -0
  105. package/dist/cli/handlers/carve.js +40 -0
  106. package/dist/cli/handlers/change-set.js +46 -0
  107. package/dist/cli/handlers/components.js +730 -0
  108. package/dist/cli/handlers/dev.js +113 -0
  109. package/dist/cli/handlers/emulator.js +233 -0
  110. package/dist/cli/handlers/explain.js +54 -0
  111. package/dist/cli/handlers/fan-out.js +422 -0
  112. package/dist/cli/handlers/gate-resume.js +275 -0
  113. package/dist/cli/handlers/generate.js +84 -0
  114. package/dist/cli/handlers/graph.js +969 -0
  115. package/dist/cli/handlers/init.js +102 -0
  116. package/dist/cli/handlers/lifecycle.js +1727 -0
  117. package/dist/cli/handlers/lint.js +62 -0
  118. package/dist/cli/handlers/migrate.js +48 -0
  119. package/dist/cli/handlers/misc.js +391 -0
  120. package/dist/cli/handlers/operator.js +1162 -0
  121. package/dist/cli/handlers/override-approve.js +102 -0
  122. package/dist/cli/handlers/pr.js +503 -0
  123. package/dist/cli/handlers/promote.js +342 -0
  124. package/dist/cli/handlers/run-generate.js +206 -0
  125. package/dist/cli/handlers/run-wave.js +66 -0
  126. package/dist/cli/handlers/run.js +1191 -0
  127. package/dist/cli/handlers/scenario.js +325 -0
  128. package/dist/cli/handlers/search.js +924 -0
  129. package/dist/cli/handlers/serve.js +32 -0
  130. package/dist/cli/handlers/vendor.js +154 -0
  131. package/dist/cli/index.js +3 -0
  132. package/dist/cli/is-entry-point.js +23 -0
  133. package/dist/cli/lsp/capabilities.js +28 -0
  134. package/dist/cli/lsp/diagnostics.js +34 -0
  135. package/dist/cli/lsp/server.js +329 -0
  136. package/dist/cli/main.d.ts.map +1 -1
  137. package/dist/cli/main.js +2540 -0
  138. package/dist/cli/mcp/lifecycle-tools.js +80 -0
  139. package/dist/cli/mcp/op-tools.js +306 -0
  140. package/dist/cli/mcp/resource-handlers.js +258 -0
  141. package/dist/cli/mcp/resources/context.js +85 -0
  142. package/dist/cli/mcp/server.js +353 -0
  143. package/dist/cli/mcp/tools/build.js +111 -0
  144. package/dist/cli/mcp/tools/composites.js +95 -0
  145. package/dist/cli/mcp/tools/explain.js +166 -0
  146. package/dist/cli/mcp/tools/import.js +49 -0
  147. package/dist/cli/mcp/tools/lint.js +41 -0
  148. package/dist/cli/mcp/tools/scaffold.js +111 -0
  149. package/dist/cli/mcp/tools/search.js +112 -0
  150. package/dist/cli/mcp/types.js +1 -0
  151. package/dist/cli/mcp/workspace-plugins.js +91 -0
  152. package/dist/cli/mcp/workspace-tools.d.ts +1 -1
  153. package/dist/cli/mcp/workspace-tools.js +564 -0
  154. package/dist/cli/mcp-config.js +70 -0
  155. package/dist/cli/plugins.js +313 -0
  156. package/dist/cli/registry.js +23 -0
  157. package/dist/cli/reporters/stylish.js +329 -0
  158. package/dist/cli/version.js +15 -0
  159. package/dist/cli/watch.js +79 -0
  160. package/dist/codegen/bound-property-types.js +82 -0
  161. package/dist/codegen/coverage.js +119 -0
  162. package/dist/codegen/docs-file-markers.js +60 -0
  163. package/dist/codegen/docs-pages.js +115 -0
  164. package/dist/codegen/docs-rule-scanning.js +164 -0
  165. package/dist/codegen/docs-rules.js +76 -0
  166. package/dist/codegen/docs-sections.js +117 -0
  167. package/dist/codegen/docs-sidebar.js +65 -0
  168. package/dist/codegen/docs-types.js +4 -0
  169. package/dist/codegen/docs.js +356 -0
  170. package/dist/codegen/fetch.js +340 -0
  171. package/dist/codegen/generate-post-synth-barrel.js +63 -0
  172. package/dist/codegen/generate-registry.js +71 -0
  173. package/dist/codegen/generate-runtime-index.js +56 -0
  174. package/dist/codegen/generate-typescript.js +119 -0
  175. package/dist/codegen/generate.js +115 -0
  176. package/dist/codegen/json-patch.js +141 -0
  177. package/dist/codegen/json-schema-to-ts.js +344 -0
  178. package/dist/codegen/json-schema.js +246 -0
  179. package/dist/codegen/lexicon-regen.js +412 -0
  180. package/dist/codegen/naming.js +217 -0
  181. package/dist/codegen/okf-lexicon.js +245 -0
  182. package/dist/codegen/package.js +150 -0
  183. package/dist/codegen/pinned-upgrade.d.ts.map +1 -1
  184. package/dist/codegen/pinned-upgrade.js +494 -0
  185. package/dist/codegen/registry.js +60 -0
  186. package/dist/codegen/rehype-base-url.mjs +68 -0
  187. package/dist/codegen/rolling-upgrade.js +217 -0
  188. package/dist/codegen/surface-snapshot.js +537 -0
  189. package/dist/codegen/testdata/postgres-tags.json +242 -0
  190. package/dist/codegen/topo-sort.js +36 -0
  191. package/dist/codegen/typecheck.js +115 -0
  192. package/dist/codegen/validate.js +200 -0
  193. package/dist/codegen/version-bump.js +35 -0
  194. package/dist/components/auto-release.js +143 -0
  195. package/dist/components/builders.js +47 -0
  196. package/dist/components/capability-plugin-loader.js +175 -0
  197. package/dist/components/capability-plugin-schema.js +46 -0
  198. package/dist/components/capability-plugin.js +99 -0
  199. package/dist/components/capability.js +60 -0
  200. package/dist/components/changed-files.js +72 -0
  201. package/dist/components/cli-support.js +427 -0
  202. package/dist/components/component.js +120 -0
  203. package/dist/components/component.schema.json +271 -0
  204. package/dist/components/config-defaults.js +130 -0
  205. package/dist/components/deploy-units.js +60 -0
  206. package/dist/components/discover.d.ts.map +1 -1
  207. package/dist/components/discover.js +189 -0
  208. package/dist/components/driver-output.js +86 -0
  209. package/dist/components/driver.js +728 -0
  210. package/dist/components/fan-out-output.js +165 -0
  211. package/dist/components/fan-out-record.js +94 -0
  212. package/dist/components/fan-out-run.js +373 -0
  213. package/dist/components/fan-out-support.js +60 -0
  214. package/dist/components/fan-out.js +273 -0
  215. package/dist/components/gate-plan.js +41 -0
  216. package/dist/components/gated-wave-pipeline.js +46 -0
  217. package/dist/components/index.js +24 -0
  218. package/dist/components/layers.js +28 -0
  219. package/dist/components/manifest-persistence.js +108 -0
  220. package/dist/components/pilots/alb-ecs.pilot.js +59 -0
  221. package/dist/components/pilots/dynamodb.pilot.js +51 -0
  222. package/dist/components/pilots/jar-emr.pilot.js +65 -0
  223. package/dist/components/pilots/lambda.pilot.js +52 -0
  224. package/dist/components/pilots/neo4j-fanout.pilot.js +68 -0
  225. package/dist/components/pilots/project.js +12 -0
  226. package/dist/components/pr-pipeline.d.ts.map +1 -1
  227. package/dist/components/pr-pipeline.js +135 -0
  228. package/dist/components/pr-run.js +363 -0
  229. package/dist/components/presets/ecs-fargate.js +72 -0
  230. package/dist/components/presets/index.js +28 -0
  231. package/dist/components/presets/lambda.js +34 -0
  232. package/dist/components/presets/single-host-compose.js +41 -0
  233. package/dist/components/promote.js +549 -0
  234. package/dist/components/registry.js +34 -0
  235. package/dist/components/run-progress.js +33 -0
  236. package/dist/components/sandbox/driver.d.ts.map +1 -1
  237. package/dist/components/sandbox/driver.js +93 -0
  238. package/dist/components/sandbox/run.js +115 -0
  239. package/dist/components/starter-plugin.js +104 -0
  240. package/dist/components/verbs/__tests__/mock-cloud-executor.js +68 -0
  241. package/dist/components/verbs/__tests__/mock-process-runner.js +45 -0
  242. package/dist/components/verbs/__tests__/mock-sbom-generator.js +56 -0
  243. package/dist/components/verbs/bom-writer.js +287 -0
  244. package/dist/components/verbs/build-archive.js +188 -0
  245. package/dist/components/verbs/build.js +142 -0
  246. package/dist/components/verbs/cloud-executor.js +110 -0
  247. package/dist/components/verbs/component-bom.js +125 -0
  248. package/dist/components/verbs/ensure-secret.js +50 -0
  249. package/dist/components/verbs/index.js +61 -0
  250. package/dist/components/verbs/license-policy.js +75 -0
  251. package/dist/components/verbs/lockfile-sbom-generator.js +191 -0
  252. package/dist/components/verbs/process-runner.js +78 -0
  253. package/dist/components/verbs/r2-sync.js +93 -0
  254. package/dist/components/verbs/reproducibility.js +62 -0
  255. package/dist/components/verbs/run-agent.js +577 -0
  256. package/dist/components/verbs/sbom-generator.js +119 -0
  257. package/dist/components/verbs/sbom.js +97 -0
  258. package/dist/components/verbs/shell.js +32 -0
  259. package/dist/components/verbs/sign.js +221 -0
  260. package/dist/components/verbs/stub.js +28 -0
  261. package/dist/components/verbs/tool-sbom-generator.js +154 -0
  262. package/dist/components/verbs/verify.js +112 -0
  263. package/dist/components/verbs/vex.js +131 -0
  264. package/dist/components/verbs/vuln-gate.js +152 -0
  265. package/dist/components/verbs/vuln-scan.js +288 -0
  266. package/dist/components/verbs/wait-verify.js +106 -0
  267. package/dist/components/verbs/wrangler.js +179 -0
  268. package/dist/components/wave-plan.js +102 -0
  269. package/dist/composite.d.ts +10 -2
  270. package/dist/composite.d.ts.map +1 -1
  271. package/dist/composite.js +313 -0
  272. package/dist/config-import.d.ts.map +1 -1
  273. package/dist/config-import.js +22 -0
  274. package/dist/config-sandbox.js +122 -0
  275. package/dist/config-static.js +206 -0
  276. package/dist/config.js +605 -0
  277. package/dist/content-digest.js +23 -0
  278. package/dist/declarable.js +114 -0
  279. package/dist/deep-observation.js +437 -0
  280. package/dist/detectLexicon.js +54 -0
  281. package/dist/discovery/cache.js +70 -0
  282. package/dist/discovery/collect.d.ts +2 -1
  283. package/dist/discovery/collect.d.ts.map +1 -1
  284. package/dist/discovery/collect.js +223 -0
  285. package/dist/discovery/cycles.js +95 -0
  286. package/dist/discovery/entity-wire-codec.js +391 -0
  287. package/dist/discovery/entity-wire.js +42 -0
  288. package/dist/discovery/files.js +121 -0
  289. package/dist/discovery/fold-import.d.ts.map +1 -1
  290. package/dist/discovery/fold-import.js +4073 -0
  291. package/dist/discovery/fold-rank.js +292 -0
  292. package/dist/discovery/graph.js +115 -0
  293. package/dist/discovery/host-composite.d.ts +35 -0
  294. package/dist/discovery/host-composite.d.ts.map +1 -0
  295. package/dist/discovery/host-composite.js +93 -0
  296. package/dist/discovery/import.d.ts.map +1 -1
  297. package/dist/discovery/import.js +65 -0
  298. package/dist/discovery/index.d.ts +9 -0
  299. package/dist/discovery/index.d.ts.map +1 -1
  300. package/dist/discovery/index.js +333 -0
  301. package/dist/discovery/param-deps.js +487 -0
  302. package/dist/discovery/resolve.js +39 -0
  303. package/dist/discovery/sandbox/bundle.js +214 -0
  304. package/dist/discovery/sandbox/child-errors.js +26 -0
  305. package/dist/discovery/sandbox/config-run.js +100 -0
  306. package/dist/discovery/sandbox/config-wire.js +183 -0
  307. package/dist/discovery/sandbox/driver.d.ts.map +1 -1
  308. package/dist/discovery/sandbox/driver.js +333 -0
  309. package/dist/discovery/sandbox/fork.js +229 -0
  310. package/dist/discovery/sandbox/policy-run.js +142 -0
  311. package/dist/discovery/sandbox/policy-wire.js +152 -0
  312. package/dist/discovery/sandbox/run.js +77 -0
  313. package/dist/discovery/specifier-resolve.js +320 -0
  314. package/dist/discovery/walk.js +284 -0
  315. package/dist/effect-receipt.js +340 -0
  316. package/dist/env.js +55 -0
  317. package/dist/errors.js +62 -0
  318. package/dist/fold/fold.js +1434 -0
  319. package/dist/fold/foldable-helpers.js +229 -0
  320. package/dist/fold/subset.js +696 -0
  321. package/dist/fold-provenance.js +414 -0
  322. package/dist/gate-decision.d.ts +20 -9
  323. package/dist/gate-decision.d.ts.map +1 -1
  324. package/dist/gate-decision.js +313 -0
  325. package/dist/gate-resume-run.js +154 -0
  326. package/dist/gated-waves.js +165 -0
  327. package/dist/governance.js +43 -0
  328. package/dist/graph-declared.js +45 -0
  329. package/dist/graph-detail.js +207 -0
  330. package/dist/graph-dot.js +54 -0
  331. package/dist/graph-effective.js +107 -0
  332. package/dist/graph-ir.js +623 -0
  333. package/dist/graph-layout.js +184 -0
  334. package/dist/graph-lens.js +105 -0
  335. package/dist/graph-mermaid.js +83 -0
  336. package/dist/graph-ops.js +39 -0
  337. package/dist/graph-refs.js +156 -0
  338. package/dist/held-elsewhere.js +87 -0
  339. package/dist/identity.js +251 -0
  340. package/dist/import/base-parser.js +34 -0
  341. package/dist/import/embedded.js +255 -0
  342. package/dist/import/generator.js +1 -0
  343. package/dist/import/ir-utils.js +85 -0
  344. package/dist/import/parser-options.js +45 -0
  345. package/dist/import/parser.js +1 -0
  346. package/dist/index.js +118 -0
  347. package/dist/intrinsic-interpolation.js +73 -0
  348. package/dist/intrinsic.js +31 -0
  349. package/dist/join-key.js +35 -0
  350. package/dist/kubectl-context.js +150 -0
  351. package/dist/lexicon-config.js +58 -0
  352. package/dist/lexicon-integrity.js +47 -0
  353. package/dist/lexicon-manifest.js +70 -0
  354. package/dist/lexicon-module.d.ts.map +1 -1
  355. package/dist/lexicon-module.js +241 -0
  356. package/dist/lexicon-output.js +218 -0
  357. package/dist/lexicon-plugin-helpers.js +104 -0
  358. package/dist/lexicon-schema.js +136 -0
  359. package/dist/lexicon.js +130 -0
  360. package/dist/lifecycle/affected.js +224 -0
  361. package/dist/lifecycle/assert-live.js +110 -0
  362. package/dist/lifecycle/build-ledger-store.js +160 -0
  363. package/dist/lifecycle/build-ledger.js +155 -0
  364. package/dist/lifecycle/change-set.js +356 -0
  365. package/dist/lifecycle/converge-ledger.js +161 -0
  366. package/dist/lifecycle/deep-diff.js +233 -0
  367. package/dist/lifecycle/deep-observe.js +147 -0
  368. package/dist/lifecycle/digest.js +143 -0
  369. package/dist/lifecycle/disruption.js +135 -0
  370. package/dist/lifecycle/gate-applied.js +113 -0
  371. package/dist/lifecycle/gate-audit.d.ts +69 -2
  372. package/dist/lifecycle/gate-audit.d.ts.map +1 -1
  373. package/dist/lifecycle/gate-audit.js +415 -0
  374. package/dist/lifecycle/gate-ledger-select.js +89 -0
  375. package/dist/lifecycle/gate-ledger.d.ts +24 -0
  376. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  377. package/dist/lifecycle/gate-ledger.js +201 -0
  378. package/dist/lifecycle/gate-origin.js +117 -0
  379. package/dist/lifecycle/gate-pending.js +58 -0
  380. package/dist/lifecycle/git.js +1182 -0
  381. package/dist/lifecycle/identity.js +58 -0
  382. package/dist/lifecycle/index.js +26 -0
  383. package/dist/lifecycle/lease.js +283 -0
  384. package/dist/lifecycle/ledger-port.js +1 -0
  385. package/dist/lifecycle/legacy-digest.js +91 -0
  386. package/dist/lifecycle/live-diff.js +274 -0
  387. package/dist/lifecycle/local-note.js +15 -0
  388. package/dist/lifecycle/member-ledger.js +122 -0
  389. package/dist/lifecycle/observation-baseline.js +155 -0
  390. package/dist/lifecycle/observe.js +375 -0
  391. package/dist/lifecycle/oras-referrer-lookup.js +82 -0
  392. package/dist/lifecycle/override-ledger.js +54 -0
  393. package/dist/lifecycle/plan-digest.js +110 -0
  394. package/dist/lifecycle/plan-ledger.js +129 -0
  395. package/dist/lifecycle/receipt-plan.js +192 -0
  396. package/dist/lifecycle/release-ledger.js +155 -0
  397. package/dist/lifecycle/release-read.js +64 -0
  398. package/dist/lifecycle/replay.js +193 -0
  399. package/dist/lifecycle/rollback.js +102 -0
  400. package/dist/lifecycle/run-ledger.js +183 -0
  401. package/dist/lifecycle/scenario-eval.js +204 -0
  402. package/dist/lifecycle/scenario.js +214 -0
  403. package/dist/lifecycle/snapshot.js +239 -0
  404. package/dist/lifecycle/status.js +447 -0
  405. package/dist/lifecycle/symptoms.js +117 -0
  406. package/dist/lifecycle/teardown.js +255 -0
  407. package/dist/lifecycle/types.js +1 -0
  408. package/dist/lifecycle/unobserved-gate.js +33 -0
  409. package/dist/lifecycle/wave-plans.js +68 -0
  410. package/dist/lifecycle/work-item-id.js +36 -0
  411. package/dist/lifecycle/work-lease.js +393 -0
  412. package/dist/lint/component-checks.js +87 -0
  413. package/dist/lint/config.js +483 -0
  414. package/dist/lint/declarative.js +122 -0
  415. package/dist/lint/discover.d.ts.map +1 -1
  416. package/dist/lint/discover.js +138 -0
  417. package/dist/lint/engine.js +246 -0
  418. package/dist/lint/knowledge-checks.js +64 -0
  419. package/dist/lint/named-checks.js +22 -0
  420. package/dist/lint/output-checks.js +87 -0
  421. package/dist/lint/output-docs.js +163 -0
  422. package/dist/lint/parser.js +33 -0
  423. package/dist/lint/pipeline-change-gate.js +70 -0
  424. package/dist/lint/policy-import.d.ts +1 -1
  425. package/dist/lint/policy-import.d.ts.map +1 -1
  426. package/dist/lint/policy-import.js +62 -0
  427. package/dist/lint/policy-sandbox.js +86 -0
  428. package/dist/lint/policy.js +122 -0
  429. package/dist/lint/post-synth.js +87 -0
  430. package/dist/lint/presets/relaxed.json +26 -0
  431. package/dist/lint/presets/strict.json +24 -24
  432. package/dist/lint/receipt-checks.js +83 -0
  433. package/dist/lint/rule-loader.d.ts.map +1 -1
  434. package/dist/lint/rule-loader.js +89 -0
  435. package/dist/lint/rule-registry.js +86 -0
  436. package/dist/lint/rule.js +1 -0
  437. package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.js +7 -0
  438. package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.js +7 -0
  439. package/dist/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.js +9 -0
  440. package/dist/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.js +11 -0
  441. package/dist/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.js +9 -0
  442. package/dist/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.js +25 -0
  443. package/dist/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.js +8 -0
  444. package/dist/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.js +21 -0
  445. package/dist/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.js +8 -0
  446. package/dist/lint/rules/__fixtures__/comp/comp003/pass/agent-turn.component.js +24 -0
  447. package/dist/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.js +17 -0
  448. package/dist/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.js +8 -0
  449. package/dist/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.js +18 -0
  450. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.js +20 -0
  451. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.js +8 -0
  452. package/dist/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.js +12 -0
  453. package/dist/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.js +16 -0
  454. package/dist/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.js +8 -0
  455. package/dist/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.js +12 -0
  456. package/dist/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.js +11 -0
  457. package/dist/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.js +11 -0
  458. package/dist/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.js +10 -0
  459. package/dist/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.js +16 -0
  460. package/dist/lint/rules/comp/comp001-publishes-never-applies.js +69 -0
  461. package/dist/lint/rules/comp/comp002-dangling-wiring-ref.js +84 -0
  462. package/dist/lint/rules/comp/comp003-mutating-no-rollback.js +103 -0
  463. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.js +70 -0
  464. package/dist/lint/rules/comp/comp005-capability-kind-is-noun.js +109 -0
  465. package/dist/lint/rules/comp/comp006-shell-needs-reason.js +49 -0
  466. package/dist/lint/rules/comp/comp007-composition-sprawl.js +64 -0
  467. package/dist/lint/rules/comp/index.js +33 -0
  468. package/dist/lint/rules/comp/support.js +129 -0
  469. package/dist/lint/rules/composite-scope.js +51 -0
  470. package/dist/lint/rules/cor017-composite-name-match.js +93 -0
  471. package/dist/lint/rules/cor018-composite-prefer-lexicon-type.js +136 -0
  472. package/dist/lint/rules/cor021-env-literal-name.js +100 -0
  473. package/dist/lint/rules/cor022-receipt-leaf.js +118 -0
  474. package/dist/lint/rules/cor024-receipt-secret-pointer.js +199 -0
  475. package/dist/lint/rules/declarable-naming-convention.js +62 -0
  476. package/dist/lint/rules/evl001-non-literal-expression.js +66 -0
  477. package/dist/lint/rules/evl002-control-flow-resource.js +69 -0
  478. package/dist/lint/rules/evl003-dynamic-property-access.js +44 -0
  479. package/dist/lint/rules/evl004-spread-non-const.js +94 -0
  480. package/dist/lint/rules/evl005-resource-block-body.js +41 -0
  481. package/dist/lint/rules/evl007-invalid-siblings.js +105 -0
  482. package/dist/lint/rules/evl009-composite-no-constant.js +158 -0
  483. package/dist/lint/rules/evl010-composite-no-transform.js +59 -0
  484. package/dist/lint/rules/evl011-symbolic-in-template.js +106 -0
  485. package/dist/lint/rules/export-required.js +115 -0
  486. package/dist/lint/rules/file-declarable-limit.js +88 -0
  487. package/dist/lint/rules/flat-declarations.js +62 -0
  488. package/dist/lint/rules/index.js +90 -0
  489. package/dist/lint/rules/no-cyclic-declarable-ref.js +138 -0
  490. package/dist/lint/rules/no-redundant-type-import.js +76 -0
  491. package/dist/lint/rules/no-redundant-value-cast.js +41 -0
  492. package/dist/lint/rules/no-string-ref.js +59 -0
  493. package/dist/lint/rules/no-unused-declarable-import.js +75 -0
  494. package/dist/lint/rules/no-unused-declarable.js +142 -0
  495. package/dist/lint/rules/op/index.js +28 -0
  496. package/dist/lint/rules/op/ops012-activity-contract.js +54 -0
  497. package/dist/lint/rules/op/ops013-step-output-ref.js +88 -0
  498. package/dist/lint/rules/op/ops014-converge-rule-refusals.js +114 -0
  499. package/dist/lint/rules/op/ops015-gate-approval.js +45 -0
  500. package/dist/lint/rules/op/support.js +11 -0
  501. package/dist/lint/rules/op/sys010-key-over-plain-http.js +100 -0
  502. package/dist/lint/rules/property-kind.js +56 -0
  503. package/dist/lint/rules/single-concern-file.js +71 -0
  504. package/dist/lint/rules/sys001-no-literal-key.js +60 -0
  505. package/dist/lint/selectors.js +168 -0
  506. package/dist/lint/suppressions.js +129 -0
  507. package/dist/lint/typescript.js +17 -0
  508. package/dist/live-endpoint.js +113 -0
  509. package/dist/live-read-session.js +76 -0
  510. package/dist/lsp/lexicon-providers.js +163 -0
  511. package/dist/lsp/types.js +5 -0
  512. package/dist/managed-fields.js +293 -0
  513. package/dist/mcp/types.js +4 -0
  514. package/dist/notify-verify.js +0 -1
  515. package/dist/notify.js +0 -1
  516. package/dist/notify.schema.json +72 -0
  517. package/dist/observation.js +266 -0
  518. package/dist/okf-read.js +134 -0
  519. package/dist/okf.js +275 -0
  520. package/dist/op/__fixtures__/decide-stub-backend.js +125 -0
  521. package/dist/op/activities/activity-contracts.d.ts +1 -1
  522. package/dist/op/activities/activity-contracts.js +313 -0
  523. package/dist/op/activities/apply.js +582 -0
  524. package/dist/op/activities/build.js +18 -0
  525. package/dist/op/activities/change-coverage.js +40 -0
  526. package/dist/op/activities/change-set.d.ts +8 -3
  527. package/dist/op/activities/change-set.d.ts.map +1 -1
  528. package/dist/op/activities/change-set.js +67 -0
  529. package/dist/op/activities/converge.js +492 -0
  530. package/dist/op/activities/decide.js +211 -0
  531. package/dist/op/activities/env-teardown.js +110 -0
  532. package/dist/op/activities/factory.js +591 -0
  533. package/dist/op/activities/forge-pull-request.js +82 -0
  534. package/dist/op/activities/gh-host.js +78 -0
  535. package/dist/op/activities/guard-validate.js +165 -0
  536. package/dist/op/activities/http-check.js +40 -0
  537. package/dist/op/activities/index.js +59 -0
  538. package/dist/op/activities/lexicon-upgrade.js +629 -0
  539. package/dist/op/activities/lifecycle.js +109 -0
  540. package/dist/op/activities/pipeline-audit.js +147 -0
  541. package/dist/op/activities/policy.js +26 -0
  542. package/dist/op/activities/predict-behaviour.js +341 -0
  543. package/dist/op/activities/propose-upgrade.js +165 -0
  544. package/dist/op/activities/reconcile.d.ts +28 -16
  545. package/dist/op/activities/reconcile.d.ts.map +1 -1
  546. package/dist/op/activities/reconcile.js +1011 -0
  547. package/dist/op/activities/shell.js +118 -0
  548. package/dist/op/activities/source-release.js +97 -0
  549. package/dist/op/activities/source-rollback.js +165 -0
  550. package/dist/op/activities/teardown.js +17 -0
  551. package/dist/op/activities/util.js +6 -0
  552. package/dist/op/activities/wait.js +51 -0
  553. package/dist/op/activities/work-evidence.js +35 -0
  554. package/dist/op/activities/workflow-audit.js +133 -0
  555. package/dist/op/activity-contract-registry.js +106 -0
  556. package/dist/op/activity-contract.js +232 -0
  557. package/dist/op/activity-failure.js +31 -0
  558. package/dist/op/activity-profiles.js +129 -0
  559. package/dist/op/activity-registry.js +105 -0
  560. package/dist/op/activity-runtime.js +28 -0
  561. package/dist/op/builders.d.ts +1 -1
  562. package/dist/op/builders.d.ts.map +1 -1
  563. package/dist/op/builders.js +801 -0
  564. package/dist/op/change-signal.js +118 -0
  565. package/dist/op/composites/apply-op.js +151 -0
  566. package/dist/op/composites/behaviour-op.js +65 -0
  567. package/dist/op/composites/converge-op.js +141 -0
  568. package/dist/op/composites/index.js +19 -0
  569. package/dist/op/composites/lexicon-upgrade-op.js +107 -0
  570. package/dist/op/composites/pipeline-audit-op.js +50 -0
  571. package/dist/op/composites/reconcile-op.js +84 -0
  572. package/dist/op/composites/watch-op.js +69 -0
  573. package/dist/op/composites/workflow-audit-op.js +57 -0
  574. package/dist/op/converge-rule.js +205 -0
  575. package/dist/op/cron.js +146 -0
  576. package/dist/op/decide-backend.js +181 -0
  577. package/dist/op/decide-config.js +68 -0
  578. package/dist/op/decide-read-inputs.js +141 -0
  579. package/dist/op/discover.d.ts.map +1 -1
  580. package/dist/op/discover.js +213 -0
  581. package/dist/op/duration.js +21 -0
  582. package/dist/op/emulator-freshness.js +80 -0
  583. package/dist/op/emulator-lifecycle.js +269 -0
  584. package/dist/op/factory.js +83 -0
  585. package/dist/op/gate-approval.js +172 -0
  586. package/dist/op/gate-name.js +86 -0
  587. package/dist/op/gate-plan-context.js +167 -0
  588. package/dist/op/gate-point-run.js +67 -0
  589. package/dist/op/gate-point.js +111 -0
  590. package/dist/op/gate-resume-plan.js +155 -0
  591. package/dist/op/gate-resume.js +31 -0
  592. package/dist/op/gate-review.js +290 -0
  593. package/dist/op/gate-run-locator.js +85 -0
  594. package/dist/op/gate-summary.js +100 -0
  595. package/dist/op/gate-wait.js +56 -0
  596. package/dist/op/gate.js +449 -0
  597. package/dist/op/generate-pipeline.js +124 -0
  598. package/dist/op/index.js +51 -0
  599. package/dist/op/lifecycle-receipt-store.js +45 -0
  600. package/dist/op/local-executor.js +1164 -0
  601. package/dist/op/local-output.js +140 -0
  602. package/dist/op/op-ir.js +317 -0
  603. package/dist/op/op-verb-class.js +131 -0
  604. package/dist/op/op-waves-notify.js +136 -0
  605. package/dist/op/op-waves-run.d.ts +1 -1
  606. package/dist/op/op-waves-run.d.ts.map +1 -1
  607. package/dist/op/op-waves-run.js +1657 -0
  608. package/dist/op/op-waves.js +409 -0
  609. package/dist/op/operator.js +743 -0
  610. package/dist/op/receipt-store.js +94 -0
  611. package/dist/op/resource.js +23 -0
  612. package/dist/op/run-context.js +28 -0
  613. package/dist/op/run-live.js +256 -0
  614. package/dist/op/runtime.js +21 -0
  615. package/dist/op/runtimes/local.js +195 -0
  616. package/dist/op/source-archive.js +131 -0
  617. package/dist/op/step-output-ref.js +397 -0
  618. package/dist/op/steward-beside.js +169 -0
  619. package/dist/op/steward-points.js +138 -0
  620. package/dist/op/steward-turn.js +59 -0
  621. package/dist/op/steward.js +317 -0
  622. package/dist/op/types.js +25 -0
  623. package/dist/op/work-lease-decl.js +81 -0
  624. package/dist/op/work-lease-run.js +393 -0
  625. package/dist/override-gate.js +284 -0
  626. package/dist/owner-chain.js +74 -0
  627. package/dist/ownership.js +92 -0
  628. package/dist/params.js +61 -0
  629. package/dist/plan-summary.js +711 -0
  630. package/dist/point-decision.js +211 -0
  631. package/dist/pr-forge.js +810 -0
  632. package/dist/pr-loop.js +203 -0
  633. package/dist/project-codegen.js +191 -0
  634. package/dist/project-root.js +74 -0
  635. package/dist/project-validation.js +50 -0
  636. package/dist/provenance.js +157 -0
  637. package/dist/pseudo-parameter.js +40 -0
  638. package/dist/reconcile.js +450 -0
  639. package/dist/resource-attributes.js +33 -0
  640. package/dist/runtime-adapter.js +77 -0
  641. package/dist/runtime.js +66 -0
  642. package/dist/secret-materialization.js +153 -0
  643. package/dist/secret-provenance.js +250 -0
  644. package/dist/serializer-walker.js +112 -0
  645. package/dist/serializer.js +1 -0
  646. package/dist/sort.js +45 -0
  647. package/dist/stack-output.js +115 -0
  648. package/dist/telemetry-attribution.js +149 -0
  649. package/dist/terraform/__fixtures__/build-graph.js +63 -0
  650. package/dist/terraform/adopt-state.js +40 -0
  651. package/dist/terraform/aws-resources.js +384 -0
  652. package/dist/terraform/bridge.js +204 -0
  653. package/dist/terraform/carve-provider.js +155 -0
  654. package/dist/terraform/carve.js +138 -0
  655. package/dist/terraform/data-source-shape.js +57 -0
  656. package/dist/terraform/emit-source.js +36 -0
  657. package/dist/terraform/excise.js +123 -0
  658. package/dist/terraform/graduate.js +128 -0
  659. package/dist/terraform/graph.js +435 -0
  660. package/dist/terraform/hcl2json.js +60 -0
  661. package/dist/terraform/manifest.js +149 -0
  662. package/dist/terraform/parse.js +81 -0
  663. package/dist/terraform/providers/aws.js +146 -0
  664. package/dist/terraform/providers/gcp.js +294 -0
  665. package/dist/terraform/providers/index.js +17 -0
  666. package/dist/terraform/providers/kubernetes.js +253 -0
  667. package/dist/terraform/score.js +151 -0
  668. package/dist/terraform/state.js +67 -0
  669. package/dist/terraform/tier-map.js +74 -0
  670. package/dist/terraform/types.js +13 -0
  671. package/dist/terraform/unified-diff.js +132 -0
  672. package/dist/testing.js +295 -0
  673. package/dist/toml-emit.js +153 -0
  674. package/dist/toml-parse.js +355 -0
  675. package/dist/toml-utils.js +60 -0
  676. package/dist/toml.js +428 -0
  677. package/dist/ts-loader.d.ts +46 -0
  678. package/dist/ts-loader.d.ts.map +1 -0
  679. package/dist/ts-loader.js +103 -0
  680. package/dist/types.js +1 -0
  681. package/dist/utils.js +61 -0
  682. package/dist/validation.js +20 -0
  683. package/dist/vendor/js-yaml-load.js +1662 -0
  684. package/dist/workspace/__fixtures__/contract-repo.d.ts +7 -0
  685. package/dist/workspace/__fixtures__/contract-repo.d.ts.map +1 -1
  686. package/dist/workspace/__fixtures__/contract-repo.js +119 -0
  687. package/dist/workspace/__fixtures__/decide-workspace.js +112 -0
  688. package/dist/workspace/__fixtures__/sessions.d.ts +1 -1
  689. package/dist/workspace/__fixtures__/sessions.d.ts.map +1 -1
  690. package/dist/workspace/__fixtures__/sessions.js +91 -0
  691. package/dist/workspace/__fixtures__/two-member-workspace.js +34 -0
  692. package/dist/workspace/agent-cli.js +99 -0
  693. package/dist/workspace/agent.schema.json +390 -0
  694. package/dist/workspace/answers-ledger.js +89 -0
  695. package/dist/workspace/box-cli.js +142 -0
  696. package/dist/workspace/box-factory-write.js +196 -0
  697. package/dist/workspace/box-factory-write.schema.json +342 -0
  698. package/dist/workspace/box-factory.js +88 -0
  699. package/dist/workspace/box-intent.js +126 -0
  700. package/dist/workspace/box-isolation.js +169 -0
  701. package/dist/workspace/box-listing-write.schema.json +204 -0
  702. package/dist/workspace/box-listing.js +298 -0
  703. package/dist/workspace/box-publish.js +352 -0
  704. package/dist/workspace/box-publish.schema.json +498 -0
  705. package/dist/workspace/box-services.js +39 -0
  706. package/dist/workspace/broker-protocol.js +359 -0
  707. package/dist/workspace/broker-protocol.schema.json +228 -0
  708. package/dist/workspace/change-set.schema.json +462 -0
  709. package/dist/workspace/changes-cli.js +56 -0
  710. package/dist/workspace/changes.js +446 -0
  711. package/dist/workspace/changes.schema.json +642 -0
  712. package/dist/workspace/chant-migrations/chud-lexicon-exit-fly-site.js +198 -0
  713. package/dist/workspace/chant-migrations/chud-lexicon-exit-live-names.js +155 -0
  714. package/dist/workspace/chant-migrations/chud-lexicon-exit-rollback.js +214 -0
  715. package/dist/workspace/chant-migrations/chud-lexicon-exit-ship-inputs.js +180 -0
  716. package/dist/workspace/chant-migrations/chud-lexicon-exit-ship-policy.js +99 -0
  717. package/dist/workspace/chant-migrations/chud-lexicon-exit.js +847 -0
  718. package/dist/workspace/chant-migrations.js +113 -0
  719. package/dist/workspace/check.schema.json +433 -0
  720. package/dist/workspace/checks/box-isolation.js +62 -0
  721. package/dist/workspace/checks/boxes.js +491 -0
  722. package/dist/workspace/checks/diagrams.js +104 -0
  723. package/dist/workspace/checks/generated.js +419 -0
  724. package/dist/workspace/checks/ledgers.js +212 -0
  725. package/dist/workspace/checks/links.js +191 -0
  726. package/dist/workspace/checks/live.js +100 -0
  727. package/dist/workspace/checks/pipelines.js +188 -0
  728. package/dist/workspace/checks/records.js +169 -0
  729. package/dist/workspace/checks.js +426 -0
  730. package/dist/workspace/ci-green-cli.js +125 -0
  731. package/dist/workspace/ci-green-forge.js +83 -0
  732. package/dist/workspace/ci-green-workflow.d.ts +3 -1
  733. package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
  734. package/dist/workspace/ci-green-workflow.js +202 -0
  735. package/dist/workspace/ci-green.js +325 -0
  736. package/dist/workspace/ci-last-green.schema.json +158 -0
  737. package/dist/workspace/class-data.d.ts +84 -0
  738. package/dist/workspace/class-data.d.ts.map +1 -0
  739. package/dist/workspace/class-data.js +238 -0
  740. package/dist/workspace/compose-graph.js +235 -0
  741. package/dist/workspace/compose-reports.js +146 -0
  742. package/dist/workspace/composites.js +264 -0
  743. package/dist/workspace/composites.schema.json +617 -0
  744. package/dist/workspace/conformance/__fixture__/app/package.json +7 -0
  745. package/dist/workspace/conformance/__fixture__/app/src/server.mjs +29 -0
  746. package/dist/workspace/conformance/__fixture__/decisions/decision.kind.mjs +54 -0
  747. package/dist/workspace/conformance/__fixture__/decisions/decision.schema.json +512 -0
  748. package/dist/workspace/conformance/__fixture__/decisions/fix-001-how-the-app-is-deployed.md +40 -0
  749. package/dist/workspace/conformance/__fixture__/delivery/chant.config.ts +7 -0
  750. package/dist/workspace/conformance/__fixture__/delivery/lexicon/index.ts +26 -0
  751. package/dist/workspace/conformance/__fixture__/delivery/package.json +7 -0
  752. package/dist/workspace/conformance/__fixture__/delivery/src/app.component.ts +14 -0
  753. package/dist/workspace/conformance/__fixture__/delivery/src/app.ts +4 -0
  754. package/dist/workspace/conformance/__fixtures__/reference-broker.js +205 -0
  755. package/dist/workspace/conformance/__writer_fixture__/answers/answer.kind.mjs +32 -0
  756. package/dist/workspace/conformance/__writer_fixture__/answers/answer.schema.json +135 -0
  757. package/dist/workspace/conformance/__writer_fixture__/contracts/contract.kind.mjs +37 -0
  758. package/dist/workspace/conformance/__writer_fixture__/contracts/contract.schema.json +213 -0
  759. package/dist/workspace/conformance/__writer_fixture__/decisions/points.json +228 -0
  760. package/dist/workspace/conformance/__writer_fixture__/drivers/driver.kind.mjs +15 -0
  761. package/dist/workspace/conformance/__writer_fixture__/drivers/driver.schema.json +38 -0
  762. package/dist/workspace/conformance/__writer_fixture__/sessions/session.kind.mjs +54 -0
  763. package/dist/workspace/conformance/__writer_fixture__/sessions/session.schema.json +289 -0
  764. package/dist/workspace/conformance/__writer_fixture__/work/W-001-the-writer-suite-works-this-item.md +25 -0
  765. package/dist/workspace/conformance/__writer_fixture__/work/work.kind.mjs +60 -0
  766. package/dist/workspace/conformance/__writer_fixture__/work/work.schema.json +603 -0
  767. package/dist/workspace/conformance/broker.js +736 -0
  768. package/dist/workspace/conformance/index.js +673 -0
  769. package/dist/workspace/conformance/vitest.js +108 -0
  770. package/dist/workspace/conformance/writer.js +1080 -0
  771. package/dist/workspace/decide.js +879 -0
  772. package/dist/workspace/decision-points.schema.json +135 -135
  773. package/dist/workspace/declaration-write-cli.js +74 -0
  774. package/dist/workspace/declaration-write.js +238 -0
  775. package/dist/workspace/declaration.js +938 -0
  776. package/dist/workspace/declaration.schema.json +1413 -1413
  777. package/dist/workspace/declared-kinds.js +106 -0
  778. package/dist/workspace/environments.js +164 -0
  779. package/dist/workspace/evidence.schema.json +279 -0
  780. package/dist/workspace/export-cli.js +185 -0
  781. package/dist/workspace/export.js +499 -0
  782. package/dist/workspace/factory-rules.js +175 -0
  783. package/dist/workspace/generated-files.js +92 -0
  784. package/dist/workspace/glob.js +45 -0
  785. package/dist/workspace/graph-cache.js +352 -0
  786. package/dist/workspace/graph-cli.js +348 -0
  787. package/dist/workspace/graph.schema.json +1338 -0
  788. package/dist/workspace/identity-gate-rule.js +75 -0
  789. package/dist/workspace/identity.js +126 -0
  790. package/dist/workspace/import.js +283 -0
  791. package/dist/workspace/init.js +620 -0
  792. package/dist/workspace/intent-cli.js +263 -0
  793. package/dist/workspace/intent-joins.js +201 -0
  794. package/dist/workspace/intent-record.js +352 -0
  795. package/dist/workspace/intent-record.schema.json +864 -0
  796. package/dist/workspace/intent.js +1582 -0
  797. package/dist/workspace/intent.schema.json +2420 -0
  798. package/dist/workspace/json-edit.js +221 -0
  799. package/dist/workspace/jsonc.js +235 -0
  800. package/dist/workspace/kind-readers.js +103 -0
  801. package/dist/workspace/kinds.d.ts +3 -7
  802. package/dist/workspace/kinds.d.ts.map +1 -1
  803. package/dist/workspace/kinds.js +553 -0
  804. package/dist/workspace/lexicon-symbols.js +112 -0
  805. package/dist/workspace/lineage-adopt-cli.js +102 -0
  806. package/dist/workspace/lineage-adopt.js +360 -0
  807. package/dist/workspace/lineage-check.js +282 -0
  808. package/dist/workspace/lineage-cli.js +121 -0
  809. package/dist/workspace/lineage-hash-index.js +284 -0
  810. package/dist/workspace/lineage-init.js +507 -0
  811. package/dist/workspace/lineage-lock.js +387 -0
  812. package/dist/workspace/lineage-merge.js +45 -0
  813. package/dist/workspace/lineage-migrations.d.ts.map +1 -1
  814. package/dist/workspace/lineage-migrations.js +329 -0
  815. package/dist/workspace/lineage-provenance.js +36 -0
  816. package/dist/workspace/lineage-update.js +138 -0
  817. package/dist/workspace/lineage-upgrade-cli.js +131 -0
  818. package/dist/workspace/lineage-upgrade.js +889 -0
  819. package/dist/workspace/lineage-vendor.js +171 -0
  820. package/dist/workspace/lineage-version.js +128 -0
  821. package/dist/workspace/lineage-versions.js +275 -0
  822. package/dist/workspace/links.js +330 -0
  823. package/dist/workspace/ls-generated.js +95 -0
  824. package/dist/workspace/ls.js +277 -0
  825. package/dist/workspace/ls.schema.json +333 -0
  826. package/dist/workspace/member-commands.js +508 -0
  827. package/dist/workspace/member-handles.js +216 -0
  828. package/dist/workspace/member-pipeline.js +258 -0
  829. package/dist/workspace/member-run.js +117 -0
  830. package/dist/workspace/member-write.schema.json +193 -0
  831. package/dist/workspace/nested-graph.js +156 -0
  832. package/dist/workspace/nesting.js +38 -0
  833. package/dist/workspace/patch.js +301 -0
  834. package/dist/workspace/patch.schema.json +321 -0
  835. package/dist/workspace/pin-cli.js +55 -0
  836. package/dist/workspace/pin-integrity.js +100 -0
  837. package/dist/workspace/plan-summary.schema.json +155 -0
  838. package/dist/workspace/point-answer.schema.json +129 -129
  839. package/dist/workspace/points-cli.js +291 -0
  840. package/dist/workspace/points-write.schema.json +660 -0
  841. package/dist/workspace/points.js +521 -0
  842. package/dist/workspace/points.schema.json +916 -0
  843. package/dist/workspace/pr-report.schema.json +108 -0
  844. package/dist/workspace/principal-classes.d.ts +4 -11
  845. package/dist/workspace/principal-classes.d.ts.map +1 -1
  846. package/dist/workspace/principal-classes.js +162 -0
  847. package/dist/workspace/reason-codes.js +326 -0
  848. package/dist/workspace/record-assets.js +151 -0
  849. package/dist/workspace/record-decided.js +105 -0
  850. package/dist/workspace/record-sessions.js +96 -0
  851. package/dist/workspace/record-source.js +114 -0
  852. package/dist/workspace/records-amend.schema.json +284 -0
  853. package/dist/workspace/records-checkout.js +76 -0
  854. package/dist/workspace/records-cli.js +707 -0
  855. package/dist/workspace/records-close.js +116 -0
  856. package/dist/workspace/records-close.schema.json +278 -0
  857. package/dist/workspace/records-new.schema.json +202 -0
  858. package/dist/workspace/records-review.schema.json +367 -0
  859. package/dist/workspace/records-since.js +317 -0
  860. package/dist/workspace/records-since.schema.json +218 -0
  861. package/dist/workspace/records-write.js +1229 -0
  862. package/dist/workspace/records.js +1345 -0
  863. package/dist/workspace/records.schema.json +604 -0
  864. package/dist/workspace/reference-kinds/app/package.json +10 -0
  865. package/dist/workspace/reference-kinds/app/workspace-kinds.json +45 -0
  866. package/dist/workspace/returns.js +303 -0
  867. package/dist/workspace/root-refusal.js +75 -0
  868. package/dist/workspace/run-statement.schema.json +622 -0
  869. package/dist/workspace/runs-cli.js +584 -0
  870. package/dist/workspace/runs-write.schema.json +994 -0
  871. package/dist/workspace/runs.js +708 -0
  872. package/dist/workspace/runs.schema.json +1257 -0
  873. package/dist/workspace/runtimes.js +76 -0
  874. package/dist/workspace/session-kinds.js +83 -0
  875. package/dist/workspace/signers.schema.json +206 -0
  876. package/dist/workspace/source-block.js +125 -0
  877. package/dist/workspace/squash.js +177 -0
  878. package/dist/workspace/status-gates.js +162 -0
  879. package/dist/workspace/status-stewards.js +330 -0
  880. package/dist/workspace/status.js +514 -0
  881. package/dist/workspace/status.schema.json +998 -0
  882. package/dist/workspace/steward-index.js +191 -0
  883. package/dist/workspace/symbols.js +188 -0
  884. package/dist/workspace/template-manifest.js +227 -0
  885. package/dist/workspace/template-pins.js +115 -0
  886. package/dist/workspace/trailer-joins.js +65 -0
  887. package/dist/workspace/trailers.js +111 -0
  888. package/dist/workspace/tree.js +136 -0
  889. package/dist/workspace/trust/attestor.js +63 -0
  890. package/dist/workspace/trust/dsse.js +108 -0
  891. package/dist/workspace/trust/evidence-cli.js +175 -0
  892. package/dist/workspace/trust/evidence.js +161 -0
  893. package/dist/workspace/trust/gate-seal.js +226 -0
  894. package/dist/workspace/trust/policy.js +190 -0
  895. package/dist/workspace/trust/provenance.js +180 -0
  896. package/dist/workspace/trust/rotation.js +298 -0
  897. package/dist/workspace/trust/run-commits.js +101 -0
  898. package/dist/workspace/trust/run-statement.js +182 -0
  899. package/dist/workspace/trust/seal.js +272 -0
  900. package/dist/workspace/trust/signers-cli.js +152 -0
  901. package/dist/workspace/trust/ssh-commit.js +178 -0
  902. package/dist/workspace/trust/test-repo.js +118 -0
  903. package/dist/workspace/trust/trust-files.js +193 -0
  904. package/dist/workspace/trust/verify-cli.js +63 -0
  905. package/dist/workspace/trust/verify.js +192 -0
  906. package/dist/workspace/which-chant.js +141 -0
  907. package/dist/workspace/wip-cli.js +95 -0
  908. package/dist/workspace/wip-write.schema.json +504 -0
  909. package/dist/workspace/wip.js +631 -0
  910. package/dist/workspace/wip.schema.json +334 -0
  911. package/dist/workspace/work-cli.js +448 -0
  912. package/dist/workspace/work-evidence.js +122 -0
  913. package/dist/workspace/work-evidence.schema.json +222 -0
  914. package/dist/workspace/work-history.schema.json +421 -0
  915. package/dist/workspace/work-lease.schema.json +246 -0
  916. package/dist/workspace/work-size.js +77 -0
  917. package/dist/workspace/work.js +283 -0
  918. package/dist/workspace/workspace-kinds.schema.json +259 -259
  919. package/dist/workspace/workspace-principals.schema.json +53 -53
  920. package/dist/workspace/write-lock-cli.js +105 -0
  921. package/dist/workspace/write-lock.js +424 -0
  922. package/dist/workspace/write-lock.schema.json +172 -0
  923. package/dist/workspace/write-scope.js +484 -0
  924. package/dist/yaml.js +459 -0
  925. package/package.json +2 -2
  926. package/src/build.ts +8 -0
  927. package/src/change-set.test.ts +48 -0
  928. package/src/change-set.ts +52 -2
  929. package/src/ci-jobs.test.ts +49 -0
  930. package/src/ci-jobs.ts +515 -0
  931. package/src/cli/commands/check-lexicon-plugin.ts +2 -0
  932. package/src/cli/commands/lint.ts +3 -0
  933. package/src/cli/commands/migrate.ts +2 -0
  934. package/src/cli/compiled-cli.e2e.test.ts +165 -0
  935. package/src/cli/main.ts +121 -27
  936. package/src/cli/mcp/workspace-tools.ts +1 -1
  937. package/src/codegen/pinned-upgrade.ts +2 -0
  938. package/src/components/discover.ts +2 -0
  939. package/src/components/pr-pipeline.ts +3 -2
  940. package/src/components/sandbox/driver.ts +3 -1
  941. package/src/composite.ts +15 -3
  942. package/src/config-import.ts +3 -0
  943. package/src/discovery/collect.ts +15 -1
  944. package/src/discovery/fold-build-parity.test.ts +71 -0
  945. package/src/discovery/fold-import.ts +25 -127
  946. package/src/discovery/fold-project-provenance.test.ts +21 -4
  947. package/src/discovery/host-composite.ts +101 -0
  948. package/src/discovery/import.ts +2 -0
  949. package/src/discovery/index.ts +11 -1
  950. package/src/discovery/sandbox/driver.ts +3 -1
  951. package/src/gate-decision-bundle.test.ts +5 -4
  952. package/src/gate-decision-identity.test.ts +59 -6
  953. package/src/gate-decision.ts +81 -21
  954. package/src/lexicon-module.ts +3 -0
  955. package/src/lifecycle/gate-audit.test.ts +55 -1
  956. package/src/lifecycle/gate-audit.ts +116 -3
  957. package/src/lifecycle/gate-ledger.test.ts +20 -1
  958. package/src/lifecycle/gate-ledger.ts +33 -1
  959. package/src/lint/config.ts +1 -1
  960. package/src/lint/discover.ts +28 -8
  961. package/src/lint/policy-import.ts +4 -1
  962. package/src/lint/rule-loader.ts +2 -0
  963. package/src/op/activities/activity-contracts.ts +1 -1
  964. package/src/op/activities/change-set.ts +11 -3
  965. package/src/op/activities/lexicon-upgrade.test.ts +2 -0
  966. package/src/op/activities/reconcile.test.ts +62 -2
  967. package/src/op/activities/reconcile.ts +46 -22
  968. package/src/op/builders.ts +1 -1
  969. package/src/op/discover.ts +3 -0
  970. package/src/op/op-waves-run.ts +4 -3
  971. package/src/op/op-waves.test.ts +2 -0
  972. package/src/op/work-lease-run.test.ts +12 -4
  973. package/src/ts-loader.test.ts +23 -0
  974. package/src/ts-loader.ts +122 -0
  975. package/src/workspace/__fixtures__/contract-repo.ts +17 -1
  976. package/src/workspace/__fixtures__/sessions.ts +3 -3
  977. package/src/workspace/change-set.schema.json +5 -3
  978. package/src/workspace/chant-migrations/chud-lexicon-exit.ts +1 -1
  979. package/src/workspace/ci-green-workflow.test.ts +4 -4
  980. package/src/workspace/ci-green-workflow.ts +5 -2
  981. package/src/workspace/class-data.test.ts +64 -0
  982. package/src/workspace/class-data.ts +236 -0
  983. package/src/workspace/declaration.ts +1 -1
  984. package/src/workspace/kinds.ts +7 -36
  985. package/src/workspace/lineage-migrations.ts +2 -0
  986. package/src/workspace/points.ts +1 -1
  987. package/src/workspace/principal-classes.ts +12 -95
  988. package/src/workspace/records-formats.test.ts +7 -2
  989. package/src/workspace/records-sessions-write.test.ts +3 -3
  990. package/src/workspace/status-contract.e2e.test.ts +37 -0
  991. package/src/workspace/status-contract.test.ts +23 -21
@@ -0,0 +1,1434 @@
1
+ import * as ts from "typescript";
2
+ import { relative } from "node:path";
3
+ import { intrinsicCallFolds, intrinsicCallFoldsEagerly, intrinsicTagFolds } from "../lexicon.js";
4
+ import { SUPPORTED_BINARY_OPERATORS, SUPPORTED_UNARY_OPERATORS, UNSUPPORTED_OBJECT_MEMBER_MESSAGE, UNSUPPORTED_UNARY_MESSAGE, briefNodeText, callExpressionMessage, computedPropertyNameMessage, dynamicElementAccessMessage, isLiteralElementKey, isLiteralPropertyName, unsupportedBinaryMessage, unsupportedExpressionMessage, } from "./subset.js";
5
+ import { isFoldableHelperName } from "./foldable-helpers.js";
6
+ /**
7
+ * Symbolic reference produced when a property/element access resolves to an
8
+ * attribute of another `const`-declared resource in the same file, e.g.
9
+ * `bucket.name` (or `bucket["name"]`) where `bucket` is
10
+ * `const bucket = new S3Bucket({...})`.
11
+ *
12
+ * This is the SAME envelope `AttrRef.prototype.toJSON()` produces at
13
+ * runtime ({@link "../attrref"}) — `serializer-walker.ts`'s `walkValue`
14
+ * already recognizes a plain `{ __attrRef }` object as an AttrRef envelope
15
+ * (it doesn't require a live `AttrRef` instance), so this is not an
16
+ * invented shape: it's the existing envelope, produced without running the
17
+ * module that would otherwise construct the real `AttrRef`.
18
+ */
19
+ /**
20
+ * Which symbolic envelope a folded value is, in words a message can use — or
21
+ * `undefined` for a value that has an honest string form.
22
+ *
23
+ * These are the shapes `fold()` produces for things the build resolves later:
24
+ * a resource attribute, a lexicon intrinsic in either of its two forms, a
25
+ * registered authoring helper, a nested construction used as a value, and a
26
+ * composite `.step`. None of them can be concatenated into a string here,
27
+ * because what they stand for is not known until the build runs.
28
+ *
29
+ * Five of the six envelope kinds. `__symbol` is the sixth and is deliberately
30
+ * absent: it is produced only inside an intrinsic's interior and cannot reach
31
+ * a plain template span, so a case for it would be unreachable code claiming
32
+ * to guard something (#2397).
33
+ */
34
+ export function symbolicEnvelopeKind(value) {
35
+ if (typeof value !== "object" || value === null)
36
+ return undefined;
37
+ const v = value;
38
+ if ("__attrRef" in v) {
39
+ const ref = v.__attrRef;
40
+ const named = typeof ref?.entity === "string" && typeof ref?.attribute === "string"
41
+ ? ` (${ref.entity}.${ref.attribute})`
42
+ : "";
43
+ return `a resource attribute reference${named}`;
44
+ }
45
+ if ("__intrinsic" in v && typeof v.__intrinsic === "string")
46
+ return `the intrinsic \`${v.__intrinsic}\``;
47
+ if ("__helper" in v && typeof v.__helper === "string")
48
+ return `the helper \`${v.__helper}\``;
49
+ // A nested construction used as a value (#1169). The run path builds a real
50
+ // instance here, whose default `toString` is `"[object Object]"` too, so
51
+ // fold and run agreed and the differential stayed silent — the same shape
52
+ // as #2349 itself (#2397).
53
+ if ("__resource" in v && typeof v.__resource === "string")
54
+ return `a nested \`new ${v.__resource}\``;
55
+ // The `.step` idiom (#1174).
56
+ if ("__compositeStep" in v && typeof v.__compositeStep === "string") {
57
+ return `the composite step \`${v.__compositeStep}(…).step\``;
58
+ }
59
+ return undefined;
60
+ }
61
+ /**
62
+ * Error thrown when a node cannot be folded to a value without executing
63
+ * code. Carries the node's source position (1-based, matching `LintError`)
64
+ * so callers can report a located diagnostic, and the id of the EVL rule
65
+ * that flags the same construct (#1024) — "EVL001" (the general
66
+ * not-statically-evaluable umbrella) unless the rejection is specifically a
67
+ * dynamic element-access key, which is "EVL003"'s construct. A rejection
68
+ * with no EVL equivalent (unresolved identifier, unregistered intrinsic tag,
69
+ * spread of a value that turns out not to be an object/array — all
70
+ * environment/value-dependent, see {@link "./subset"}'s module doc) still
71
+ * defaults to "EVL001" since that's the closest umbrella rule, even though
72
+ * EVL can't actually detect it ahead of a real fold.
73
+ *
74
+ * chant #1020 hang fix — every `FoldError` is thrown for a routine, EXPECTED
75
+ * outcome (this node's shape isn't in the fold subset) and is ALWAYS caught
76
+ * a few frames up (`tryFoldFileCore`'s own top-level catch, ultimately),
77
+ * reduced to `.message`; `.stack` is never read anywhere on this path. V8
78
+ * still eagerly walks live JS frames to populate the (lazy) `.stack` getter's
79
+ * backing data at CONSTRUCTION time regardless of whether it's ever read —
80
+ * cheap for a shallow call stack, but expensive once the surrounding
81
+ * functions are hot enough for V8 to aggressively inline them (every corpus
82
+ * entry re-triggers the same call shapes across `foldFileMemoized` ->
83
+ * `buildExternals` -> `tryFoldFileCore` -> `resolveDeclaratorValue` ->
84
+ * `resolveLiveValue` -> `resolveCallExpression`/`fold`, chant #1020's
85
+ * cross-file resolution making that chain several layers deeper than the
86
+ * pre-#1020 single-file fold ever needed): capturing a stack from deep,
87
+ * optimized/inlined frames requires V8 to reconstruct them from deopt
88
+ * metadata, confirmed via `sample` to dominate CPU during the observed
89
+ * multi-minute stall (`Isolate::CaptureAndSetErrorStack` /
90
+ * `OptimizedJSFrame::Summarize` / `DeoptTranslationIterator`). Most files in
91
+ * the corpus (77/98 entries have at least one run-fallback file) throw one
92
+ * of these, so the cost compounds across a build. `Error.stackTraceLimit = 0`
93
+ * for the duration of `super()` makes V8 capture zero frames — free
94
+ * regardless of stack depth/optimization state — then the limit is restored
95
+ * immediately, so it doesn't suppress a real stack trace anywhere else in
96
+ * the process.
97
+ */
98
+ export class FoldError extends Error {
99
+ constructor(message, line, column, ruleId = "EVL001", refusedAtDepth = false) {
100
+ const prevStackTraceLimit = Error.stackTraceLimit;
101
+ Error.stackTraceLimit = 0;
102
+ super(`${line}:${column} - ${message}`);
103
+ Error.stackTraceLimit = prevStackTraceLimit;
104
+ this.name = "FoldError";
105
+ this.line = line;
106
+ this.column = column;
107
+ this.ruleId = ruleId;
108
+ this.refusedAtDepth = refusedAtDepth;
109
+ }
110
+ }
111
+ /**
112
+ * A project-local function `fold()` can CALL — chant #1373.
113
+ *
114
+ * Produced by ../discovery/fold-import.ts for every top-level function a
115
+ * project file declares (`export function f(...) {...}`, `export const f =
116
+ * (...) => ...`, and their non-exported siblings) and placed in the folding
117
+ * file's `externals` under the function's name, so a call through a bare
118
+ * identifier bound to one evaluates STATICALLY: the arguments fold in the
119
+ * caller's scope, the parameters are bound, and the body folds in the
120
+ * DEFINING module's scope (`consts`/`externals` here are that module's, not
121
+ * the caller's). Nothing is imported and nothing runs — this is the same
122
+ * "evaluate the source instead of the module" move #1023 makes for a
123
+ * composite factory body, applied to a plain function.
124
+ *
125
+ * Why this exists: the advice every chant project gets is to read build
126
+ * parameters through a small helper (`optionalAccountId(params.accountId)`)
127
+ * so defaulting and validation live in one place. Before #1373 a call to
128
+ * that helper was "a function call as a value" and unfoldable, and because
129
+ * fallback is per file and taint propagates along imports, ONE helper call
130
+ * at the top of a parameter file demoted every stack that imported it.
131
+ *
132
+ * The value is a marker, never a real function: a folded file's export
133
+ * namespace may carry one (an importer's `buildExternals` picks it up by
134
+ * name), and `fold()` refuses it anywhere a VALUE is expected — a function
135
+ * object cannot be serialized, and the run path's export namespace holds the
136
+ * real function the collector ignores, so ignoring the marker matches.
137
+ *
138
+ * Not a `FoldedValue`: it never appears inside a folded tree.
139
+ */
140
+ export class FoldableFunction {
141
+ constructor(
142
+ /** The binding name, for diagnostics. */
143
+ name, fn,
144
+ /** Absolute path of the defining module, for diagnostics. */
145
+ file,
146
+ /**
147
+ * The defining module's top-level `const` initializers, with every
148
+ * `new`-bound one already REMOVED — a body that mentions one reads the
149
+ * live instance out of `externals` instead (the same object the module's
150
+ * own fold registered), never a by-name `{__attrRef}` that would name an
151
+ * entity of the wrong file once revived in the caller.
152
+ */
153
+ consts,
154
+ /** The defining module's resolved imports, its own pre-built resources, and its own sibling functions. Read live, never copied, so a function declared before a const it reads still sees that const's value. */
155
+ externals,
156
+ /** Why an import of the defining module did NOT resolve, by local name — enriches an "unresolved identifier" inside the body. */
157
+ failures) {
158
+ this.name = name;
159
+ this.fn = fn;
160
+ this.file = file;
161
+ this.consts = consts;
162
+ this.externals = externals;
163
+ this.failures = failures;
164
+ /**
165
+ * Set once a call to this function has RETURNED a live object (a value
166
+ * with a prototype — a pre-built resource instance of the defining module,
167
+ * say) into a caller. The caller then shares that object's identity with
168
+ * the defining module exactly as an imported resource binding would, and
169
+ * fold-import.ts records the same `liveSources` edge for it so the two
170
+ * files fold or run together. A function that returns only plain data never
171
+ * sets this, which is what keeps a parameter helper from tainting anything.
172
+ */
173
+ this.leakedIdentity = false;
174
+ }
175
+ }
176
+ /** True when `value` (or anything inside it, through plain objects and arrays) carries a prototype other than Object/Array — i.e. is a live instance, not folded data. */
177
+ function carriesLiveObject(value, seen = new Set()) {
178
+ if (value === null || typeof value !== "object")
179
+ return typeof value === "function";
180
+ if (seen.has(value))
181
+ return false;
182
+ seen.add(value);
183
+ const proto = Object.getPrototypeOf(value);
184
+ if (proto !== Object.prototype && proto !== Array.prototype && proto !== null)
185
+ return true;
186
+ for (const inner of Object.values(value)) {
187
+ if (carriesLiveObject(inner, seen))
188
+ return true;
189
+ }
190
+ return false;
191
+ }
192
+ /**
193
+ * True when a module-level `const` is (transitively) bound to a `new Type(...)`.
194
+ * Follows an identifier chain (`const a = new T(); const b = a;`) so aliasing
195
+ * cannot smuggle a module-level resource into a function body.
196
+ *
197
+ * chant#2436 moved this here from ../discovery/fold-import.ts so the two places
198
+ * that build {@link FoldableFunction}s share one implementation rather than two
199
+ * that can drift.
200
+ */
201
+ export function constResolvesToResource(consts, name, seen = new Set()) {
202
+ if (seen.has(name))
203
+ return false;
204
+ seen.add(name);
205
+ const init = consts.get(name);
206
+ if (init === undefined)
207
+ return false;
208
+ if (ts.isNewExpression(init))
209
+ return true;
210
+ if (ts.isIdentifier(init))
211
+ return constResolvesToResource(consts, init.text, seen);
212
+ return false;
213
+ }
214
+ /** `const f = (…) => …`, through parentheses / `as` / `satisfies`. */
215
+ function unwrapFunctionInitializer(node) {
216
+ let current = node;
217
+ while (ts.isParenthesizedExpression(current) || ts.isAsExpression(current) || ts.isSatisfiesExpression(current)) {
218
+ current = current.expression;
219
+ }
220
+ return ts.isArrowFunction(current) || ts.isFunctionExpression(current) ? current : undefined;
221
+ }
222
+ /**
223
+ * Every top-level function a file declares, exported or not, as a
224
+ * {@link FoldableFunction}: `function f(...) {...}` and `const f = (...) => …`.
225
+ *
226
+ * The markers carry `externals` BY REFERENCE, so the caller may keep filling it
227
+ * after this returns (which is how a sibling function, or a resource built
228
+ * later, becomes reachable from a body).
229
+ *
230
+ * `consts` drops every `new`-bound const, transitively through aliases: a body
231
+ * that mentions one must read the live instance out of `externals`, the same
232
+ * object the module's own fold registered, never re-fold the initializer and
233
+ * construct a duplicate of a resource discovery already has.
234
+ *
235
+ * chant#2436 — one implementation, called both by ../discovery/fold-import.ts
236
+ * during a build and by {@link fold} when a unit-level fold has no externals of
237
+ * its own. Getting the `new`-bound stripping wrong yields a wrong value rather
238
+ * than a fallback to run, which is why there is only one copy of it.
239
+ */
240
+ export function collectSameFileFunctions(sourceFile, consts, file, externals, failures) {
241
+ const bodyConsts = new Map(consts);
242
+ for (const [name] of [...bodyConsts]) {
243
+ if (constResolvesToResource(consts, name, new Set()))
244
+ bodyConsts.delete(name);
245
+ }
246
+ const functions = new Map();
247
+ const add = (name, fn) => {
248
+ functions.set(name, new FoldableFunction(name, fn, file, bodyConsts, externals, failures));
249
+ };
250
+ for (const statement of sourceFile.statements) {
251
+ if (ts.isFunctionDeclaration(statement)) {
252
+ if (statement.name && statement.body)
253
+ add(statement.name.text, statement);
254
+ continue;
255
+ }
256
+ if (!ts.isVariableStatement(statement))
257
+ continue;
258
+ if ((statement.declarationList.flags & ts.NodeFlags.Const) === 0)
259
+ continue;
260
+ for (const decl of statement.declarationList.declarations) {
261
+ if (!ts.isIdentifier(decl.name) || !decl.initializer)
262
+ continue;
263
+ const fn = unwrapFunctionInitializer(decl.initializer);
264
+ if (fn)
265
+ add(decl.name.text, fn);
266
+ }
267
+ }
268
+ return functions;
269
+ }
270
+ /**
271
+ * The same-file functions in scope at `node`, for a fold with no `externals`.
272
+ *
273
+ * Memoized per (source file, consts map), both of which are objects the caller
274
+ * holds for the duration of a fold, so a file with many calls walks its
275
+ * statements once. `undefined` when the node has no file to read, which is the
276
+ * pre-#2436 answer: the call is not foldable.
277
+ *
278
+ * The map is its own `externals`, so a function can call a sibling.
279
+ */
280
+ function sameFileFunctions(node, consts) {
281
+ let sourceFile;
282
+ try {
283
+ sourceFile = node.getSourceFile();
284
+ }
285
+ catch {
286
+ return undefined;
287
+ }
288
+ if (!sourceFile)
289
+ return undefined;
290
+ let byConsts = sameFileFunctionCache.get(sourceFile);
291
+ if (!byConsts) {
292
+ byConsts = new WeakMap();
293
+ sameFileFunctionCache.set(sourceFile, byConsts);
294
+ }
295
+ const cached = byConsts.get(consts);
296
+ if (cached)
297
+ return cached;
298
+ const scope = new Map();
299
+ const functions = collectSameFileFunctions(sourceFile, consts, sourceFile.fileName, scope);
300
+ for (const [name, fn] of functions)
301
+ scope.set(name, fn);
302
+ byConsts.set(consts, functions);
303
+ return functions;
304
+ }
305
+ const sameFileFunctionCache = new WeakMap();
306
+ export function isFoldableFunction(value) {
307
+ return value instanceof FoldableFunction;
308
+ }
309
+ /** A binding element a folded function can bind plainly: `{ a }` / `{ a: b }`, no rest, default, or nested pattern. */
310
+ function plainBindingKey(el) {
311
+ if (el.dotDotDotToken || el.initializer || !ts.isIdentifier(el.name))
312
+ return undefined;
313
+ const key = el.propertyName ?? el.name;
314
+ if (ts.isIdentifier(key) || ts.isStringLiteral(key) || ts.isNumericLiteral(key))
315
+ return key.text;
316
+ return undefined;
317
+ }
318
+ /**
319
+ * The SHAPE half of what makes a project-local function foldable (chant
320
+ * #1373) — a reason string, or `undefined` when the function is admissible.
321
+ * Deliberately the same statement-level contract #1023 gives a composite
322
+ * factory body: parameters bound plainly (an identifier, optionally
323
+ * defaulted, or a flat object pattern), and a body that is either a single
324
+ * expression or `const` declarations followed by one `return`. Every
325
+ * expression inside is then folded by {@link fold} itself, so the expression
326
+ * subset is defined exactly once — with the additions {@link fold} refuses
327
+ * INSIDE a function body (a `new`, a tagged template, a registered helper or
328
+ * intrinsic call), because each of those reduces to an envelope revived
329
+ * against the CALLER's imports, which are not the scope the body was written
330
+ * in.
331
+ */
332
+ export function findFunctionSubsetViolation(fn) {
333
+ if (fn.asteriskToken)
334
+ return "a generator function is not foldable";
335
+ if (fn.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword))
336
+ return "an async function is not foldable";
337
+ if (!fn.body)
338
+ return "a function without a body (an overload signature) is not foldable";
339
+ for (const param of fn.parameters) {
340
+ if (param.dotDotDotToken)
341
+ return "a rest parameter is not foldable";
342
+ if (ts.isIdentifier(param.name))
343
+ continue;
344
+ if (ts.isObjectBindingPattern(param.name)) {
345
+ for (const el of param.name.elements) {
346
+ if (plainBindingKey(el) === undefined) {
347
+ return "a destructured parameter with a rest, default, or nested element is not foldable";
348
+ }
349
+ }
350
+ continue;
351
+ }
352
+ return "an array-destructured parameter is not foldable";
353
+ }
354
+ if (!ts.isBlock(fn.body))
355
+ return undefined;
356
+ const statements = fn.body.statements;
357
+ for (let i = 0; i < statements.length; i += 1) {
358
+ const statement = statements[i];
359
+ const last = i === statements.length - 1;
360
+ if (ts.isReturnStatement(statement)) {
361
+ if (!last)
362
+ return "an early `return` is not foldable";
363
+ continue;
364
+ }
365
+ if (!ts.isVariableStatement(statement)) {
366
+ return `\`${ts.SyntaxKind[statement.kind]}\` in a function body is not foldable — only \`const\` declarations and a final \`return\` are`;
367
+ }
368
+ if ((statement.declarationList.flags & ts.NodeFlags.Const) === 0) {
369
+ return "`let`/`var` in a function body is not foldable";
370
+ }
371
+ for (const decl of statement.declarationList.declarations) {
372
+ if (!decl.initializer)
373
+ return "an uninitialized `const` in a function body is not foldable";
374
+ if (ts.isIdentifier(decl.name))
375
+ continue;
376
+ if (ts.isObjectBindingPattern(decl.name)) {
377
+ for (const el of decl.name.elements) {
378
+ if (plainBindingKey(el) === undefined) {
379
+ return "a destructured `const` with a rest, default, or nested element is not foldable";
380
+ }
381
+ }
382
+ continue;
383
+ }
384
+ return "an array-destructured `const` in a function body is not foldable";
385
+ }
386
+ }
387
+ return undefined;
388
+ }
389
+ /**
390
+ * How many project-local function bodies are being folded around the current
391
+ * `fold()` call — 0 at a file's own top level. Two jobs: terminate a function
392
+ * that (directly or through another) calls itself, which has no fixpoint and
393
+ * no file boundary for fold-import's cycle detection to notice; and tell the
394
+ * envelope-producing branches of {@link fold} that they are inside a body,
395
+ * where an envelope must not be produced (see {@link findFunctionSubsetViolation}).
396
+ */
397
+ let functionBodyDepth = 0;
398
+ const MAX_FUNCTION_CALL_DEPTH = 32;
399
+ function insideFunctionBody(node, what) {
400
+ if (functionBodyDepth === 0)
401
+ return undefined;
402
+ return foldError(node, `${what} inside a folded function body is not foldable`, "EVL001", true);
403
+ }
404
+ function fileLabel(file) {
405
+ const rel = relative(process.cwd(), file);
406
+ return rel.startsWith("..") ? file : rel;
407
+ }
408
+ /**
409
+ * Evaluate a call to a project-local function (chant #1373) — see
410
+ * {@link FoldableFunction}. Arguments fold in the caller's scope (`consts`/
411
+ * `externals`); the body folds in the callee's, with the parameters bound on
412
+ * top. Any failure inside the body is re-thrown at the CALL site, naming the
413
+ * callee, its file and the position inside it, and the reason — so the
414
+ * `[fold:run]` line for the importing file says which helper to fix and why,
415
+ * rather than the bare "function call as a value" it said before.
416
+ */
417
+ function callFoldableFunction(callee, node, consts, intrinsics, externals) {
418
+ const label = `call to "${callee.name}" (${fileLabel(callee.file)})`;
419
+ const violation = findFunctionSubsetViolation(callee.fn);
420
+ if (violation)
421
+ throw foldError(node, `${label} is not foldable: ${violation}`);
422
+ if (functionBodyDepth >= MAX_FUNCTION_CALL_DEPTH) {
423
+ throw foldError(node, `${label} is not foldable: call depth exceeded — is it recursive?`);
424
+ }
425
+ const args = [];
426
+ for (const arg of node.arguments) {
427
+ if (ts.isSpreadElement(arg))
428
+ throw foldError(arg, `${label} is not foldable: a spread argument is not foldable`);
429
+ args.push(fold(arg, consts, intrinsics, externals));
430
+ }
431
+ const bodyConsts = new Map(callee.consts);
432
+ const bodyExternals = new Map(callee.externals);
433
+ const bind = (name, value) => {
434
+ // A parameter or body binding SHADOWS a module-level const of the same
435
+ // name — `fold()` consults `consts` before `externals`.
436
+ bodyConsts.delete(name);
437
+ bodyExternals.set(name, value);
438
+ };
439
+ const destructure = (pattern, value) => {
440
+ if (value === null || typeof value !== "object") {
441
+ throw foldError(pattern, `destructured source in \`${briefNodeText(pattern)}\` is not an object`);
442
+ }
443
+ for (const el of pattern.elements) {
444
+ bind(el.name.text, value[plainBindingKey(el)]);
445
+ }
446
+ };
447
+ functionBodyDepth += 1;
448
+ try {
449
+ const result = evaluateFunctionBody(callee, args, bodyConsts, bodyExternals, intrinsics, bind, destructure);
450
+ // Live objects that ARRIVED through the arguments are the caller's own
451
+ // already; only one the body produced from its module's scope is new.
452
+ if (!callee.leakedIdentity && carriesLiveObject(result) && !args.some((arg) => carriesLiveObject(arg))) {
453
+ callee.leakedIdentity = true;
454
+ }
455
+ return result;
456
+ }
457
+ catch (err) {
458
+ if (!(err instanceof FoldError))
459
+ throw err;
460
+ // The inner message is positioned inside the CALLEE file. Strip that
461
+ // prefix and re-anchor at the call site: callee, its file and position,
462
+ // then the reason.
463
+ const prefix = `${err.line}:${err.column} - `;
464
+ const inner = err.message.startsWith(prefix) ? err.message.slice(prefix.length) : err.message;
465
+ let reason = inner;
466
+ const unresolved = /^unresolved identifier: (\w+)$/.exec(inner);
467
+ if (unresolved && callee.failures?.has(unresolved[1])) {
468
+ reason = `${inner} (${callee.failures.get(unresolved[1])})`;
469
+ }
470
+ throw foldError(node, `${label} is not foldable: ${fileLabel(callee.file)}:${err.line}:${err.column} - ${reason}`, err.ruleId,
471
+ // chant#2441 — the refusal happened inside the callee's body and this
472
+ // frame is the CALL site, so without carrying the flag the caller sees
473
+ // an ordinary failure and falls back to invoking.
474
+ err.refusedAtDepth);
475
+ }
476
+ finally {
477
+ functionBodyDepth -= 1;
478
+ }
479
+ }
480
+ function evaluateFunctionBody(callee, args, bodyConsts, bodyExternals, intrinsics, bind, destructure) {
481
+ callee.fn.parameters.forEach((param, i) => {
482
+ let value = args[i];
483
+ if (value === undefined && param.initializer) {
484
+ value = fold(param.initializer, bodyConsts, intrinsics, bodyExternals);
485
+ }
486
+ if (ts.isIdentifier(param.name))
487
+ bind(param.name.text, value);
488
+ else
489
+ destructure(param.name, value);
490
+ });
491
+ const body = callee.fn.body;
492
+ if (!ts.isBlock(body))
493
+ return fold(body, bodyConsts, intrinsics, bodyExternals);
494
+ for (const statement of body.statements) {
495
+ if (ts.isReturnStatement(statement)) {
496
+ return statement.expression ? fold(statement.expression, bodyConsts, intrinsics, bodyExternals) : undefined;
497
+ }
498
+ for (const decl of statement.declarationList.declarations) {
499
+ const value = fold(decl.initializer, bodyConsts, intrinsics, bodyExternals);
500
+ if (ts.isIdentifier(decl.name))
501
+ bind(decl.name.text, value);
502
+ else
503
+ destructure(decl.name, value);
504
+ }
505
+ }
506
+ // A block body with no `return` evaluates to `undefined`, as it would run.
507
+ return undefined;
508
+ }
509
+ /**
510
+ * Resolve a node's 1-based line/column via its owning `SourceFile`. Exported
511
+ * (chant #1020) so fold-import.ts can build its own located `FoldError`s
512
+ * (e.g. an import-cycle diagnostic pointing at the specific `import`
513
+ * statement that closes the cycle) using the exact same position math
514
+ * `foldError` uses here, rather than a second hand-rolled implementation.
515
+ */
516
+ export function locate(node) {
517
+ const sourceFile = node.getSourceFile();
518
+ const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
519
+ return { line: line + 1, column: character + 1 };
520
+ }
521
+ function foldError(node, message, ruleId = "EVL001", refusedAtDepth = false) {
522
+ const { line, column } = locate(node);
523
+ return new FoldError(message, line, column, ruleId, refusedAtDepth);
524
+ }
525
+ /**
526
+ * Collect every top-level `const x = <initializer>` in a source file into a
527
+ * name -> initializer map. Single-file only (cross-file is #1020).
528
+ */
529
+ export function collectConsts(sourceFile) {
530
+ const consts = new Map();
531
+ for (const statement of sourceFile.statements) {
532
+ if (!ts.isVariableStatement(statement))
533
+ continue;
534
+ if ((statement.declarationList.flags & ts.NodeFlags.Const) === 0)
535
+ continue;
536
+ for (const decl of statement.declarationList.declarations) {
537
+ if (ts.isIdentifier(decl.name) && decl.initializer) {
538
+ consts.set(decl.name.text, decl.initializer);
539
+ }
540
+ }
541
+ }
542
+ return consts;
543
+ }
544
+ /**
545
+ * A property/element key foldable without execution: identifier, string, or
546
+ * numeric literal.
547
+ *
548
+ * Exported for chant #1023's composite-factory interpreter
549
+ * (../discovery/fold-import.ts), which walks object literals itself — a
550
+ * factory body may construct a resource inside one, which {@link fold} has no
551
+ * case for — and must reject a computed key with the identical message
552
+ * {@link fold} would, rather than growing a second, silently divergent copy of
553
+ * this rule.
554
+ */
555
+ export function propName(node) {
556
+ if (isLiteralPropertyName(node))
557
+ return node.text;
558
+ throw foldError(node, computedPropertyNameMessage(node));
559
+ }
560
+ /**
561
+ * An element-access key foldable without execution: a string or numeric
562
+ * LITERAL only (EVL003 semantics — a variable or expression key is a
563
+ * dynamic key and is rejected).
564
+ */
565
+ function elementKey(node) {
566
+ if (isLiteralElementKey(node))
567
+ return node.text;
568
+ throw foldError(node, dynamicElementAccessMessage(node), "EVL003");
569
+ }
570
+ /** True when `ident` is a `const` bound to a `new Type(...)` resource constructor. */
571
+ function resolvesToResource(consts, ident) {
572
+ const init = consts.get(ident.text);
573
+ return init !== undefined && ts.isNewExpression(init);
574
+ }
575
+ /**
576
+ * True when `node` is a call through a bare identifier that isn't ALREADY
577
+ * one of `fold()`'s other three call shapes — a registered authoring helper,
578
+ * a registered call-form intrinsic, or a project-local {@link FoldableFunction}
579
+ * — i.e. exactly the callee the `CallExpression` branch below would
580
+ * otherwise throw {@link callExpressionMessage} for. Used only by the
581
+ * `.step` narrowing in the property-access branch (chant #1174,
582
+ * {@link FoldedCompositeStepCall}): checked from the OUTSIDE, at the
583
+ * property-access node, so `Checkout({...})` alone (no `.step`) still falls
584
+ * through to the ordinary `CallExpression` throw, unchanged.
585
+ */
586
+ function isUnclaimedBareCall(node, consts, intrinsics, externals) {
587
+ if (!ts.isCallExpression(node) || !ts.isIdentifier(node.expression))
588
+ return false;
589
+ const name = node.expression.text;
590
+ if (consts.has(name))
591
+ return false;
592
+ if (isFoldableHelperName(name))
593
+ return false;
594
+ if (intrinsics.some((i) => i.name === name && intrinsicCallFolds(i)))
595
+ return false;
596
+ if (isFoldableFunction(externals?.get(name)))
597
+ return false;
598
+ return true;
599
+ }
600
+ /** True when a folded value is a {@link FoldedResource} envelope (a `new Type(...)` that nothing constructed yet). */
601
+ function isFoldedResource(value) {
602
+ return typeof value === "object" && value !== null && !Array.isArray(value) && "__resource" in value;
603
+ }
604
+ /**
605
+ * True when `value` is one of `fold()`'s own symbolic envelope shapes — a
606
+ * stand-in for a value nothing has constructed or revived yet, not the value
607
+ * itself. A method call (see the `CallExpression` branch's property-access
608
+ * case below) must refuse one rather than silently falling through to
609
+ * `Object.prototype`'s own inherited methods — `toString` chief among them —
610
+ * which would answer with the placeholder's shape instead of what the real,
611
+ * eventually-revived value would produce.
612
+ */
613
+ function isFoldSymbolicEnvelope(value) {
614
+ if (typeof value !== "object" || value === null || Array.isArray(value))
615
+ return false;
616
+ return ("__attrRef" in value ||
617
+ "__intrinsic" in value ||
618
+ "__helper" in value ||
619
+ "__resource" in value ||
620
+ "__compositeStep" in value);
621
+ }
622
+ /**
623
+ * chant #1535 — an attribute read whose object folded to a resource ENVELOPE
624
+ * rather than resolving through {@link resolvesToResource}. That happens when
625
+ * the const's initializer is not a bare `new` but an expression that yields
626
+ * one: `const provider = flag ? new OIDCProvider({...}) : undefined;` then
627
+ * `provider.Arn`. Indexing the envelope (`{__resource, props}`) by the
628
+ * attribute name returns `undefined`, and the property vanished from the
629
+ * output without a word — a trust policy built with `Principal: { Federated:
630
+ * provider.Arn }` landed in CloudFormation as `Principal: {}`.
631
+ *
632
+ * When the object is a plain identifier, the answer is the same symbolic
633
+ * `{__attrRef}` the bare-`new` case produces — the serializer resolves it by
634
+ * the const's name, exactly as it would have for `const provider = new
635
+ * OIDCProvider({...})`. Any other expression shape has no name to key the
636
+ * ref on, so it refuses and the file falls back to run rather than emitting
637
+ * something wrong.
638
+ */
639
+ function attrRefOnFoldedResource(node, attribute) {
640
+ if (ts.isIdentifier(node.expression)) {
641
+ return { __attrRef: { entity: node.expression.text, attribute } };
642
+ }
643
+ throw foldError(node, `attribute "${attribute}" read on an inline resource expression is not foldable — bind the resource to a const first (falls back to run)`);
644
+ }
645
+ /**
646
+ * chant #2328 — the marker an optional-chain link leaves behind when it
647
+ * short-circuits, carried up the rest of the chain and unwrapped to
648
+ * `undefined` at its end.
649
+ *
650
+ * `a?.b` on a nullish `a` is DEFINED to be `undefined` in JavaScript, and so
651
+ * is every link after it: `a?.b.c` is `undefined` too, not a `TypeError` on
652
+ * `undefined.c`. A non-optional `a.b` on a nullish `a` throws. Both shapes
653
+ * reach the property-access branch below with the same nullish object, so
654
+ * telling them apart needs the answer to "did an EARLIER link short-circuit?"
655
+ * — which a plain `undefined` return cannot carry, because a genuine
656
+ * `undefined` looks identical: `({}).b.c` is `undefined` at the first link
657
+ * and running it DOES throw at the second.
658
+ *
659
+ * This marker carries it. {@link shortCircuited} produces it only where
660
+ * {@link continuesOptionalChain} says the parent node is the next link of the
661
+ * same chain, so the parent always consumes it, and turns it back into
662
+ * `undefined` at the last link — which is where JavaScript's own
663
+ * short-circuit lands. It never escapes {@link fold}'s return to a caller.
664
+ */
665
+ const CHAIN_SHORT_CIRCUIT = Symbol("chant.fold.optional-chain-short-circuit");
666
+ /** True when `value` is the {@link CHAIN_SHORT_CIRCUIT} marker. */
667
+ function isChainShortCircuit(value) {
668
+ return value === CHAIN_SHORT_CIRCUIT;
669
+ }
670
+ /**
671
+ * The value a chain that short-circuited at or before `node` has AT `node`:
672
+ * the {@link CHAIN_SHORT_CIRCUIT} marker while another link follows,
673
+ * `undefined` once `node` is the last one.
674
+ */
675
+ function shortCircuited(node) {
676
+ return continuesOptionalChain(node) ? CHAIN_SHORT_CIRCUIT : undefined;
677
+ }
678
+ /**
679
+ * True when `node`'s parent is the next link of the SAME optional chain, so a
680
+ * short-circuit at `node` must keep travelling rather than becoming
681
+ * `undefined` here.
682
+ *
683
+ * TypeScript flags every access/call node after a `?.` as part of that chain
684
+ * and stops flagging at the first construct that ends it, so this needs no
685
+ * bookkeeping of its own: `(a?.b).c` — where the parentheses end the chain
686
+ * and running really does throw on `.c` — is not a continuation, and neither
687
+ * is `(a?.b as X).c`. A `NonNullChain` (`a?.b!.c`) is transparent, exactly as
688
+ * {@link fold}'s own non-null unwrapping is.
689
+ */
690
+ function continuesOptionalChain(node) {
691
+ const parent = node.parent;
692
+ if (parent === undefined)
693
+ return false;
694
+ if (ts.isNonNullExpression(parent) && ts.isOptionalChain(parent))
695
+ return continuesOptionalChain(parent);
696
+ return ((ts.isPropertyAccessExpression(parent) || ts.isElementAccessExpression(parent) || ts.isCallExpression(parent)) &&
697
+ parent.expression === node &&
698
+ ts.isOptionalChain(parent));
699
+ }
700
+ /**
701
+ * chant #2328 — a property or element read whose object folded to `null` or
702
+ * `undefined`. Folding it to `undefined` (what both branches did from #1026
703
+ * until now) drops the property from the output and lets the build carry on,
704
+ * while RUNNING the same expression throws `TypeError: Cannot read properties
705
+ * of undefined` — the fold/run disagreement #1535 already ruled unacceptable
706
+ * one branch over, where an attribute read on a resource envelope folded away
707
+ * and a trust policy shipped as `Principal: {}`.
708
+ *
709
+ * So it refuses, and the file falls back to run — where the real `TypeError`
710
+ * happens at the line that caused it, naming the property the way it would
711
+ * without `--fold` at all. The usual cause is a typo in a nested path
712
+ * (`cfg.nett.vpcId`); a genuinely optional read says so with `?.`, which
713
+ * short-circuits above instead of reaching this message.
714
+ */
715
+ function nullishAccessMessage(member, obj) {
716
+ return (`property "${member}" read on ${String(obj)} is not foldable — running this expression throws a TypeError, ` +
717
+ `so the file falls back to run (write \`?.\` if the value is genuinely optional)`);
718
+ }
719
+ /**
720
+ * True when `node` is an identifier, or a dotted/bracketed access chain
721
+ * rooted at an identifier, that neither `consts` nor `externals` can resolve
722
+ * — e.g. `AWS.StackName` from an imported pseudo-parameter namespace inside
723
+ * a lexicon package (still #1063). Nothing here can say what it refers to,
724
+ * so an intrinsic's interior keeps it symbolically rather than rejecting it.
725
+ *
726
+ * `externals` (chant #1020) is consulted so a root that fold CAN resolve is
727
+ * not treated as unresolved: `Ref(environment)`, where `environment` is a
728
+ * `Parameter` imported from a sibling project file, must fold to the REAL,
729
+ * already-constructed Declarable the fold session made for that file, not to
730
+ * a `{__symbol}` the bridge later re-imports — re-importing the defining
731
+ * module builds a second, differently-identified instance of the same
732
+ * resource, which is exactly the shared-identity property #1020 exists to
733
+ * preserve (see fold-import.ts's module doc).
734
+ */
735
+ function isUnresolvedSymbolChain(node, consts, externals) {
736
+ if (ts.isIdentifier(node)) {
737
+ return node.text !== "undefined" && !consts.has(node.text) && !externals?.has(node.text);
738
+ }
739
+ if (ts.isPropertyAccessExpression(node))
740
+ return isUnresolvedSymbolChain(node.expression, consts, externals);
741
+ if (ts.isElementAccessExpression(node))
742
+ return isUnresolvedSymbolChain(node.expression, consts, externals);
743
+ if (ts.isNonNullExpression(node))
744
+ return isUnresolvedSymbolChain(node.expression, consts, externals);
745
+ return false;
746
+ }
747
+ /**
748
+ * Fold one sub-expression of a registered intrinsic's interior — an
749
+ * interpolation of its tagged-template form, or (chant #1044) an argument of
750
+ * its plain-call form. Identical to {@link fold}, except a symbol chain
751
+ * nothing can resolve (a pseudo-parameter-style access into a lexicon
752
+ * package, `AWS.StackName`) folds to a {@link SymbolicValue} instead of
753
+ * throwing — the run path resolves it once the module actually imports and
754
+ * runs; fold preserves it symbolically rather than stringifying or rejecting
755
+ * it, and fold-import.ts's `resolveSymbolicValue` resolves it for real
756
+ * before the intrinsic is constructed.
757
+ *
758
+ * `externals` (chant #1020) takes precedence over the symbolic path: see
759
+ * {@link isUnresolvedSymbolChain} for why an already-resolved cross-file
760
+ * binding must reach the intrinsic as the real, shared object rather than as
761
+ * a symbol the bridge re-imports.
762
+ */
763
+ function foldIntrinsicValue(node, consts, intrinsics, externals) {
764
+ if (isUnresolvedSymbolChain(node, consts, externals)) {
765
+ return { __symbol: node.getText() };
766
+ }
767
+ return fold(node, consts, intrinsics, externals);
768
+ }
769
+ /**
770
+ * A template part's raw text, as `TemplateStringsArray.raw` holds it. The
771
+ * parser sets `rawText` on every literal it reads; the fallback takes the
772
+ * source between the delimiters for a node without one. Line terminators are
773
+ * normalized the way the language does for `raw` (`\r\n` and `\r` become
774
+ * `\n`), which TypeScript's `rawText` does not do.
775
+ */
776
+ function rawTemplateText(part) {
777
+ let raw = part.rawText;
778
+ if (raw === undefined) {
779
+ const text = part.getText();
780
+ const close = ts.isTemplateHead(part) || ts.isTemplateMiddle(part) ? 2 : 1;
781
+ raw = text.slice(1, text.length - close);
782
+ }
783
+ return raw.replace(/\r\n?/g, "\n");
784
+ }
785
+ /**
786
+ * True when a raw template part holds an escape a tagged template allows but
787
+ * cannot cook (`\u{zz}`, `\xg`, `\1`, `\01`). Its cooked string is
788
+ * `undefined` at run time, while TypeScript's `text` carries a string, so
789
+ * folding it would hand the tag something running never does.
790
+ */
791
+ function hasInvalidTemplateEscape(raw) {
792
+ for (let i = 0; i < raw.length; i++) {
793
+ if (raw[i] !== "\\")
794
+ continue;
795
+ const rest = raw.slice(i + 1);
796
+ const c = rest[0];
797
+ if (c === "x") {
798
+ if (!/^x[0-9a-fA-F]{2}/.test(rest))
799
+ return true;
800
+ }
801
+ else if (c === "u") {
802
+ const m = /^u(?:[0-9a-fA-F]{4}|\{([0-9a-fA-F]+)\})/.exec(rest);
803
+ if (!m || (m[1] !== undefined && parseInt(m[1], 16) > 0x10ffff))
804
+ return true;
805
+ }
806
+ else if (c !== undefined && c >= "1" && c <= "9") {
807
+ return true;
808
+ }
809
+ else if (c === "0" && rest[1] !== undefined && rest[1] >= "0" && rest[1] <= "9") {
810
+ return true;
811
+ }
812
+ i += 1;
813
+ }
814
+ return false;
815
+ }
816
+ /**
817
+ * Fold a `TaggedTemplateExpression` whose tag is a registered, foldable
818
+ * lexicon intrinsic ({@link intrinsicTagFolds}, `../lexicon.ts`) to its node
819
+ * form. An unregistered — or registered-but-not-foldable — tag throws a
820
+ * located {@link FoldError}.
821
+ *
822
+ * Checks the TAG-form predicate specifically (chant #1044): an intrinsic
823
+ * whose lexicon opted its plain-call form in is not thereby usable as a
824
+ * tagged template, and `` Ref`...` `` stays a rejection.
825
+ *
826
+ * The envelope carries both the cooked parts and the raw ones (#3196), so the
827
+ * revived call receives the `TemplateStringsArray` a real tagged call does. A
828
+ * tag that reads `strings.raw` (a SQL tag keeping `'\d+'` as written) would
829
+ * otherwise build different text folded than run.
830
+ */
831
+ function foldTaggedTemplate(node, consts, intrinsics, externals) {
832
+ const tagName = node.tag.getText();
833
+ const isRegistered = intrinsics.some((i) => i.name === tagName && intrinsicTagFolds(i));
834
+ if (!isRegistered) {
835
+ throw foldError(node, `unregistered tagged template intrinsic: ${briefNodeText(node.tag)}\`...\``);
836
+ }
837
+ const template = node.template;
838
+ const parts = ts.isNoSubstitutionTemplateLiteral(template)
839
+ ? [template]
840
+ : [template.head, ...template.templateSpans.map((span) => span.literal)];
841
+ const raw = parts.map(rawTemplateText);
842
+ if (raw.some(hasInvalidTemplateEscape)) {
843
+ throw foldError(node, `${briefNodeText(node.tag)}\`...\` holds an escape sequence with no cooked value — not foldable, falls back to run`);
844
+ }
845
+ const strings = parts.map((part) => part.text);
846
+ const values = ts.isNoSubstitutionTemplateLiteral(template)
847
+ ? []
848
+ : template.templateSpans.map((span) => foldIntrinsicValue(span.expression, consts, intrinsics, externals));
849
+ return { __intrinsic: tagName, strings, raw, values };
850
+ }
851
+ /**
852
+ * Fold a single expression node to a value. Throws {@link FoldError} for
853
+ * anything outside the supported subset — including any `CallExpression`
854
+ * that is neither a registered chant authoring helper nor a registered,
855
+ * call-form-opted-in lexicon intrinsic (see the module doc).
856
+ *
857
+ * @param intrinsics - The active lexicons' registered intrinsics. A tagged
858
+ * template whose tag isn't in this list, or is in it without
859
+ * {@link intrinsicTagFolds}, is rejected; a plain call is rejected unless
860
+ * its callee is in this list with {@link intrinsicCallFolds} (chant
861
+ * #1044). Defaults to none — pass the target lexicon's manifest
862
+ * `intrinsics` to recognize either form.
863
+ * @param externals - chant #1020: pre-resolved imported bindings, consulted
864
+ * only when an identifier isn't in `consts`. See the module doc above.
865
+ * `undefined` (the default) preserves the exact pre-#1020 single-file
866
+ * behavior — every identifier not in `consts` is unresolved.
867
+ */
868
+ export function fold(node, consts, intrinsics = [], externals) {
869
+ if (ts.isParenthesizedExpression(node) ||
870
+ ts.isAsExpression(node) ||
871
+ ts.isSatisfiesExpression(node) ||
872
+ ts.isNonNullExpression(node)) {
873
+ return fold(node.expression, consts, intrinsics, externals);
874
+ }
875
+ if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {
876
+ // chant #1373 — a function is callable here (see {@link FoldableFunction})
877
+ // but never a VALUE: nothing downstream can serialize one.
878
+ throw foldError(node, "a function used as a value is not foldable");
879
+ }
880
+ if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {
881
+ return node.text;
882
+ }
883
+ if (ts.isNumericLiteral(node)) {
884
+ return Number(node.text);
885
+ }
886
+ if (node.kind === ts.SyntaxKind.TrueKeyword)
887
+ return true;
888
+ if (node.kind === ts.SyntaxKind.FalseKeyword)
889
+ return false;
890
+ if (node.kind === ts.SyntaxKind.NullKeyword)
891
+ return null;
892
+ if (ts.isIdentifier(node) && node.text === "undefined")
893
+ return undefined;
894
+ if (ts.isTaggedTemplateExpression(node)) {
895
+ const inside = insideFunctionBody(node, "a tagged template intrinsic");
896
+ if (inside)
897
+ throw inside;
898
+ return foldTaggedTemplate(node, consts, intrinsics, externals);
899
+ }
900
+ if (ts.isTemplateExpression(node)) {
901
+ let out = node.head.text;
902
+ for (const span of node.templateSpans) {
903
+ const value = fold(span.expression, consts, intrinsics, externals);
904
+ // A symbolic envelope has no string form. `String({__attrRef: …})` is
905
+ // `"[object Object]"`, and so is `String(attrRef)` on the run path,
906
+ // because `../attrref.ts` defines no `toString` — so the two paths
907
+ // agreed on a wrong answer and the differential saw nothing (#2349).
908
+ // Refused here rather than stringified, for the same reason the
909
+ // eager-intrinsic branch refuses a deferred envelope (#1966).
910
+ const symbolic = symbolicEnvelopeKind(value);
911
+ if (symbolic) {
912
+ throw foldError(span.expression, `${symbolic} interpolated into a plain template literal, which would stringify it as ` +
913
+ '"[object Object]". A symbolic value has no string form until the build resolves it, so a ' +
914
+ "plain template cannot carry one. Use the lexicon's own intrinsic, whose interior handles " +
915
+ "envelopes — `Sub`${…}`` for CloudFormation — or move the reference out of the template.");
916
+ }
917
+ out += String(value) + span.literal.text;
918
+ }
919
+ return out;
920
+ }
921
+ if (ts.isObjectLiteralExpression(node)) {
922
+ const obj = {};
923
+ for (const prop of node.properties) {
924
+ if (ts.isPropertyAssignment(prop)) {
925
+ obj[propName(prop.name)] = fold(prop.initializer, consts, intrinsics, externals);
926
+ }
927
+ else if (ts.isShorthandPropertyAssignment(prop)) {
928
+ obj[prop.name.text] = fold(prop.name, consts, intrinsics, externals);
929
+ }
930
+ else if (ts.isSpreadAssignment(prop)) {
931
+ const src = fold(prop.expression, consts, intrinsics, externals);
932
+ if (src === null || typeof src !== "object") {
933
+ throw foldError(prop, "spread source not an object");
934
+ }
935
+ Object.assign(obj, src);
936
+ }
937
+ else {
938
+ throw foldError(prop, UNSUPPORTED_OBJECT_MEMBER_MESSAGE);
939
+ }
940
+ }
941
+ return obj;
942
+ }
943
+ if (ts.isArrayLiteralExpression(node)) {
944
+ const arr = [];
945
+ for (const el of node.elements) {
946
+ if (ts.isSpreadElement(el)) {
947
+ const src = fold(el.expression, consts, intrinsics, externals);
948
+ if (!Array.isArray(src)) {
949
+ throw foldError(el, "spread source not an array");
950
+ }
951
+ arr.push(...src);
952
+ }
953
+ else {
954
+ arr.push(fold(el, consts, intrinsics, externals));
955
+ }
956
+ }
957
+ return arr;
958
+ }
959
+ if (ts.isIdentifier(node)) {
960
+ if (!consts.has(node.text)) {
961
+ // chant #1020 — an imported binding fold-import.ts already resolved
962
+ // (to a plain value, or the real live Declarable/CompositeInstance a
963
+ // sibling file's own fold produced) is returned as-is: for a plain
964
+ // value this is exactly like resolving a local const; for a real live
965
+ // object, the property-access branches below just index it like any
966
+ // other object, which is what makes a real, correctly-identified
967
+ // `AttrRef` fall out of `network.vpc.VpcId` with zero special-casing
968
+ // here (see fold-import.ts's module doc).
969
+ if (externals?.has(node.text)) {
970
+ const external = externals.get(node.text);
971
+ if (isFoldableFunction(external)) {
972
+ throw foldError(node, `function "${node.text}" used as a value is not foldable`);
973
+ }
974
+ // chant #1966 — a registered eager-fold lexicon helper (see the
975
+ // CallExpression branch below) is callable, never a bare value:
976
+ // nothing downstream can serialize a function.
977
+ if (typeof external === "function" &&
978
+ intrinsics.some((i) => i.name === node.text && intrinsicCallFoldsEagerly(i))) {
979
+ throw foldError(node, `function "${node.text}" used as a value is not foldable — call it instead`);
980
+ }
981
+ return external;
982
+ }
983
+ // chant #1064 — a bare `process` reference is ALWAYS an ambient
984
+ // environment read (`process.env.X`, `process.argv`, …), never
985
+ // something a future resolution pass could fold: it's Node's global,
986
+ // not a local const or an importable module export. Point at the
987
+ // supported alternative instead of leaving the author to infer the fix
988
+ // from the generic "unresolved identifier" message — see
989
+ // ../build-params.ts/../params.ts.
990
+ if (node.text === "process") {
991
+ throw foldError(node, `ambient "process" read is not foldable — declare a build-time parameter instead ` +
992
+ `(chant.config.ts's buildParams + \`chant build --param name=value\`/\`--params-file\`) and reference ` +
993
+ `it via \`import { params } from "@intentius/chant/params"\`, rather than reading process.env directly`);
994
+ }
995
+ throw foldError(node, `unresolved identifier: ${node.text}`);
996
+ }
997
+ const initializer = consts.get(node.text);
998
+ // chant #1169 — a BARE reference to a same-file `const x = new T(...)` is a
999
+ // reference to THAT resource instance, and the ONE thing it must never
1000
+ // become is a second one. Re-folding the initializer here would do exactly
1001
+ // that now that the `new` branch below constructs: the consumer would get a
1002
+ // duplicate object discovery never registered, whose `AttrRef`s could never
1003
+ // be assigned a logical name ("Cannot serialize AttrRef …: logical name not
1004
+ // set") and whose `Ref` would silently inline instead of referencing. A
1005
+ // crash or wrong output, not drift.
1006
+ //
1007
+ // So `externals` — and ONLY `externals` — answers this one. A caller with a
1008
+ // module graph (../discovery/fold-import.ts) pre-resolves each of this
1009
+ // file's `new`-valued consts to ONE instance, in source order, before any
1010
+ // declarator is folded, and puts it here; every reference in the file then
1011
+ // reads that same object, exactly as running the module top-to-bottom
1012
+ // would. A caller without one (`foldModule`, a unit test) has no way to
1013
+ // construct anything, so the reference stays a rejection and the file falls
1014
+ // back to run.
1015
+ //
1016
+ // `bucket.name` is a different question and keeps its answer regardless: the
1017
+ // property-access branch below consults `consts` first, so a sibling
1018
+ // attribute reference is still the symbolic `{__attrRef}` the serializer
1019
+ // resolves by NAME. Nothing about the existing envelope changes.
1020
+ //
1021
+ // chant #3196 — the same holds for a same-file `const x = tag\`...\``
1022
+ // whose tag returns an entity (a SQL `table`): re-folding the initializer
1023
+ // would call the tag again and build a second entity discovery never
1024
+ // registers. The caller pre-resolves those too; without it the
1025
+ // initializer re-folds as before.
1026
+ //
1027
+ // chant#3325 — and a same-file `const x = Composite({...})` that a
1028
+ // composite call's props name: the caller resolves it on the live spine
1029
+ // and puts the instance here. Without it the call is refused below.
1030
+ if ((ts.isTaggedTemplateExpression(initializer) || ts.isCallExpression(initializer)) &&
1031
+ externals?.has(node.text)) {
1032
+ return externals.get(node.text);
1033
+ }
1034
+ if (ts.isNewExpression(initializer)) {
1035
+ if (externals?.has(node.text))
1036
+ return externals.get(node.text);
1037
+ throw foldError(node, `same-file resource \`${node.text}\` used as a value is not foldable — falls back to run`);
1038
+ }
1039
+ return fold(initializer, consts, intrinsics, externals);
1040
+ }
1041
+ if (ts.isPropertyAccessExpression(node)) {
1042
+ if (ts.isIdentifier(node.expression) && resolvesToResource(consts, node.expression)) {
1043
+ return { __attrRef: { entity: node.expression.text, attribute: node.name.text } };
1044
+ }
1045
+ // chant #1174 — `<Identifier>(...).step`, the composite-consumer idiom
1046
+ // (`Checkout({...}).step`) — see FoldedCompositeStepCall's doc. Checked
1047
+ // here, at the property-access node, rather than inside the
1048
+ // CallExpression branch: a bare `Checkout({...})` with no `.step` still
1049
+ // has no case there and throws exactly as before.
1050
+ if (node.name.text === "step" && isUnclaimedBareCall(node.expression, consts, intrinsics, externals)) {
1051
+ const call = node.expression;
1052
+ const calleeName = call.expression.text;
1053
+ const inside = insideFunctionBody(node, `composite call \`${calleeName}(...).step\``);
1054
+ if (inside)
1055
+ throw inside;
1056
+ return {
1057
+ __compositeStep: calleeName,
1058
+ args: call.arguments.map((arg) => fold(arg, consts, intrinsics, externals)),
1059
+ };
1060
+ }
1061
+ const obj = fold(node.expression, consts, intrinsics, externals);
1062
+ // chant #2328 — see {@link nullishAccessMessage}. An earlier `?.` that
1063
+ // short-circuited carries the whole chain to `undefined`; a `?.` here does
1064
+ // the same for a nullish object; a plain `.` on one is the refusal.
1065
+ if (isChainShortCircuit(obj))
1066
+ return shortCircuited(node);
1067
+ if (obj === null || obj === undefined) {
1068
+ if (node.questionDotToken)
1069
+ return shortCircuited(node);
1070
+ throw foldError(node, nullishAccessMessage(node.name.text, obj));
1071
+ }
1072
+ if (isFoldedResource(obj))
1073
+ return attrRefOnFoldedResource(node, node.name.text);
1074
+ return obj[node.name.text];
1075
+ }
1076
+ if (ts.isElementAccessExpression(node)) {
1077
+ const key = elementKey(node.argumentExpression);
1078
+ if (ts.isIdentifier(node.expression) && resolvesToResource(consts, node.expression)) {
1079
+ return { __attrRef: { entity: node.expression.text, attribute: key } };
1080
+ }
1081
+ const obj = fold(node.expression, consts, intrinsics, externals);
1082
+ // chant #2328 — identical to the property-access branch above; `a?.["k"]`
1083
+ // is the bracketed spelling of the same short-circuit.
1084
+ if (isChainShortCircuit(obj))
1085
+ return shortCircuited(node);
1086
+ if (obj === null || obj === undefined) {
1087
+ if (node.questionDotToken)
1088
+ return shortCircuited(node);
1089
+ throw foldError(node, nullishAccessMessage(key, obj));
1090
+ }
1091
+ if (isFoldedResource(obj))
1092
+ return attrRefOnFoldedResource(node, key);
1093
+ return obj[key];
1094
+ }
1095
+ if (ts.isPrefixUnaryExpression(node)) {
1096
+ if (!SUPPORTED_UNARY_OPERATORS.has(node.operator)) {
1097
+ throw foldError(node, UNSUPPORTED_UNARY_MESSAGE);
1098
+ }
1099
+ const value = fold(node.operand, consts, intrinsics, externals);
1100
+ if (node.operator === ts.SyntaxKind.ExclamationToken)
1101
+ return !value;
1102
+ return -value; // ts.SyntaxKind.MinusToken — the only other supported operator
1103
+ }
1104
+ if (ts.isBinaryExpression(node)) {
1105
+ const opKind = node.operatorToken.kind;
1106
+ const S = ts.SyntaxKind;
1107
+ if (opKind === S.AmpersandAmpersandToken) {
1108
+ const left = fold(node.left, consts, intrinsics, externals);
1109
+ return left ? fold(node.right, consts, intrinsics, externals) : left;
1110
+ }
1111
+ if (opKind === S.BarBarToken) {
1112
+ const left = fold(node.left, consts, intrinsics, externals);
1113
+ return left ? left : fold(node.right, consts, intrinsics, externals);
1114
+ }
1115
+ if (opKind === S.QuestionQuestionToken) {
1116
+ const left = fold(node.left, consts, intrinsics, externals);
1117
+ return left === null || left === undefined ? fold(node.right, consts, intrinsics, externals) : left;
1118
+ }
1119
+ if (!SUPPORTED_BINARY_OPERATORS.has(opKind)) {
1120
+ throw foldError(node, unsupportedBinaryMessage(opKind));
1121
+ }
1122
+ const left = fold(node.left, consts, intrinsics, externals);
1123
+ const right = fold(node.right, consts, intrinsics, externals);
1124
+ switch (opKind) {
1125
+ case S.PlusToken:
1126
+ return left + right;
1127
+ case S.MinusToken:
1128
+ return left - right;
1129
+ case S.AsteriskToken:
1130
+ return left * right;
1131
+ case S.SlashToken:
1132
+ return left / right;
1133
+ case S.EqualsEqualsEqualsToken:
1134
+ return left === right;
1135
+ case S.ExclamationEqualsEqualsToken:
1136
+ return left !== right;
1137
+ case S.GreaterThanToken:
1138
+ return left > right;
1139
+ case S.LessThanToken:
1140
+ return left < right;
1141
+ case S.GreaterThanEqualsToken:
1142
+ return left >= right;
1143
+ case S.LessThanEqualsToken:
1144
+ return left <= right;
1145
+ default:
1146
+ // Unreachable given the SUPPORTED_BINARY_OPERATORS guard above —
1147
+ // kept as a defensive fallback in case that set and this switch
1148
+ // ever fall out of sync.
1149
+ throw foldError(node, unsupportedBinaryMessage(opKind));
1150
+ }
1151
+ }
1152
+ if (ts.isConditionalExpression(node)) {
1153
+ return fold(node.condition, consts, intrinsics, externals)
1154
+ ? fold(node.whenTrue, consts, intrinsics, externals)
1155
+ : fold(node.whenFalse, consts, intrinsics, externals);
1156
+ }
1157
+ if (ts.isNewExpression(node)) {
1158
+ // chant #1169 — a nested `new Type({...})` used as a property VALUE folds
1159
+ // to the SAME {@link FoldedResource} envelope a top-level resource
1160
+ // declaration does, and is constructed for real by the same bridge.
1161
+ //
1162
+ // This used to be an unconditional rejection, and the reason it was is
1163
+ // worth keeping in view: `fold()` alone can only produce the envelope, and
1164
+ // an envelope that reaches serialization is the wrong value — the #1025
1165
+ // differential caught exactly that on gitlab/multi-stage-deploy, where
1166
+ // `new Image({...})` as a job's `image:` must serialize as the constructed
1167
+ // Image's own shape, not as `{__resource, props}`. What changed is not the
1168
+ // envelope's safety but who consumes it: ../discovery/fold-import.ts's
1169
+ // `reviveFoldedValue` now REVIVES a `{__resource}` node into a real
1170
+ // instance, built by the class the file's own `import` names, resolved
1171
+ // through the same provenance-checked machinery that already constructs a
1172
+ // top-level resource (and that #1023's factory interpreter already uses to
1173
+ // construct a nested `new` inside a factory body — the asymmetry that
1174
+ // motivated this change). Nothing symbolic survives into the serializer:
1175
+ // the value the outer constructor receives is the same object the run path
1176
+ // would have handed it, with the same prototype, the same `props`, and the
1177
+ // same `toJSON`/`kind` the serializer's walker dispatches on.
1178
+ //
1179
+ // Only a PLAIN IDENTIFIER constructor is admissible. `new ns.Type(...)`
1180
+ // cannot be resolved to a live class through the file's named imports, so
1181
+ // it stays a rejection rather than folding to an envelope nothing can
1182
+ // revive — the same bare-identifier rule #1023's `checkFactoryExpression`
1183
+ // applies to a body-level construction, and the same one `fold()` applies
1184
+ // to an intrinsic call and an authoring helper.
1185
+ if (!ts.isIdentifier(node.expression)) {
1186
+ throw foldError(node, `nested \`new ${briefNodeText(node.expression)}(...)\` as a value needs a plain imported constructor — falls back to run`);
1187
+ }
1188
+ const inside = insideFunctionBody(node, `\`new ${node.expression.text}(...)\``);
1189
+ if (inside)
1190
+ throw inside;
1191
+ return foldResource(node, consts, intrinsics, externals);
1192
+ }
1193
+ if (ts.isCallExpression(node)) {
1194
+ // chant #1082 — the ONE call shape that folds: a registered chant
1195
+ // authoring helper ({@link FOLDABLE_AUTHORING_HELPERS}), called through a
1196
+ // bare identifier that this file hasn't shadowed with its own `const`.
1197
+ // Nothing is executed here — the call reduces to a symbolic
1198
+ // {@link FoldedHelperCall} envelope, exactly as a registered intrinsic
1199
+ // tagged template reduces to a {@link FoldedIntrinsic} one, and for the
1200
+ // same reason: the real function lives in another module, and resolving
1201
+ // + invoking it is the async bridge's job (../discovery/fold-import.ts's
1202
+ // `reviveFoldedValue`), which also verifies the name is actually bound to
1203
+ // an import of chant's own before invoking anything. Every other call —
1204
+ // a user's function, a method call, a call to something declared in this
1205
+ // file — still has no case and throws, unchanged.
1206
+ if (ts.isIdentifier(node.expression) &&
1207
+ isFoldableHelperName(node.expression.text) &&
1208
+ !consts.has(node.expression.text)) {
1209
+ const inside = insideFunctionBody(node, `authoring helper call \`${node.expression.text}(...)\``);
1210
+ if (inside)
1211
+ throw inside;
1212
+ return {
1213
+ __helper: node.expression.text,
1214
+ args: node.arguments.map((arg) => fold(arg, consts, intrinsics, externals)),
1215
+ };
1216
+ }
1217
+ // chant #1044 — the other call shape that folds: a lexicon intrinsic in
1218
+ // PLAIN-CALL form (`Ref(bucket)`, `Concat("a", b)`), where that lexicon
1219
+ // registered it AND opted its call form in ({@link intrinsicCallFolds},
1220
+ // ../lexicon.ts — default off, never inferred). Reduces to the same
1221
+ // `{__intrinsic}` envelope family the tagged-template form produces, with
1222
+ // positional `args`; nothing is executed here, for the same reason as the
1223
+ // tag form — the real function lives in the lexicon module, and resolving
1224
+ // it through this file's own imports and invoking it is the async
1225
+ // bridge's job (../discovery/fold-import.ts's `reviveFoldedValue`).
1226
+ //
1227
+ // Arguments fold through {@link foldIntrinsicValue}, exactly like a tag's
1228
+ // interpolations: an intrinsic's interior is where a pseudo-parameter
1229
+ // chain (`GetAZs(AWS.Region)`) legitimately appears, and it stays
1230
+ // symbolic rather than rejecting.
1231
+ //
1232
+ // The door does not open any wider than this. A bare-identifier callee
1233
+ // only, so `ns.Ref(...)` and `arr.map(...)` are untouched; the file's own
1234
+ // `const` shadowing wins, so a local `Ref` is not the lexicon's; and a
1235
+ // name absent from the active lexicons' registered set — or registered
1236
+ // without the opt-in — falls straight through to the throw below.
1237
+ if (ts.isIdentifier(node.expression) && !consts.has(node.expression.text)) {
1238
+ const calleeName = node.expression.text;
1239
+ if (intrinsics.some((i) => i.name === calleeName && intrinsicCallFolds(i))) {
1240
+ const inside = insideFunctionBody(node, `intrinsic call \`${calleeName}(...)\``);
1241
+ if (inside)
1242
+ throw inside;
1243
+ return {
1244
+ __intrinsic: calleeName,
1245
+ args: node.arguments.map((arg) => foldIntrinsicValue(arg, consts, intrinsics, externals)),
1246
+ };
1247
+ }
1248
+ }
1249
+ // chant #1373 — the third call shape, and the only open-ended one: a
1250
+ // PROJECT-LOCAL function (declared in this file or imported from a
1251
+ // sibling project file) whose body is itself foldable. fold-import.ts
1252
+ // places a {@link FoldableFunction} marker in `externals` for each such
1253
+ // declaration (a same-file `const f = () => …` is in `consts` too, which
1254
+ // is why this is not gated on `consts` like the two above); the call is
1255
+ // evaluated right here, statically, against the defining module's scope
1256
+ // — see {@link callFoldableFunction}. Checked AFTER the two registered
1257
+ // shapes so a registered name keeps its registered meaning; a package
1258
+ // export never produces a marker, so `node_modules` stays out.
1259
+ if (ts.isIdentifier(node.expression)) {
1260
+ const callee = externals?.get(node.expression.text);
1261
+ if (isFoldableFunction(callee)) {
1262
+ return callFoldableFunction(callee, node, consts, intrinsics, externals);
1263
+ }
1264
+ // chant#2436 — the same shape, reached without a build. A caller that
1265
+ // supplied no `externals` has no module graph and so no markers, and a
1266
+ // same-file call fell through to the throw below even though a build
1267
+ // folds it. Derive the file's own functions and call one.
1268
+ //
1269
+ // Only when `externals` is absent. A caller that passed one is managing
1270
+ // its own bindings (a build, which already put the markers there before
1271
+ // folding anything), and second-guessing it here could bind a name it
1272
+ // deliberately left out. A same-file function only: an imported one needs
1273
+ // module resolution, which this module does not do and will not start.
1274
+ if (externals === undefined) {
1275
+ const local = sameFileFunctions(node, consts)?.get(node.expression.text);
1276
+ if (local)
1277
+ return callFoldableFunction(local, node, consts, intrinsics, local.externals);
1278
+ }
1279
+ }
1280
+ // chant #1966 — the fourth call shape: a lexicon-package function its
1281
+ // lexicon registered with {@link intrinsicCallFoldsEagerly} (../lexicon.ts),
1282
+ // resolved into `externals` by ../discovery/fold-import.ts's
1283
+ // `resolveActiveLexiconExport` exactly like a plain data export
1284
+ // (`Azure.ResourceGroupLocation`, chant #1063), except callable. Unlike
1285
+ // the intrinsic-call shape above, this one is EVALUATED right here rather
1286
+ // than enveloped: a lexicon's own string-building helper (`matrix("os")`,
1287
+ // github lexicon) is typically embedded directly in a template literal
1288
+ // (`` `${matrix("os")}` ``), which coerces its result via native
1289
+ // `String()` at fold time — an envelope deferred to later revival would
1290
+ // stringify as "[object Object]" there. Evaluating eagerly, with the
1291
+ // folded arguments, produces the real, already-live return value instead
1292
+ // — the same guarantee a live external's own getter execution already
1293
+ // gives {@link fold}'s property-access branch.
1294
+ if (ts.isIdentifier(node.expression) &&
1295
+ !consts.has(node.expression.text) &&
1296
+ intrinsics.some((i) => i.name === node.expression.text && intrinsicCallFoldsEagerly(i))) {
1297
+ const callee = externals?.get(node.expression.text);
1298
+ if (typeof callee !== "function") {
1299
+ throw foldError(node, `"${node.expression.text}" did not resolve to a function — falls back to run`);
1300
+ }
1301
+ const args = node.arguments.map((arg) => fold(arg, consts, intrinsics, externals));
1302
+ return callee(...args);
1303
+ }
1304
+ // chant #1966 — a method call whose RECEIVER is itself foldable: property
1305
+ // access on a live external (`github.actor.toString()`), a call folded by
1306
+ // one of the shapes above (`matrix("os").toString()`), or fold's own
1307
+ // array/object literal (`[...].join(",")`). The method is never checked
1308
+ // by name — only that the receiver is a REAL value (not one of fold's own
1309
+ // symbolic envelopes, see {@link isFoldSymbolicEnvelope}) and that the
1310
+ // named property on it is actually a function. Calling it with the folded
1311
+ // arguments is then no different from what running the file would do:
1312
+ // the receiver is the same real object either way.
1313
+ if (ts.isPropertyAccessExpression(node.expression)) {
1314
+ const methodName = node.expression.name.text;
1315
+ const receiver = fold(node.expression.expression, consts, intrinsics, externals);
1316
+ // chant #2328 — a call is a link of an optional chain like any other:
1317
+ // `a?.b()` and `a?.b.c()` on a nullish `a` are `undefined` in
1318
+ // JavaScript, not a call on nothing. Only a non-optional receiver keeps
1319
+ // the refusal this branch has made since #1966.
1320
+ if (isChainShortCircuit(receiver))
1321
+ return shortCircuited(node);
1322
+ if (receiver === null || receiver === undefined) {
1323
+ if (node.expression.questionDotToken)
1324
+ return shortCircuited(node);
1325
+ throw foldError(node, `cannot call ".${methodName}(...)" on ${String(receiver)}`);
1326
+ }
1327
+ if (isFoldSymbolicEnvelope(receiver)) {
1328
+ throw foldError(node, `method call \`.${methodName}(...)\` on an unresolved value is not foldable — falls back to run`);
1329
+ }
1330
+ const method = receiver[methodName];
1331
+ if (typeof method !== "function") {
1332
+ throw foldError(node, `"${methodName}" is not a callable method on the folded value — falls back to run`);
1333
+ }
1334
+ const args = node.arguments.map((arg) => fold(arg, consts, intrinsics, externals));
1335
+ return method.apply(receiver, args);
1336
+ }
1337
+ throw foldError(node, callExpressionMessage(node));
1338
+ }
1339
+ throw foldError(node, unsupportedExpressionMessage(node));
1340
+ }
1341
+ /**
1342
+ * Fold a resource constructor call to its spec.
1343
+ *
1344
+ * The common `createResource` shape (../runtime.ts) is `new Type({ ...props
1345
+ * })` or `new Type({ ...props }, { ...attributes })` — CFN-style resource
1346
+ * attributes (`DependsOn`, `Condition`, `DeletionPolicy`, …) second — and
1347
+ * that shape reduces to `props` (+ `attributes`) exactly as before.
1348
+ *
1349
+ * chant #1082 — but that is a convention, not a rule every lexicon class
1350
+ * follows. AWS's deploy-time `Parameter` is `(type, props)`
1351
+ * (lexicons/aws/src/parameter.ts): the props object is the SECOND argument
1352
+ * and the first is a plain string. `foldResource` used to require argument 0
1353
+ * to be an object literal, so no `new Parameter(...)` anywhere could ever
1354
+ * fold, whatever surrounded it. The general case now folds every argument in
1355
+ * source order into {@link FoldedResource.args}, which the caller constructs
1356
+ * the entity from verbatim — no positional assumption at all. `props` is
1357
+ * still reported (the first object-literal argument, for callers that read
1358
+ * it) but is a VIEW onto `args`, not the thing constructed from.
1359
+ */
1360
+ export function foldResource(node, consts, intrinsics = [], externals) {
1361
+ const typeName = node.expression.getText();
1362
+ const args = node.arguments ?? [];
1363
+ const [firstArg, secondArg] = args;
1364
+ const foldArg = (arg) => fold(arg, consts, intrinsics, externals);
1365
+ if (!firstArg) {
1366
+ return { __resource: typeName, props: {} };
1367
+ }
1368
+ // The classic (props) / (props, attributes) shape — reported without an
1369
+ // `args` list so the spec of an ordinary resource is unchanged.
1370
+ if (ts.isObjectLiteralExpression(firstArg)) {
1371
+ const props = foldArg(firstArg);
1372
+ if (args.length === 1) {
1373
+ return { __resource: typeName, props };
1374
+ }
1375
+ if (args.length === 2 && ts.isObjectLiteralExpression(secondArg)) {
1376
+ return { __resource: typeName, props, attributes: foldArg(secondArg) };
1377
+ }
1378
+ }
1379
+ // Anything else: fold every argument positionally. Each one still has to be
1380
+ // in the fold subset on its own terms — a non-foldable argument throws from
1381
+ // `fold()` exactly as a non-foldable prop value does.
1382
+ const folded = args.map(foldArg);
1383
+ const propsIndex = args.findIndex((arg) => ts.isObjectLiteralExpression(arg));
1384
+ const props = (propsIndex === -1 ? {} : folded[propsIndex]);
1385
+ return { __resource: typeName, props, args: folded };
1386
+ }
1387
+ function hasExportModifier(statement) {
1388
+ return statement.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ?? false;
1389
+ }
1390
+ /**
1391
+ * Fold every exported `const X = new Type({...})` resource declaration in a
1392
+ * source file to its spec, with no module execution.
1393
+ *
1394
+ * Non-resource `const` exports (anything whose initializer isn't a `new`
1395
+ * expression) are left out of the result rather than folded or errored —
1396
+ * `new`-less resource forms (composite factory calls) are epic Phase 5
1397
+ * (#1023) and are not attempted here.
1398
+ *
1399
+ * @param intrinsics - Lexicon-registered intrinsic tags, forwarded to
1400
+ * {@link fold} for every resource. See {@link fold}'s `intrinsics` param.
1401
+ */
1402
+ export function foldModule(source, fileName = "module.ts", intrinsics = []) {
1403
+ const sourceFile = ts.createSourceFile(fileName, source, ts.ScriptTarget.Latest, /* setParentNodes */ true);
1404
+ const consts = collectConsts(sourceFile);
1405
+ const result = {};
1406
+ for (const statement of sourceFile.statements) {
1407
+ if (!ts.isVariableStatement(statement))
1408
+ continue;
1409
+ if (!hasExportModifier(statement))
1410
+ continue;
1411
+ if ((statement.declarationList.flags & ts.NodeFlags.Const) === 0)
1412
+ continue;
1413
+ for (const decl of statement.declarationList.declarations) {
1414
+ if (!ts.isIdentifier(decl.name) || !decl.initializer)
1415
+ continue;
1416
+ if (!ts.isNewExpression(decl.initializer))
1417
+ continue;
1418
+ const name = decl.name.text;
1419
+ try {
1420
+ const spec = foldResource(decl.initializer, consts, intrinsics);
1421
+ result[name] = { ok: true, spec };
1422
+ }
1423
+ catch (err) {
1424
+ if (err instanceof FoldError) {
1425
+ result[name] = { ok: false, error: err.message, ruleId: err.ruleId, line: err.line, column: err.column };
1426
+ }
1427
+ else {
1428
+ throw err;
1429
+ }
1430
+ }
1431
+ }
1432
+ }
1433
+ return result;
1434
+ }