@intentius/chant 0.124.12 → 0.124.14

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 (928) 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.js +668 -0
  35. package/dist/builder.js +44 -0
  36. package/dist/cdk/advise.js +30 -0
  37. package/dist/cdk/assembly.js +122 -0
  38. package/dist/cdk/graph.js +444 -0
  39. package/dist/cdk/tier-map.js +64 -0
  40. package/dist/cdk/types.js +24 -0
  41. package/dist/change-set.js +312 -0
  42. package/dist/child-project.js +21 -0
  43. package/dist/claimed-fields.js +135 -0
  44. package/dist/cli/build-options.js +70 -0
  45. package/dist/cli/build-params-cli.js +139 -0
  46. package/dist/cli/command-group.js +123 -0
  47. package/dist/cli/commands/audit-agents.js +326 -0
  48. package/dist/cli/commands/audit.js +571 -0
  49. package/dist/cli/commands/build.js +920 -0
  50. package/dist/cli/commands/carve-apply.js +153 -0
  51. package/dist/cli/commands/carve-bridge.js +201 -0
  52. package/dist/cli/commands/carve-emit.js +332 -0
  53. package/dist/cli/commands/carve-status.js +119 -0
  54. package/dist/cli/commands/carve.js +204 -0
  55. package/dist/cli/commands/check-lexicon-docs.js +79 -0
  56. package/dist/cli/commands/check-lexicon-examples.js +177 -0
  57. package/dist/cli/commands/check-lexicon-intrinsics.js +291 -0
  58. package/dist/cli/commands/check-lexicon-mcp.js +82 -0
  59. package/dist/cli/commands/check-lexicon-plugin.d.ts.map +1 -1
  60. package/dist/cli/commands/check-lexicon-plugin.js +104 -0
  61. package/dist/cli/commands/check-lexicon.js +766 -0
  62. package/dist/cli/commands/describe.js +85 -0
  63. package/dist/cli/commands/diff.js +175 -0
  64. package/dist/cli/commands/doctor.js +350 -0
  65. package/dist/cli/commands/import-agents.js +155 -0
  66. package/dist/cli/commands/import.js +670 -0
  67. package/dist/cli/commands/init-lexicon/templates/codegen.js +194 -0
  68. package/dist/cli/commands/init-lexicon/templates/docs.js +100 -0
  69. package/dist/cli/commands/init-lexicon/templates/examples.js +29 -0
  70. package/dist/cli/commands/init-lexicon/templates/lint.js +34 -0
  71. package/dist/cli/commands/init-lexicon/templates/lsp.js +37 -0
  72. package/dist/cli/commands/init-lexicon/templates/plugin.js +108 -0
  73. package/dist/cli/commands/init-lexicon/templates/project.js +240 -0
  74. package/dist/cli/commands/init-lexicon/templates/spec.js +56 -0
  75. package/dist/cli/commands/init-lexicon/templates/tests.js +66 -0
  76. package/dist/cli/commands/init-lexicon.js +172 -0
  77. package/dist/cli/commands/init.js +381 -0
  78. package/dist/cli/commands/lexicon-rolling-upgrade.js +145 -0
  79. package/dist/cli/commands/lexicon-surface-diff.js +145 -0
  80. package/dist/cli/commands/licenses.js +125 -0
  81. package/dist/cli/commands/lint.d.ts.map +1 -1
  82. package/dist/cli/commands/lint.js +948 -0
  83. package/dist/cli/commands/list.js +63 -0
  84. package/dist/cli/commands/migrate.d.ts.map +1 -1
  85. package/dist/cli/commands/migrate.js +423 -0
  86. package/dist/cli/commands/onboard.js +403 -0
  87. package/dist/cli/commands/pinned-upgrade.js +191 -0
  88. package/dist/cli/commands/update.js +194 -0
  89. package/dist/cli/commands/vendor.js +217 -0
  90. package/dist/cli/conflict-check.js +104 -0
  91. package/dist/cli/debug.js +8 -0
  92. package/dist/cli/format.js +104 -0
  93. package/dist/cli/handlers/build.js +267 -0
  94. package/dist/cli/handlers/carve-apply.js +30 -0
  95. package/dist/cli/handlers/carve-bridge.js +28 -0
  96. package/dist/cli/handlers/carve-emit.js +50 -0
  97. package/dist/cli/handlers/carve-status.js +26 -0
  98. package/dist/cli/handlers/carve.js +40 -0
  99. package/dist/cli/handlers/change-set.js +46 -0
  100. package/dist/cli/handlers/components.js +730 -0
  101. package/dist/cli/handlers/dev.js +113 -0
  102. package/dist/cli/handlers/emulator.js +233 -0
  103. package/dist/cli/handlers/explain.js +54 -0
  104. package/dist/cli/handlers/fan-out.js +422 -0
  105. package/dist/cli/handlers/gate-resume.js +275 -0
  106. package/dist/cli/handlers/generate.js +84 -0
  107. package/dist/cli/handlers/graph.js +969 -0
  108. package/dist/cli/handlers/init.js +102 -0
  109. package/dist/cli/handlers/lifecycle.js +1727 -0
  110. package/dist/cli/handlers/lint.js +62 -0
  111. package/dist/cli/handlers/migrate.js +48 -0
  112. package/dist/cli/handlers/misc.js +391 -0
  113. package/dist/cli/handlers/operator.js +1162 -0
  114. package/dist/cli/handlers/override-approve.js +102 -0
  115. package/dist/cli/handlers/pr.js +503 -0
  116. package/dist/cli/handlers/promote.js +342 -0
  117. package/dist/cli/handlers/run-generate.js +206 -0
  118. package/dist/cli/handlers/run-wave.js +66 -0
  119. package/dist/cli/handlers/run.js +1191 -0
  120. package/dist/cli/handlers/scenario.js +325 -0
  121. package/dist/cli/handlers/search.js +924 -0
  122. package/dist/cli/handlers/serve.js +32 -0
  123. package/dist/cli/handlers/vendor.js +154 -0
  124. package/dist/cli/index.js +3 -0
  125. package/dist/cli/is-entry-point.js +23 -0
  126. package/dist/cli/lsp/capabilities.js +28 -0
  127. package/dist/cli/lsp/diagnostics.js +34 -0
  128. package/dist/cli/lsp/server.js +329 -0
  129. package/dist/cli/main.d.ts.map +1 -1
  130. package/dist/cli/main.js +2540 -0
  131. package/dist/cli/mcp/lifecycle-tools.js +80 -0
  132. package/dist/cli/mcp/op-tools.js +306 -0
  133. package/dist/cli/mcp/resource-handlers.js +258 -0
  134. package/dist/cli/mcp/resources/context.js +85 -0
  135. package/dist/cli/mcp/server.js +353 -0
  136. package/dist/cli/mcp/tools/build.js +111 -0
  137. package/dist/cli/mcp/tools/composites.js +95 -0
  138. package/dist/cli/mcp/tools/explain.js +166 -0
  139. package/dist/cli/mcp/tools/import.js +49 -0
  140. package/dist/cli/mcp/tools/lint.js +41 -0
  141. package/dist/cli/mcp/tools/scaffold.js +111 -0
  142. package/dist/cli/mcp/tools/search.js +112 -0
  143. package/dist/cli/mcp/types.js +1 -0
  144. package/dist/cli/mcp/workspace-plugins.js +91 -0
  145. package/dist/cli/mcp/workspace-tools.d.ts +1 -1
  146. package/dist/cli/mcp/workspace-tools.js +564 -0
  147. package/dist/cli/mcp-config.js +70 -0
  148. package/dist/cli/plugins.js +313 -0
  149. package/dist/cli/registry.js +23 -0
  150. package/dist/cli/reporters/stylish.js +329 -0
  151. package/dist/cli/version.js +15 -0
  152. package/dist/cli/watch.js +79 -0
  153. package/dist/codegen/bound-property-types.js +82 -0
  154. package/dist/codegen/coverage.js +119 -0
  155. package/dist/codegen/docs-file-markers.js +60 -0
  156. package/dist/codegen/docs-pages.js +115 -0
  157. package/dist/codegen/docs-rule-scanning.js +164 -0
  158. package/dist/codegen/docs-rules.js +76 -0
  159. package/dist/codegen/docs-sections.js +117 -0
  160. package/dist/codegen/docs-sidebar.js +65 -0
  161. package/dist/codegen/docs-types.js +4 -0
  162. package/dist/codegen/docs.js +356 -0
  163. package/dist/codegen/fetch.js +340 -0
  164. package/dist/codegen/generate-post-synth-barrel.js +63 -0
  165. package/dist/codegen/generate-registry.js +71 -0
  166. package/dist/codegen/generate-runtime-index.js +56 -0
  167. package/dist/codegen/generate-typescript.js +119 -0
  168. package/dist/codegen/generate.js +115 -0
  169. package/dist/codegen/json-patch.js +141 -0
  170. package/dist/codegen/json-schema-to-ts.js +344 -0
  171. package/dist/codegen/json-schema.js +246 -0
  172. package/dist/codegen/lexicon-regen.js +412 -0
  173. package/dist/codegen/naming.js +217 -0
  174. package/dist/codegen/okf-lexicon.js +245 -0
  175. package/dist/codegen/package.js +150 -0
  176. package/dist/codegen/pinned-upgrade.d.ts.map +1 -1
  177. package/dist/codegen/pinned-upgrade.js +494 -0
  178. package/dist/codegen/registry.js +60 -0
  179. package/dist/codegen/rehype-base-url.mjs +68 -0
  180. package/dist/codegen/rolling-upgrade.js +217 -0
  181. package/dist/codegen/surface-snapshot.js +537 -0
  182. package/dist/codegen/testdata/postgres-tags.json +242 -0
  183. package/dist/codegen/topo-sort.js +36 -0
  184. package/dist/codegen/typecheck.js +115 -0
  185. package/dist/codegen/validate.js +200 -0
  186. package/dist/codegen/version-bump.js +35 -0
  187. package/dist/components/auto-release.js +143 -0
  188. package/dist/components/builders.js +47 -0
  189. package/dist/components/capability-plugin-loader.js +175 -0
  190. package/dist/components/capability-plugin-schema.js +46 -0
  191. package/dist/components/capability-plugin.js +99 -0
  192. package/dist/components/capability.js +60 -0
  193. package/dist/components/changed-files.js +72 -0
  194. package/dist/components/cli-support.js +427 -0
  195. package/dist/components/component.js +120 -0
  196. package/dist/components/component.schema.json +271 -0
  197. package/dist/components/config-defaults.js +130 -0
  198. package/dist/components/deploy-units.js +60 -0
  199. package/dist/components/discover.d.ts.map +1 -1
  200. package/dist/components/discover.js +189 -0
  201. package/dist/components/driver-output.js +86 -0
  202. package/dist/components/driver.js +728 -0
  203. package/dist/components/fan-out-output.js +165 -0
  204. package/dist/components/fan-out-record.js +94 -0
  205. package/dist/components/fan-out-run.js +373 -0
  206. package/dist/components/fan-out-support.js +60 -0
  207. package/dist/components/fan-out.js +273 -0
  208. package/dist/components/gate-plan.js +41 -0
  209. package/dist/components/gated-wave-pipeline.js +46 -0
  210. package/dist/components/index.js +24 -0
  211. package/dist/components/layers.js +28 -0
  212. package/dist/components/manifest-persistence.js +108 -0
  213. package/dist/components/pilots/alb-ecs.pilot.js +59 -0
  214. package/dist/components/pilots/dynamodb.pilot.js +51 -0
  215. package/dist/components/pilots/jar-emr.pilot.js +65 -0
  216. package/dist/components/pilots/lambda.pilot.js +52 -0
  217. package/dist/components/pilots/neo4j-fanout.pilot.js +68 -0
  218. package/dist/components/pilots/project.js +12 -0
  219. package/dist/components/pr-pipeline.js +134 -0
  220. package/dist/components/pr-run.js +363 -0
  221. package/dist/components/presets/ecs-fargate.js +72 -0
  222. package/dist/components/presets/index.js +28 -0
  223. package/dist/components/presets/lambda.js +34 -0
  224. package/dist/components/presets/single-host-compose.js +41 -0
  225. package/dist/components/promote.js +549 -0
  226. package/dist/components/registry.js +34 -0
  227. package/dist/components/run-progress.js +33 -0
  228. package/dist/components/sandbox/driver.d.ts.map +1 -1
  229. package/dist/components/sandbox/driver.js +93 -0
  230. package/dist/components/sandbox/run.js +115 -0
  231. package/dist/components/starter-plugin.js +104 -0
  232. package/dist/components/verbs/__tests__/mock-cloud-executor.js +68 -0
  233. package/dist/components/verbs/__tests__/mock-process-runner.js +45 -0
  234. package/dist/components/verbs/__tests__/mock-sbom-generator.js +56 -0
  235. package/dist/components/verbs/bom-writer.js +287 -0
  236. package/dist/components/verbs/build-archive.js +188 -0
  237. package/dist/components/verbs/build.js +142 -0
  238. package/dist/components/verbs/cloud-executor.js +110 -0
  239. package/dist/components/verbs/component-bom.js +125 -0
  240. package/dist/components/verbs/ensure-secret.js +50 -0
  241. package/dist/components/verbs/index.js +61 -0
  242. package/dist/components/verbs/license-policy.js +75 -0
  243. package/dist/components/verbs/lockfile-sbom-generator.js +191 -0
  244. package/dist/components/verbs/process-runner.js +78 -0
  245. package/dist/components/verbs/r2-sync.js +93 -0
  246. package/dist/components/verbs/reproducibility.js +62 -0
  247. package/dist/components/verbs/run-agent.js +577 -0
  248. package/dist/components/verbs/sbom-generator.js +119 -0
  249. package/dist/components/verbs/sbom.js +97 -0
  250. package/dist/components/verbs/shell.js +32 -0
  251. package/dist/components/verbs/sign.js +221 -0
  252. package/dist/components/verbs/stub.js +28 -0
  253. package/dist/components/verbs/tool-sbom-generator.js +154 -0
  254. package/dist/components/verbs/verify.js +112 -0
  255. package/dist/components/verbs/vex.js +131 -0
  256. package/dist/components/verbs/vuln-gate.js +152 -0
  257. package/dist/components/verbs/vuln-scan.js +288 -0
  258. package/dist/components/verbs/wait-verify.js +106 -0
  259. package/dist/components/verbs/wrangler.js +179 -0
  260. package/dist/components/wave-plan.js +102 -0
  261. package/dist/composite.js +305 -0
  262. package/dist/config-import.d.ts.map +1 -1
  263. package/dist/config-import.js +22 -0
  264. package/dist/config-sandbox.js +122 -0
  265. package/dist/config-static.js +206 -0
  266. package/dist/config.js +605 -0
  267. package/dist/content-digest.js +23 -0
  268. package/dist/declarable.js +114 -0
  269. package/dist/deep-observation.js +437 -0
  270. package/dist/detectLexicon.js +54 -0
  271. package/dist/discovery/cache.js +70 -0
  272. package/dist/discovery/collect.js +208 -0
  273. package/dist/discovery/cycles.js +95 -0
  274. package/dist/discovery/entity-wire-codec.js +391 -0
  275. package/dist/discovery/entity-wire.js +42 -0
  276. package/dist/discovery/files.js +121 -0
  277. package/dist/discovery/fold-import.d.ts.map +1 -1
  278. package/dist/discovery/fold-import.js +4178 -0
  279. package/dist/discovery/fold-rank.js +292 -0
  280. package/dist/discovery/graph.js +115 -0
  281. package/dist/discovery/import.d.ts.map +1 -1
  282. package/dist/discovery/import.js +65 -0
  283. package/dist/discovery/index.js +333 -0
  284. package/dist/discovery/param-deps.js +487 -0
  285. package/dist/discovery/resolve.js +39 -0
  286. package/dist/discovery/sandbox/bundle.js +214 -0
  287. package/dist/discovery/sandbox/child-errors.js +26 -0
  288. package/dist/discovery/sandbox/config-run.js +100 -0
  289. package/dist/discovery/sandbox/config-wire.js +183 -0
  290. package/dist/discovery/sandbox/driver.d.ts.map +1 -1
  291. package/dist/discovery/sandbox/driver.js +333 -0
  292. package/dist/discovery/sandbox/fork.js +229 -0
  293. package/dist/discovery/sandbox/policy-run.js +142 -0
  294. package/dist/discovery/sandbox/policy-wire.js +152 -0
  295. package/dist/discovery/sandbox/run.js +77 -0
  296. package/dist/discovery/specifier-resolve.js +320 -0
  297. package/dist/discovery/walk.js +284 -0
  298. package/dist/effect-receipt.js +340 -0
  299. package/dist/env.js +55 -0
  300. package/dist/errors.js +62 -0
  301. package/dist/fold/fold.js +1434 -0
  302. package/dist/fold/foldable-helpers.js +229 -0
  303. package/dist/fold/subset.js +696 -0
  304. package/dist/fold-provenance.js +414 -0
  305. package/dist/gate-decision.d.ts +36 -4
  306. package/dist/gate-decision.d.ts.map +1 -1
  307. package/dist/gate-decision.js +260 -0
  308. package/dist/gate-resume-run.js +154 -0
  309. package/dist/gated-waves.js +165 -0
  310. package/dist/governance.js +43 -0
  311. package/dist/graph-declared.js +45 -0
  312. package/dist/graph-detail.js +207 -0
  313. package/dist/graph-dot.js +54 -0
  314. package/dist/graph-effective.js +107 -0
  315. package/dist/graph-ir.js +623 -0
  316. package/dist/graph-layout.js +184 -0
  317. package/dist/graph-lens.js +105 -0
  318. package/dist/graph-mermaid.js +83 -0
  319. package/dist/graph-ops.js +39 -0
  320. package/dist/graph-refs.js +156 -0
  321. package/dist/held-elsewhere.js +87 -0
  322. package/dist/identity.js +251 -0
  323. package/dist/import/base-parser.js +34 -0
  324. package/dist/import/embedded.js +255 -0
  325. package/dist/import/generator.js +1 -0
  326. package/dist/import/ir-utils.js +85 -0
  327. package/dist/import/parser-options.js +45 -0
  328. package/dist/import/parser.js +1 -0
  329. package/dist/index.js +118 -0
  330. package/dist/intrinsic-interpolation.js +73 -0
  331. package/dist/intrinsic.js +31 -0
  332. package/dist/join-key.js +35 -0
  333. package/dist/kubectl-context.js +150 -0
  334. package/dist/lexicon-config.js +58 -0
  335. package/dist/lexicon-integrity.js +47 -0
  336. package/dist/lexicon-manifest.js +70 -0
  337. package/dist/lexicon-module.d.ts.map +1 -1
  338. package/dist/lexicon-module.js +241 -0
  339. package/dist/lexicon-output.js +218 -0
  340. package/dist/lexicon-plugin-helpers.js +104 -0
  341. package/dist/lexicon-schema.js +136 -0
  342. package/dist/lexicon.js +130 -0
  343. package/dist/lifecycle/affected.js +224 -0
  344. package/dist/lifecycle/assert-live.js +110 -0
  345. package/dist/lifecycle/build-ledger-store.js +160 -0
  346. package/dist/lifecycle/build-ledger.js +155 -0
  347. package/dist/lifecycle/change-set.js +356 -0
  348. package/dist/lifecycle/converge-ledger.js +161 -0
  349. package/dist/lifecycle/deep-diff.js +233 -0
  350. package/dist/lifecycle/deep-observe.js +147 -0
  351. package/dist/lifecycle/digest.js +143 -0
  352. package/dist/lifecycle/disruption.js +135 -0
  353. package/dist/lifecycle/gate-applied.js +113 -0
  354. package/dist/lifecycle/gate-audit.js +341 -0
  355. package/dist/lifecycle/gate-ledger-select.js +89 -0
  356. package/dist/lifecycle/gate-ledger.d.ts +8 -0
  357. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  358. package/dist/lifecycle/gate-ledger.js +193 -0
  359. package/dist/lifecycle/gate-origin.js +117 -0
  360. package/dist/lifecycle/gate-pending.js +58 -0
  361. package/dist/lifecycle/git.js +1182 -0
  362. package/dist/lifecycle/identity.js +58 -0
  363. package/dist/lifecycle/index.js +26 -0
  364. package/dist/lifecycle/lease.js +283 -0
  365. package/dist/lifecycle/ledger-port.js +1 -0
  366. package/dist/lifecycle/legacy-digest.js +91 -0
  367. package/dist/lifecycle/live-diff.js +274 -0
  368. package/dist/lifecycle/local-note.js +15 -0
  369. package/dist/lifecycle/member-ledger.js +122 -0
  370. package/dist/lifecycle/observation-baseline.js +155 -0
  371. package/dist/lifecycle/observe.js +375 -0
  372. package/dist/lifecycle/oras-referrer-lookup.js +82 -0
  373. package/dist/lifecycle/override-ledger.js +54 -0
  374. package/dist/lifecycle/plan-digest.js +110 -0
  375. package/dist/lifecycle/plan-ledger.js +129 -0
  376. package/dist/lifecycle/receipt-plan.js +192 -0
  377. package/dist/lifecycle/release-ledger.js +155 -0
  378. package/dist/lifecycle/release-read.js +64 -0
  379. package/dist/lifecycle/replay.js +193 -0
  380. package/dist/lifecycle/rollback.js +102 -0
  381. package/dist/lifecycle/run-ledger.js +183 -0
  382. package/dist/lifecycle/scenario-eval.js +204 -0
  383. package/dist/lifecycle/scenario.js +214 -0
  384. package/dist/lifecycle/snapshot.js +239 -0
  385. package/dist/lifecycle/status.js +447 -0
  386. package/dist/lifecycle/symptoms.js +117 -0
  387. package/dist/lifecycle/teardown.js +255 -0
  388. package/dist/lifecycle/types.js +1 -0
  389. package/dist/lifecycle/unobserved-gate.js +33 -0
  390. package/dist/lifecycle/wave-plans.js +68 -0
  391. package/dist/lifecycle/work-item-id.js +36 -0
  392. package/dist/lifecycle/work-lease.js +393 -0
  393. package/dist/lint/component-checks.js +87 -0
  394. package/dist/lint/config.js +483 -0
  395. package/dist/lint/declarative.js +122 -0
  396. package/dist/lint/discover.d.ts.map +1 -1
  397. package/dist/lint/discover.js +138 -0
  398. package/dist/lint/engine.js +246 -0
  399. package/dist/lint/knowledge-checks.js +64 -0
  400. package/dist/lint/named-checks.js +22 -0
  401. package/dist/lint/output-checks.js +87 -0
  402. package/dist/lint/output-docs.js +163 -0
  403. package/dist/lint/parser.js +33 -0
  404. package/dist/lint/pipeline-change-gate.js +70 -0
  405. package/dist/lint/policy-import.d.ts +1 -1
  406. package/dist/lint/policy-import.d.ts.map +1 -1
  407. package/dist/lint/policy-import.js +62 -0
  408. package/dist/lint/policy-sandbox.js +86 -0
  409. package/dist/lint/policy.js +122 -0
  410. package/dist/lint/post-synth.js +87 -0
  411. package/dist/lint/presets/relaxed.json +26 -0
  412. package/dist/lint/presets/strict.json +24 -24
  413. package/dist/lint/receipt-checks.js +83 -0
  414. package/dist/lint/rule-loader.d.ts.map +1 -1
  415. package/dist/lint/rule-loader.js +89 -0
  416. package/dist/lint/rule-registry.js +86 -0
  417. package/dist/lint/rule.js +1 -0
  418. package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.js +7 -0
  419. package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.js +7 -0
  420. package/dist/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.js +9 -0
  421. package/dist/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.js +11 -0
  422. package/dist/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.js +9 -0
  423. package/dist/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.js +25 -0
  424. package/dist/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.js +8 -0
  425. package/dist/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.js +21 -0
  426. package/dist/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.js +8 -0
  427. package/dist/lint/rules/__fixtures__/comp/comp003/pass/agent-turn.component.js +24 -0
  428. package/dist/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.js +17 -0
  429. package/dist/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.js +8 -0
  430. package/dist/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.js +18 -0
  431. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.js +20 -0
  432. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.js +8 -0
  433. package/dist/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.js +12 -0
  434. package/dist/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.js +16 -0
  435. package/dist/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.js +8 -0
  436. package/dist/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.js +12 -0
  437. package/dist/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.js +11 -0
  438. package/dist/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.js +11 -0
  439. package/dist/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.js +10 -0
  440. package/dist/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.js +16 -0
  441. package/dist/lint/rules/comp/comp001-publishes-never-applies.js +69 -0
  442. package/dist/lint/rules/comp/comp002-dangling-wiring-ref.js +84 -0
  443. package/dist/lint/rules/comp/comp003-mutating-no-rollback.js +103 -0
  444. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.js +70 -0
  445. package/dist/lint/rules/comp/comp005-capability-kind-is-noun.js +109 -0
  446. package/dist/lint/rules/comp/comp006-shell-needs-reason.js +49 -0
  447. package/dist/lint/rules/comp/comp007-composition-sprawl.js +64 -0
  448. package/dist/lint/rules/comp/index.js +33 -0
  449. package/dist/lint/rules/comp/support.js +129 -0
  450. package/dist/lint/rules/composite-scope.js +51 -0
  451. package/dist/lint/rules/cor017-composite-name-match.js +93 -0
  452. package/dist/lint/rules/cor018-composite-prefer-lexicon-type.js +136 -0
  453. package/dist/lint/rules/cor021-env-literal-name.js +100 -0
  454. package/dist/lint/rules/cor022-receipt-leaf.js +118 -0
  455. package/dist/lint/rules/cor024-receipt-secret-pointer.js +199 -0
  456. package/dist/lint/rules/declarable-naming-convention.js +62 -0
  457. package/dist/lint/rules/evl001-non-literal-expression.js +66 -0
  458. package/dist/lint/rules/evl002-control-flow-resource.js +69 -0
  459. package/dist/lint/rules/evl003-dynamic-property-access.js +44 -0
  460. package/dist/lint/rules/evl004-spread-non-const.js +94 -0
  461. package/dist/lint/rules/evl005-resource-block-body.js +41 -0
  462. package/dist/lint/rules/evl007-invalid-siblings.js +105 -0
  463. package/dist/lint/rules/evl009-composite-no-constant.js +158 -0
  464. package/dist/lint/rules/evl010-composite-no-transform.js +59 -0
  465. package/dist/lint/rules/evl011-symbolic-in-template.js +106 -0
  466. package/dist/lint/rules/export-required.js +115 -0
  467. package/dist/lint/rules/file-declarable-limit.js +88 -0
  468. package/dist/lint/rules/flat-declarations.js +62 -0
  469. package/dist/lint/rules/index.js +90 -0
  470. package/dist/lint/rules/no-cyclic-declarable-ref.js +138 -0
  471. package/dist/lint/rules/no-redundant-type-import.js +76 -0
  472. package/dist/lint/rules/no-redundant-value-cast.js +41 -0
  473. package/dist/lint/rules/no-string-ref.js +59 -0
  474. package/dist/lint/rules/no-unused-declarable-import.js +75 -0
  475. package/dist/lint/rules/no-unused-declarable.js +142 -0
  476. package/dist/lint/rules/op/index.js +28 -0
  477. package/dist/lint/rules/op/ops012-activity-contract.js +54 -0
  478. package/dist/lint/rules/op/ops013-step-output-ref.js +88 -0
  479. package/dist/lint/rules/op/ops014-converge-rule-refusals.js +114 -0
  480. package/dist/lint/rules/op/ops015-gate-approval.js +45 -0
  481. package/dist/lint/rules/op/support.js +11 -0
  482. package/dist/lint/rules/op/sys010-key-over-plain-http.js +100 -0
  483. package/dist/lint/rules/property-kind.js +56 -0
  484. package/dist/lint/rules/single-concern-file.js +71 -0
  485. package/dist/lint/rules/sys001-no-literal-key.js +60 -0
  486. package/dist/lint/selectors.js +168 -0
  487. package/dist/lint/suppressions.js +129 -0
  488. package/dist/lint/typescript.js +17 -0
  489. package/dist/live-endpoint.js +113 -0
  490. package/dist/live-read-session.js +76 -0
  491. package/dist/lsp/lexicon-providers.js +163 -0
  492. package/dist/lsp/types.js +5 -0
  493. package/dist/managed-fields.js +293 -0
  494. package/dist/mcp/types.js +4 -0
  495. package/dist/notify-verify.js +0 -1
  496. package/dist/notify.js +0 -1
  497. package/dist/notify.schema.json +72 -0
  498. package/dist/observation.js +266 -0
  499. package/dist/okf-read.js +134 -0
  500. package/dist/okf.js +275 -0
  501. package/dist/op/__fixtures__/decide-stub-backend.js +125 -0
  502. package/dist/op/activities/activity-contracts.js +313 -0
  503. package/dist/op/activities/apply.js +582 -0
  504. package/dist/op/activities/build.js +18 -0
  505. package/dist/op/activities/change-coverage.js +40 -0
  506. package/dist/op/activities/change-set.js +64 -0
  507. package/dist/op/activities/converge.js +492 -0
  508. package/dist/op/activities/decide.js +211 -0
  509. package/dist/op/activities/env-teardown.js +110 -0
  510. package/dist/op/activities/factory.js +591 -0
  511. package/dist/op/activities/forge-pull-request.js +82 -0
  512. package/dist/op/activities/gh-host.js +78 -0
  513. package/dist/op/activities/guard-validate.js +165 -0
  514. package/dist/op/activities/http-check.js +40 -0
  515. package/dist/op/activities/index.js +59 -0
  516. package/dist/op/activities/lexicon-upgrade.js +629 -0
  517. package/dist/op/activities/lifecycle.js +109 -0
  518. package/dist/op/activities/pipeline-audit.js +147 -0
  519. package/dist/op/activities/policy.js +26 -0
  520. package/dist/op/activities/predict-behaviour.js +341 -0
  521. package/dist/op/activities/propose-upgrade.js +165 -0
  522. package/dist/op/activities/reconcile.js +997 -0
  523. package/dist/op/activities/shell.js +118 -0
  524. package/dist/op/activities/source-release.js +97 -0
  525. package/dist/op/activities/source-rollback.js +165 -0
  526. package/dist/op/activities/teardown.js +17 -0
  527. package/dist/op/activities/util.js +6 -0
  528. package/dist/op/activities/wait.js +51 -0
  529. package/dist/op/activities/work-evidence.js +35 -0
  530. package/dist/op/activities/workflow-audit.js +133 -0
  531. package/dist/op/activity-contract-registry.js +106 -0
  532. package/dist/op/activity-contract.js +232 -0
  533. package/dist/op/activity-failure.js +31 -0
  534. package/dist/op/activity-profiles.js +129 -0
  535. package/dist/op/activity-registry.js +105 -0
  536. package/dist/op/activity-runtime.js +28 -0
  537. package/dist/op/builders.js +801 -0
  538. package/dist/op/change-signal.js +118 -0
  539. package/dist/op/composites/apply-op.js +151 -0
  540. package/dist/op/composites/behaviour-op.js +65 -0
  541. package/dist/op/composites/converge-op.js +141 -0
  542. package/dist/op/composites/index.js +19 -0
  543. package/dist/op/composites/lexicon-upgrade-op.js +107 -0
  544. package/dist/op/composites/pipeline-audit-op.js +50 -0
  545. package/dist/op/composites/reconcile-op.js +84 -0
  546. package/dist/op/composites/watch-op.js +69 -0
  547. package/dist/op/composites/workflow-audit-op.js +57 -0
  548. package/dist/op/converge-rule.js +205 -0
  549. package/dist/op/cron.js +146 -0
  550. package/dist/op/decide-backend.js +181 -0
  551. package/dist/op/decide-config.js +68 -0
  552. package/dist/op/decide-read-inputs.js +141 -0
  553. package/dist/op/discover.d.ts.map +1 -1
  554. package/dist/op/discover.js +213 -0
  555. package/dist/op/duration.js +21 -0
  556. package/dist/op/emulator-freshness.js +80 -0
  557. package/dist/op/emulator-lifecycle.js +269 -0
  558. package/dist/op/factory.js +83 -0
  559. package/dist/op/gate-approval.js +172 -0
  560. package/dist/op/gate-name.js +86 -0
  561. package/dist/op/gate-plan-context.js +167 -0
  562. package/dist/op/gate-point-run.js +67 -0
  563. package/dist/op/gate-point.js +111 -0
  564. package/dist/op/gate-resume-plan.js +155 -0
  565. package/dist/op/gate-resume.js +31 -0
  566. package/dist/op/gate-review.js +290 -0
  567. package/dist/op/gate-run-locator.js +85 -0
  568. package/dist/op/gate-summary.js +100 -0
  569. package/dist/op/gate-wait.js +56 -0
  570. package/dist/op/gate.js +449 -0
  571. package/dist/op/generate-pipeline.js +124 -0
  572. package/dist/op/index.js +51 -0
  573. package/dist/op/lifecycle-receipt-store.js +45 -0
  574. package/dist/op/local-executor.js +1164 -0
  575. package/dist/op/local-output.js +140 -0
  576. package/dist/op/op-ir.js +317 -0
  577. package/dist/op/op-verb-class.js +131 -0
  578. package/dist/op/op-waves-notify.js +136 -0
  579. package/dist/op/op-waves-run.d.ts +1 -1
  580. package/dist/op/op-waves-run.d.ts.map +1 -1
  581. package/dist/op/op-waves-run.js +1657 -0
  582. package/dist/op/op-waves.js +409 -0
  583. package/dist/op/operator.js +743 -0
  584. package/dist/op/receipt-store.js +94 -0
  585. package/dist/op/resource.js +23 -0
  586. package/dist/op/run-context.js +28 -0
  587. package/dist/op/run-live.js +256 -0
  588. package/dist/op/runtime.js +21 -0
  589. package/dist/op/runtimes/local.js +195 -0
  590. package/dist/op/source-archive.js +131 -0
  591. package/dist/op/step-output-ref.js +397 -0
  592. package/dist/op/steward-beside.js +169 -0
  593. package/dist/op/steward-points.js +138 -0
  594. package/dist/op/steward-turn.js +59 -0
  595. package/dist/op/steward.js +317 -0
  596. package/dist/op/types.js +25 -0
  597. package/dist/op/work-lease-decl.js +81 -0
  598. package/dist/op/work-lease-run.js +393 -0
  599. package/dist/override-gate.js +284 -0
  600. package/dist/owner-chain.js +74 -0
  601. package/dist/ownership.js +92 -0
  602. package/dist/params.js +61 -0
  603. package/dist/plan-summary.js +711 -0
  604. package/dist/point-decision.js +211 -0
  605. package/dist/pr-forge.js +810 -0
  606. package/dist/pr-loop.js +203 -0
  607. package/dist/project-codegen.js +191 -0
  608. package/dist/project-root.js +74 -0
  609. package/dist/project-validation.js +50 -0
  610. package/dist/provenance.js +157 -0
  611. package/dist/pseudo-parameter.js +40 -0
  612. package/dist/reconcile.js +450 -0
  613. package/dist/resource-attributes.js +33 -0
  614. package/dist/runtime-adapter.js +77 -0
  615. package/dist/runtime.js +66 -0
  616. package/dist/secret-materialization.js +153 -0
  617. package/dist/secret-provenance.js +250 -0
  618. package/dist/serializer-walker.js +112 -0
  619. package/dist/serializer.js +1 -0
  620. package/dist/sort.js +45 -0
  621. package/dist/stack-output.js +115 -0
  622. package/dist/telemetry-attribution.js +149 -0
  623. package/dist/terraform/__fixtures__/build-graph.js +63 -0
  624. package/dist/terraform/adopt-state.js +40 -0
  625. package/dist/terraform/aws-resources.js +384 -0
  626. package/dist/terraform/bridge.js +204 -0
  627. package/dist/terraform/carve-provider.js +155 -0
  628. package/dist/terraform/carve.js +138 -0
  629. package/dist/terraform/data-source-shape.js +57 -0
  630. package/dist/terraform/emit-source.js +36 -0
  631. package/dist/terraform/excise.js +123 -0
  632. package/dist/terraform/graduate.js +128 -0
  633. package/dist/terraform/graph.js +435 -0
  634. package/dist/terraform/hcl2json.js +60 -0
  635. package/dist/terraform/manifest.js +149 -0
  636. package/dist/terraform/parse.js +81 -0
  637. package/dist/terraform/providers/aws.js +146 -0
  638. package/dist/terraform/providers/gcp.js +294 -0
  639. package/dist/terraform/providers/index.js +17 -0
  640. package/dist/terraform/providers/kubernetes.js +253 -0
  641. package/dist/terraform/score.js +151 -0
  642. package/dist/terraform/state.js +67 -0
  643. package/dist/terraform/tier-map.js +74 -0
  644. package/dist/terraform/types.js +13 -0
  645. package/dist/terraform/unified-diff.js +132 -0
  646. package/dist/testing.js +295 -0
  647. package/dist/toml-emit.js +153 -0
  648. package/dist/toml-parse.js +355 -0
  649. package/dist/toml-utils.js +60 -0
  650. package/dist/toml.js +428 -0
  651. package/dist/ts-loader.d.ts +46 -0
  652. package/dist/ts-loader.d.ts.map +1 -0
  653. package/dist/ts-loader.js +103 -0
  654. package/dist/types.js +1 -0
  655. package/dist/utils.js +61 -0
  656. package/dist/validation.js +20 -0
  657. package/dist/vendor/js-yaml-load.js +1662 -0
  658. package/dist/workspace/__fixtures__/contract-repo.js +103 -0
  659. package/dist/workspace/__fixtures__/decide-workspace.js +112 -0
  660. package/dist/workspace/__fixtures__/sessions.js +91 -0
  661. package/dist/workspace/__fixtures__/two-member-workspace.js +34 -0
  662. package/dist/workspace/agent-cli.js +99 -0
  663. package/dist/workspace/agent.schema.json +390 -0
  664. package/dist/workspace/answers-ledger.js +89 -0
  665. package/dist/workspace/box-cli.js +142 -0
  666. package/dist/workspace/box-factory-write.js +196 -0
  667. package/dist/workspace/box-factory-write.schema.json +342 -0
  668. package/dist/workspace/box-factory.js +88 -0
  669. package/dist/workspace/box-intent.js +126 -0
  670. package/dist/workspace/box-isolation.js +169 -0
  671. package/dist/workspace/box-listing-write.schema.json +204 -0
  672. package/dist/workspace/box-listing.js +298 -0
  673. package/dist/workspace/box-publish.js +352 -0
  674. package/dist/workspace/box-publish.schema.json +498 -0
  675. package/dist/workspace/box-services.js +39 -0
  676. package/dist/workspace/broker-protocol.js +359 -0
  677. package/dist/workspace/broker-protocol.schema.json +228 -0
  678. package/dist/workspace/change-set.schema.json +460 -0
  679. package/dist/workspace/changes-cli.js +56 -0
  680. package/dist/workspace/changes.js +446 -0
  681. package/dist/workspace/changes.schema.json +642 -0
  682. package/dist/workspace/chant-migrations/chud-lexicon-exit-fly-site.js +198 -0
  683. package/dist/workspace/chant-migrations/chud-lexicon-exit-live-names.js +155 -0
  684. package/dist/workspace/chant-migrations/chud-lexicon-exit-rollback.js +214 -0
  685. package/dist/workspace/chant-migrations/chud-lexicon-exit-ship-inputs.js +180 -0
  686. package/dist/workspace/chant-migrations/chud-lexicon-exit-ship-policy.js +99 -0
  687. package/dist/workspace/chant-migrations/chud-lexicon-exit.js +847 -0
  688. package/dist/workspace/chant-migrations.js +113 -0
  689. package/dist/workspace/check.schema.json +433 -0
  690. package/dist/workspace/checks/box-isolation.js +62 -0
  691. package/dist/workspace/checks/boxes.js +491 -0
  692. package/dist/workspace/checks/diagrams.js +104 -0
  693. package/dist/workspace/checks/generated.js +419 -0
  694. package/dist/workspace/checks/ledgers.js +212 -0
  695. package/dist/workspace/checks/links.js +191 -0
  696. package/dist/workspace/checks/live.js +100 -0
  697. package/dist/workspace/checks/pipelines.js +188 -0
  698. package/dist/workspace/checks/records.js +169 -0
  699. package/dist/workspace/checks.js +426 -0
  700. package/dist/workspace/ci-green-cli.js +125 -0
  701. package/dist/workspace/ci-green-forge.js +83 -0
  702. package/dist/workspace/ci-green-workflow.js +199 -0
  703. package/dist/workspace/ci-green.js +325 -0
  704. package/dist/workspace/ci-last-green.schema.json +158 -0
  705. package/dist/workspace/compose-graph.js +235 -0
  706. package/dist/workspace/compose-reports.js +146 -0
  707. package/dist/workspace/composites.js +264 -0
  708. package/dist/workspace/composites.schema.json +617 -0
  709. package/dist/workspace/conformance/__fixture__/app/package.json +7 -0
  710. package/dist/workspace/conformance/__fixture__/app/src/server.mjs +29 -0
  711. package/dist/workspace/conformance/__fixture__/decisions/decision.kind.mjs +54 -0
  712. package/dist/workspace/conformance/__fixture__/decisions/decision.schema.json +512 -0
  713. package/dist/workspace/conformance/__fixture__/decisions/fix-001-how-the-app-is-deployed.md +40 -0
  714. package/dist/workspace/conformance/__fixture__/delivery/chant.config.ts +7 -0
  715. package/dist/workspace/conformance/__fixture__/delivery/lexicon/index.ts +26 -0
  716. package/dist/workspace/conformance/__fixture__/delivery/package.json +7 -0
  717. package/dist/workspace/conformance/__fixture__/delivery/src/app.component.ts +14 -0
  718. package/dist/workspace/conformance/__fixture__/delivery/src/app.ts +4 -0
  719. package/dist/workspace/conformance/__fixtures__/reference-broker.js +205 -0
  720. package/dist/workspace/conformance/__writer_fixture__/answers/answer.kind.mjs +32 -0
  721. package/dist/workspace/conformance/__writer_fixture__/answers/answer.schema.json +135 -0
  722. package/dist/workspace/conformance/__writer_fixture__/contracts/contract.kind.mjs +37 -0
  723. package/dist/workspace/conformance/__writer_fixture__/contracts/contract.schema.json +213 -0
  724. package/dist/workspace/conformance/__writer_fixture__/decisions/points.json +228 -0
  725. package/dist/workspace/conformance/__writer_fixture__/drivers/driver.kind.mjs +15 -0
  726. package/dist/workspace/conformance/__writer_fixture__/drivers/driver.schema.json +38 -0
  727. package/dist/workspace/conformance/__writer_fixture__/sessions/session.kind.mjs +54 -0
  728. package/dist/workspace/conformance/__writer_fixture__/sessions/session.schema.json +289 -0
  729. package/dist/workspace/conformance/__writer_fixture__/work/W-001-the-writer-suite-works-this-item.md +25 -0
  730. package/dist/workspace/conformance/__writer_fixture__/work/work.kind.mjs +60 -0
  731. package/dist/workspace/conformance/__writer_fixture__/work/work.schema.json +603 -0
  732. package/dist/workspace/conformance/broker.js +736 -0
  733. package/dist/workspace/conformance/index.js +673 -0
  734. package/dist/workspace/conformance/vitest.js +108 -0
  735. package/dist/workspace/conformance/writer.js +1080 -0
  736. package/dist/workspace/decide.js +879 -0
  737. package/dist/workspace/decision-points.schema.json +135 -135
  738. package/dist/workspace/declaration-write-cli.js +74 -0
  739. package/dist/workspace/declaration-write.js +238 -0
  740. package/dist/workspace/declaration.js +938 -0
  741. package/dist/workspace/declaration.schema.json +1413 -1413
  742. package/dist/workspace/declared-kinds.js +106 -0
  743. package/dist/workspace/environments.js +164 -0
  744. package/dist/workspace/evidence.schema.json +279 -0
  745. package/dist/workspace/export-cli.js +185 -0
  746. package/dist/workspace/export.js +499 -0
  747. package/dist/workspace/factory-rules.js +175 -0
  748. package/dist/workspace/generated-files.js +92 -0
  749. package/dist/workspace/glob.js +45 -0
  750. package/dist/workspace/graph-cache.js +352 -0
  751. package/dist/workspace/graph-cli.js +348 -0
  752. package/dist/workspace/graph.schema.json +1338 -0
  753. package/dist/workspace/identity-gate-rule.d.ts +65 -0
  754. package/dist/workspace/identity-gate-rule.d.ts.map +1 -0
  755. package/dist/workspace/identity-gate-rule.js +75 -0
  756. package/dist/workspace/identity.d.ts +4 -2
  757. package/dist/workspace/identity.d.ts.map +1 -1
  758. package/dist/workspace/identity.js +126 -0
  759. package/dist/workspace/import.js +283 -0
  760. package/dist/workspace/init.js +620 -0
  761. package/dist/workspace/intent-cli.js +263 -0
  762. package/dist/workspace/intent-joins.js +201 -0
  763. package/dist/workspace/intent-record.js +352 -0
  764. package/dist/workspace/intent-record.schema.json +864 -0
  765. package/dist/workspace/intent.js +1582 -0
  766. package/dist/workspace/intent.schema.json +2420 -0
  767. package/dist/workspace/json-edit.js +221 -0
  768. package/dist/workspace/jsonc.js +235 -0
  769. package/dist/workspace/kind-readers.js +103 -0
  770. package/dist/workspace/kinds.js +587 -0
  771. package/dist/workspace/lexicon-symbols.js +112 -0
  772. package/dist/workspace/lineage-adopt-cli.js +102 -0
  773. package/dist/workspace/lineage-adopt.js +360 -0
  774. package/dist/workspace/lineage-check.js +282 -0
  775. package/dist/workspace/lineage-cli.js +121 -0
  776. package/dist/workspace/lineage-hash-index.js +284 -0
  777. package/dist/workspace/lineage-init.js +507 -0
  778. package/dist/workspace/lineage-lock.js +387 -0
  779. package/dist/workspace/lineage-merge.js +45 -0
  780. package/dist/workspace/lineage-migrations.d.ts.map +1 -1
  781. package/dist/workspace/lineage-migrations.js +329 -0
  782. package/dist/workspace/lineage-provenance.js +36 -0
  783. package/dist/workspace/lineage-update.js +138 -0
  784. package/dist/workspace/lineage-upgrade-cli.js +131 -0
  785. package/dist/workspace/lineage-upgrade.js +889 -0
  786. package/dist/workspace/lineage-vendor.js +171 -0
  787. package/dist/workspace/lineage-version.js +128 -0
  788. package/dist/workspace/lineage-versions.js +275 -0
  789. package/dist/workspace/links.js +330 -0
  790. package/dist/workspace/ls-generated.js +95 -0
  791. package/dist/workspace/ls.js +277 -0
  792. package/dist/workspace/ls.schema.json +333 -0
  793. package/dist/workspace/member-commands.js +508 -0
  794. package/dist/workspace/member-handles.js +216 -0
  795. package/dist/workspace/member-pipeline.js +258 -0
  796. package/dist/workspace/member-run.js +117 -0
  797. package/dist/workspace/member-write.schema.json +193 -0
  798. package/dist/workspace/nested-graph.js +156 -0
  799. package/dist/workspace/nesting.js +38 -0
  800. package/dist/workspace/patch.js +301 -0
  801. package/dist/workspace/patch.schema.json +321 -0
  802. package/dist/workspace/pin-cli.js +55 -0
  803. package/dist/workspace/pin-integrity.js +100 -0
  804. package/dist/workspace/plan-summary.schema.json +155 -0
  805. package/dist/workspace/point-answer.schema.json +129 -129
  806. package/dist/workspace/points-cli.js +291 -0
  807. package/dist/workspace/points-write.schema.json +660 -0
  808. package/dist/workspace/points.js +521 -0
  809. package/dist/workspace/points.schema.json +916 -0
  810. package/dist/workspace/pr-report.schema.json +108 -0
  811. package/dist/workspace/principal-classes.d.ts +3 -14
  812. package/dist/workspace/principal-classes.d.ts.map +1 -1
  813. package/dist/workspace/principal-classes.js +245 -0
  814. package/dist/workspace/reason-codes.js +326 -0
  815. package/dist/workspace/record-assets.js +151 -0
  816. package/dist/workspace/record-decided.js +105 -0
  817. package/dist/workspace/record-sessions.js +96 -0
  818. package/dist/workspace/record-source.js +114 -0
  819. package/dist/workspace/records-amend.schema.json +284 -0
  820. package/dist/workspace/records-checkout.js +76 -0
  821. package/dist/workspace/records-cli.js +707 -0
  822. package/dist/workspace/records-close.js +116 -0
  823. package/dist/workspace/records-close.schema.json +278 -0
  824. package/dist/workspace/records-new.schema.json +202 -0
  825. package/dist/workspace/records-review.schema.json +367 -0
  826. package/dist/workspace/records-since.js +317 -0
  827. package/dist/workspace/records-since.schema.json +218 -0
  828. package/dist/workspace/records-write.js +1229 -0
  829. package/dist/workspace/records.js +1345 -0
  830. package/dist/workspace/records.schema.json +604 -0
  831. package/dist/workspace/reference-kinds/app/package.json +10 -0
  832. package/dist/workspace/reference-kinds/app/workspace-kinds.json +45 -0
  833. package/dist/workspace/returns.js +303 -0
  834. package/dist/workspace/root-refusal.js +75 -0
  835. package/dist/workspace/run-statement.schema.json +622 -0
  836. package/dist/workspace/runs-cli.js +584 -0
  837. package/dist/workspace/runs-write.schema.json +994 -0
  838. package/dist/workspace/runs.js +708 -0
  839. package/dist/workspace/runs.schema.json +1257 -0
  840. package/dist/workspace/runtimes.js +76 -0
  841. package/dist/workspace/session-kinds.js +83 -0
  842. package/dist/workspace/signers.schema.json +206 -0
  843. package/dist/workspace/source-block.js +125 -0
  844. package/dist/workspace/squash.js +177 -0
  845. package/dist/workspace/status-gates.js +162 -0
  846. package/dist/workspace/status-stewards.js +330 -0
  847. package/dist/workspace/status.js +514 -0
  848. package/dist/workspace/status.schema.json +998 -0
  849. package/dist/workspace/steward-index.js +191 -0
  850. package/dist/workspace/symbols.js +188 -0
  851. package/dist/workspace/template-manifest.js +227 -0
  852. package/dist/workspace/template-pins.js +115 -0
  853. package/dist/workspace/trailer-joins.js +65 -0
  854. package/dist/workspace/trailers.js +111 -0
  855. package/dist/workspace/tree.js +136 -0
  856. package/dist/workspace/trust/attestor.js +63 -0
  857. package/dist/workspace/trust/dsse.js +108 -0
  858. package/dist/workspace/trust/evidence-cli.js +175 -0
  859. package/dist/workspace/trust/evidence.js +161 -0
  860. package/dist/workspace/trust/gate-seal.js +226 -0
  861. package/dist/workspace/trust/policy.js +190 -0
  862. package/dist/workspace/trust/provenance.js +180 -0
  863. package/dist/workspace/trust/rotation.js +298 -0
  864. package/dist/workspace/trust/run-commits.js +101 -0
  865. package/dist/workspace/trust/run-statement.js +182 -0
  866. package/dist/workspace/trust/seal.js +272 -0
  867. package/dist/workspace/trust/signers-cli.js +152 -0
  868. package/dist/workspace/trust/ssh-commit.js +178 -0
  869. package/dist/workspace/trust/test-repo.js +118 -0
  870. package/dist/workspace/trust/trust-files.js +193 -0
  871. package/dist/workspace/trust/verify-cli.js +63 -0
  872. package/dist/workspace/trust/verify.js +192 -0
  873. package/dist/workspace/which-chant.js +141 -0
  874. package/dist/workspace/wip-cli.js +95 -0
  875. package/dist/workspace/wip-write.schema.json +504 -0
  876. package/dist/workspace/wip.js +631 -0
  877. package/dist/workspace/wip.schema.json +334 -0
  878. package/dist/workspace/work-cli.js +448 -0
  879. package/dist/workspace/work-evidence.js +122 -0
  880. package/dist/workspace/work-evidence.schema.json +222 -0
  881. package/dist/workspace/work-history.schema.json +421 -0
  882. package/dist/workspace/work-lease.schema.json +246 -0
  883. package/dist/workspace/work-size.js +77 -0
  884. package/dist/workspace/work.js +283 -0
  885. package/dist/workspace/workspace-kinds.schema.json +259 -259
  886. package/dist/workspace/workspace-principals.schema.json +53 -53
  887. package/dist/workspace/write-lock-cli.js +105 -0
  888. package/dist/workspace/write-lock.js +424 -0
  889. package/dist/workspace/write-lock.schema.json +172 -0
  890. package/dist/workspace/write-scope.js +484 -0
  891. package/dist/yaml.js +459 -0
  892. package/package.json +2 -2
  893. package/src/cli/commands/check-lexicon-plugin.ts +2 -0
  894. package/src/cli/commands/lint.ts +36 -6
  895. package/src/cli/commands/migrate.ts +2 -0
  896. package/src/cli/compiled-cli.e2e.test.ts +165 -0
  897. package/src/cli/main.ts +121 -27
  898. package/src/cli/mcp/workspace-tools.ts +1 -1
  899. package/src/codegen/pinned-upgrade.ts +2 -0
  900. package/src/components/discover.ts +2 -0
  901. package/src/components/sandbox/driver.ts +3 -1
  902. package/src/config-import.ts +3 -0
  903. package/src/discovery/fold-import.ts +23 -14
  904. package/src/discovery/import.ts +2 -0
  905. package/src/discovery/sandbox/driver.ts +3 -1
  906. package/src/gate-decision-bundle.test.ts +3 -2
  907. package/src/gate-decision-identity.test.ts +176 -0
  908. package/src/gate-decision.ts +100 -22
  909. package/src/lexicon-module.ts +3 -0
  910. package/src/lifecycle/gate-ledger.ts +8 -0
  911. package/src/lint/config.ts +1 -1
  912. package/src/lint/discover.ts +28 -8
  913. package/src/lint/policy-import.ts +4 -1
  914. package/src/lint/rule-loader.ts +2 -0
  915. package/src/op/discover.ts +3 -0
  916. package/src/op/op-waves-point.test.ts +1 -0
  917. package/src/op/op-waves-run.ts +5 -4
  918. package/src/op/op-waves.test.ts +14 -0
  919. package/src/ts-loader.test.ts +23 -0
  920. package/src/ts-loader.ts +122 -0
  921. package/src/workspace/chant-migrations/chud-lexicon-exit.ts +1 -1
  922. package/src/workspace/declaration.ts +1 -1
  923. package/src/workspace/identity-gate-rule.ts +109 -0
  924. package/src/workspace/identity.ts +8 -18
  925. package/src/workspace/kinds.ts +1 -1
  926. package/src/workspace/lineage-migrations.ts +2 -0
  927. package/src/workspace/points.ts +1 -1
  928. package/src/workspace/principal-classes.ts +5 -30
@@ -0,0 +1,920 @@
1
+ import { build } from "../../build.js";
2
+ import { loadChantConfigUpward, resolveOwnershipMarker, resolveOwnershipEnv, ownershipEnvDisagreement, isOwnershipParamRef, resolveKnowledgeDir, } from "../../config.js";
3
+ import { resolveBuildModes, resolveProjectBuildOptions } from "../build-options.js";
4
+ import { resolveTelemetryAttribution } from "../../telemetry-attribution.js";
5
+ import { loadOkfBundle } from "../../okf-read.js";
6
+ import { unknownEnvError } from "../../env.js";
7
+ import { resolveCliBuildParams } from "../build-params-cli.js";
8
+ import { runPostSynthChecks } from "../../lint/post-synth.js";
9
+ import { loadActivityContracts } from "../../op/activity-contract-registry.js";
10
+ import { isOpEntity } from "../../op/resource.js";
11
+ import { serializeOpIR } from "../../op/op-ir.js";
12
+ import { opUsesDeprecatedGateKey, DEPRECATED_GATE_KEY_WARNING } from "../../op/gate-name.js";
13
+ import { coreReceiptChecks } from "../../lint/receipt-checks.js";
14
+ import { coreOutputChecks } from "../../lint/output-checks.js";
15
+ import { coreKnowledgeChecks } from "../../lint/knowledge-checks.js";
16
+ import { applyConfiguredSeverity, applyConfiguredPreset, resolvePresetIds } from "../../lint/config.js";
17
+ import { applyInlineSuppressions } from "../../lint/suppressions.js";
18
+ import { coreOpChecks } from "../../lint/rules/op/index.js";
19
+ import { loadPolicyChecks } from "../../lint/policy.js";
20
+ import { armSandboxPolicyExecution, runProjectPolicies } from "../../lint/policy-sandbox.js";
21
+ import { sortedJsonReplacer } from "../../utils.js";
22
+ import { rankFoldBlockers, toCollapsedFormat } from "../../discovery/fold-rank.js";
23
+ import { formatError, formatWarning, formatSuccess, formatBold, formatInfo } from "../format.js";
24
+ import { writeFileSync, mkdirSync } from "fs";
25
+ import { resolve, dirname, join, relative } from "path";
26
+ import { watchDirectory, formatTimestamp, formatChangedFiles } from "../watch.js";
27
+ /**
28
+ * Resolve the output format for `chant build`.
29
+ *
30
+ * When `--format` is not given, infer it from the `-o` file extension
31
+ * (`.yaml`/`.yml` → yaml, `.json` → json); fall back to json when there is no
32
+ * extension to infer from. An explicit `--format` always wins, but a mismatch
33
+ * with the output extension is surfaced as a warning.
34
+ */
35
+ export function resolveBuildFormat(explicit, output) {
36
+ const inferred = output
37
+ ? /\.ya?ml$/i.test(output)
38
+ ? "yaml"
39
+ : /\.json$/i.test(output)
40
+ ? "json"
41
+ : undefined
42
+ : undefined;
43
+ if (explicit === "json" || explicit === "yaml") {
44
+ if (inferred && inferred !== explicit) {
45
+ return {
46
+ format: explicit,
47
+ warning: `Output file "${output}" looks like ${inferred} but --format ${explicit} was given; writing ${explicit}.`,
48
+ };
49
+ }
50
+ return { format: explicit };
51
+ }
52
+ return { format: inferred ?? "json" };
53
+ }
54
+ /**
55
+ * Run each lexicon plugin's own post-synth checks over a build result, each
56
+ * plugin seeing only its own lexicon's output. Shared by `chant build` and
57
+ * `chant lint` (#3750), so the two run the same checks over the same scoping;
58
+ * each caller then applies `lint.presets`, `lint.rules` and inline
59
+ * suppressions its own way. A plugin with no checks yields no entry.
60
+ */
61
+ export function runLexiconPostSynthChecks(plugins, result, env, opts) {
62
+ const batches = [];
63
+ for (const plugin of plugins) {
64
+ if (!plugin.postSynthChecks)
65
+ continue;
66
+ const checks = plugin.postSynthChecks();
67
+ if (checks.length === 0)
68
+ continue;
69
+ // Scope outputs to this plugin's lexicon so cross-lexicon outputs don't
70
+ // interfere. Outputs are keyed by the serializer's lexicon name (the
71
+ // build partition key), which differs from plugin.name for a dialect like
72
+ // forgejo (plugin "forgejo", serializer "github").
73
+ const outputKey = plugin.serializer.name;
74
+ const scopedOutputs = new Map();
75
+ const pluginOutput = result.outputs.get(outputKey);
76
+ if (pluginOutput !== undefined) {
77
+ scopedOutputs.set(outputKey, pluginOutput);
78
+ }
79
+ const scopedResult = { ...result, outputs: scopedOutputs };
80
+ batches.push({ plugin, diagnostics: runPostSynthChecks(checks, scopedResult, env, opts) });
81
+ }
82
+ return batches;
83
+ }
84
+ /**
85
+ * Execute the build command
86
+ */
87
+ export async function buildCommand(options) {
88
+ const errors = [];
89
+ const warnings = [];
90
+ // Resolve the path
91
+ const infraPath = resolve(options.path);
92
+ // Resolve opt-in ownership marking from project config. chant #1117 — walks
93
+ // up from the infra dir to the project root (`loadChantConfigUpward`), not
94
+ // just the infra dir's immediate parent: a project whose stacks live two or
95
+ // more levels below `chant.config.ts` (a `src/<stack>` layout) otherwise
96
+ // never finds the root config at all, and every declared
97
+ // `buildParams`/`ownership`/`lint.policies` setting silently falls back to
98
+ // its default.
99
+ const loaded = await loadChantConfigUpward(infraPath);
100
+ const config = loaded.config;
101
+ // The ownership marker is resolved further down, after build parameters —
102
+ // `ownership.env` may reference one (#1396).
103
+ // Project-authored organizational policy checks (lint.policies), run over the
104
+ // resolved resources during build. Resolve paths relative to the config dir.
105
+ const configDir = loaded.configPath ? dirname(loaded.configPath) : infraPath;
106
+ const policies = config.lint?.policies ?? [];
107
+ // #1022/#1134 (fold) and #1045 Phase 2 (sandbox) — an explicit CLI flag
108
+ // (--fold/--no-fold, --sandbox) wins over `chant.config.ts`'s
109
+ // `build.fold`/`build.sandbox`, which wins over the defaults (fold on,
110
+ // sandbox off). Resolved here rather than with the rest of the build
111
+ // options below because arming sandboxed policy execution has to happen
112
+ // before any policy module could be loaded — see #2002 in ../build-options.ts.
113
+ const modes = resolveBuildModes(config, { fold: options.fold, sandbox: options.sandbox });
114
+ const { fold, sandbox } = modes;
115
+ // #1131 — arm sandboxed policy execution from the RESOLVED value, before any
116
+ // policy module could be loaded. Resolved, not `options.sandbox`, because
117
+ // policies have none of the config's bootstrap limit: they are loaded long
118
+ // after `build.sandbox` is known, so a config-only opt-in sandboxes them just
119
+ // as the CLI flag does. Arming (rather than threading a flag to each caller)
120
+ // makes `loadPolicyChecks` refuse process-wide — a call site that forgot to
121
+ // ask gets a loud error instead of quietly running project code here.
122
+ if (sandbox)
123
+ armSandboxPolicyExecution();
124
+ // Unsandboxed, the policy pack is still loaded HERE, before the build — a
125
+ // policy path that doesn't resolve has always failed the command up front,
126
+ // including when the build itself then fails, and #1131 does not change that.
127
+ // Sandboxed, there is nothing to load in this process at all.
128
+ const preloadedPolicyChecks = !sandbox && policies.length > 0 ? await loadPolicyChecks([...policies], configDir) : undefined;
129
+ // #1113 — the bootstrap limit, surfaced rather than left implicit. Reading
130
+ // `build.sandbox` out of `chant.config.ts` requires evaluating that file, so
131
+ // a config-only opt-in cannot have covered its own evaluation; only the CLI
132
+ // flag, known before any config is touched, arms `../config-sandbox.ts`.
133
+ // Say so instead of letting two different boundaries share one word.
134
+ if (sandbox && !options.sandbox && loaded.configPath?.endsWith(".ts")) {
135
+ warnings.push(formatWarning({
136
+ message: `build.sandbox is enabled by ${loaded.configPath}, but that file was itself evaluated in this process — reading the setting requires running the config. Pass --sandbox on the command line to evaluate chant.config.ts inside the boundary too.`,
137
+ }));
138
+ }
139
+ // #1064 (factored into ../build-params-cli.ts's resolveCliBuildParams by
140
+ // #1108, so the component deploy driver runs the identical sequence) —
141
+ // resolve declared build-time parameters (chant.config.ts's buildParams)
142
+ // against this invocation's --param/--params-file/declared env mapping,
143
+ // BEFORE calling build() — a resolution failure (an unknown name, a
144
+ // missing required value, a type/enum mismatch) is reported as a chant
145
+ // build error naming the parameter, never a thrown error from inside user
146
+ // source (which is what a hand-rolled `tierFromEnv()`-style validator in a
147
+ // project's own `params.ts` does before migrating to this mechanism). Also
148
+ // logs a one-line count on success, or every resolved value (`[param] name =
149
+ // value (source)`) under --verbose (#1424).
150
+ const paramsResolution = resolveCliBuildParams(config.buildParams, {
151
+ cli: options.params,
152
+ paramsFile: options.paramsFile,
153
+ verbose: options.verbose,
154
+ });
155
+ if (!paramsResolution.success) {
156
+ errors.push(...paramsResolution.errors);
157
+ return { success: false, resourceCount: 0, fileCount: 0, errors, warnings };
158
+ }
159
+ // chant #1117 — a project that declares buildParams but resolves NONE of
160
+ // them for this build is the exact shape that let a silent misresolution run
161
+ // for two releases: the discovered config wasn't the one the project author
162
+ // expected (a stale --path, a workspace boundary that stopped the walk
163
+ // short), or every declared parameter's `env:` var went unset, and either
164
+ // way every `params.<name>` read silently falls back to `undefined` — with
165
+ // no error (an all-`required: false` declaration resolves successfully to
166
+ // an empty set). Warn, naming the config path this build actually
167
+ // discovered, so a mismatch is visible instead of silent.
168
+ if (Object.keys(config.buildParams ?? {}).length > 0 &&
169
+ paramsResolution.provenance.length === 0) {
170
+ warnings.push(formatWarning({
171
+ message: `chant.config.ts declares buildParams${loaded.configPath ? ` (${loaded.configPath})` : ""}, but none resolved for this build — every params.<name> read will be undefined. Pass --param/--params-file, or check that this is the config you expect.`,
172
+ }));
173
+ }
174
+ // #1396 — opt-in ownership marking, resolved AFTER build parameters so
175
+ // `ownership.env: { param: "env" }` takes the value `--param env=prod` (or
176
+ // the declared env mapping, or the default) bound to params.env — one
177
+ // source for the label and the marker. A reference that cannot be
178
+ // satisfied is a build error, not a marker silently stamped without an env.
179
+ let ownership;
180
+ // Environment for policy evaluation: explicit --env wins, else ownership.env
181
+ // (read even when marking itself is off, so policy can still branch on it).
182
+ let env;
183
+ try {
184
+ ownership = resolveOwnershipMarker(config, paramsResolution.provenance);
185
+ env = options.env ?? resolveOwnershipEnv(config, paramsResolution.provenance);
186
+ }
187
+ catch (err) {
188
+ errors.push(formatError({ message: err instanceof Error ? err.message : String(err) }));
189
+ return { success: false, resourceCount: 0, fileCount: 0, errors, warnings };
190
+ }
191
+ // A literal `ownership.env` next to an `env` build parameter that resolved
192
+ // to something else is the silent divergence #1396 reports — say so.
193
+ const disagreement = ownershipEnvDisagreement(config, paramsResolution.provenance);
194
+ if (disagreement)
195
+ warnings.push(formatWarning({ message: disagreement }));
196
+ // #1221 — dynamic-env legality. `--env` is validated against the declared
197
+ // `environments` in cli/main.ts; a param-bound `ownership.env` supplied via
198
+ // `--param env=<value>` reached here unchecked, so `--param env=pord`
199
+ // stamped a marker for an environment the project never declared. Same
200
+ // check, same site of truth: literal entries match by equality, entries
201
+ // containing `*` (e.g. `"pr-*"`) match as glob patterns, so an unbounded
202
+ // family like per-PR environments is declarable without listing each name.
203
+ if (isOwnershipParamRef(config.ownership?.env)) {
204
+ const dynamicEnvErr = unknownEnvError(env, config.environments);
205
+ if (dynamicEnvErr) {
206
+ errors.push(formatError({
207
+ message: dynamicEnvErr,
208
+ hint: 'Declare it in chant.config `environments` (a "pr-*" pattern entry covers a dynamic family), or pass a declared value.',
209
+ }));
210
+ return { success: false, resourceCount: 0, fileCount: 0, errors, warnings };
211
+ }
212
+ }
213
+ // Run the build. #2002 — every option comes from the shared assembler
214
+ // (../build-options.ts), which `evaluateProjectPolicies` calls too, so the
215
+ // `policyGate` step decides on the same project this command builds.
216
+ const telemetry = await resolveTelemetryAttribution(configDir, config, env);
217
+ const runBuild = (serializers) => build(infraPath, serializers, undefined, resolveProjectBuildOptions({
218
+ config,
219
+ configDir,
220
+ plugins: options.plugins,
221
+ modes,
222
+ ownership,
223
+ buildParams: paramsResolution.provenance,
224
+ telemetry,
225
+ }));
226
+ let result;
227
+ if (options.sharedBuild) {
228
+ const shared = options.sharedBuild;
229
+ shared.result ?? (shared.result = runBuild(shared.serializers));
230
+ const full = await shared.result;
231
+ const own = new Set(options.serializers.map((x) => x.name));
232
+ result = { ...full, outputs: new Map([...full.outputs].filter(([name]) => own.has(name))) };
233
+ }
234
+ else {
235
+ result = await runBuild(options.serializers);
236
+ }
237
+ // #1022 — report per-file fold vs run so it's visible what still runs.
238
+ // #1424 — one line by default; the per-file lines and their reasons are
239
+ // --verbose. A file that ran is the expected outcome for source that
240
+ // computes values in functions, and a dozen "is not foldable" notes read
241
+ // like errors to someone meeting the project for the first time.
242
+ if (fold && result.foldDecisions.length > 0) {
243
+ if (options.verbose) {
244
+ for (const decision of result.foldDecisions) {
245
+ const rel = relative(infraPath, decision.file) || decision.file;
246
+ const detail = decision.mode === "fold"
247
+ ? `${decision.resourceCount ?? 0} resource(s), no module execution`
248
+ : (decision.reason ?? "fell back to run");
249
+ console.error(formatInfo(`[fold:${decision.mode}] ${rel} — ${detail}`));
250
+ }
251
+ }
252
+ else {
253
+ console.error(formatInfo(summarizeFoldDecisions(result.foldDecisions)));
254
+ }
255
+ }
256
+ // chant #1083 — rank fold blockers by dominator retained-count over the
257
+ // forward import-failure graph, and report the reverse-taint bucket
258
+ // (#1044) separately. Opt-in (`--fold-rank`) and independent of
259
+ // `--verbose`: the per-file listing above says WHAT ran; this says WHICH
260
+ // of those files is worth fixing first.
261
+ if (fold && (options.foldRank || options.foldRankCollapsedFile) && result.foldDecisions.length > 0) {
262
+ const ranking = await rankFoldBlockers(result.foldDecisions);
263
+ console.error(formatInfo(formatFoldRanking(ranking, infraPath)));
264
+ if (options.foldRankCollapsedFile) {
265
+ const collapsedPath = resolve(options.foldRankCollapsedFile);
266
+ mkdirSync(dirname(collapsedPath), { recursive: true });
267
+ const lines = toCollapsedFormat(ranking, { relativeTo: infraPath });
268
+ writeFileSync(collapsedPath, lines.length > 0 ? `${lines.join("\n")}\n` : "");
269
+ console.error(formatInfo(`[fold-rank] collapsed-format export: ${collapsedPath} (${lines.length} line(s))`));
270
+ }
271
+ }
272
+ // Format errors — grouped by message, because one refusal can surface once
273
+ // per resource file. A project whose params module throws (a guard like
274
+ // "this seam cannot back that tier") throws in EVERY file that imports it,
275
+ // and fourteen copies of one sentence bury the sentence
276
+ // (INTENTIUS/fountain-ops#62). The first file to hit it is named, the rest
277
+ // become a count; errors with genuinely different messages keep their own
278
+ // lines, and a message that appears once is printed exactly as before.
279
+ const byMessage = new Map();
280
+ for (const error of result.errors) {
281
+ const key = `${error.name ?? ""}:${error.message}`;
282
+ const seen = byMessage.get(key);
283
+ if (seen)
284
+ seen.files += 1;
285
+ else
286
+ byMessage.set(key, { first: error, files: 1 });
287
+ }
288
+ for (const { first: error, files } of byMessage.values()) {
289
+ const formatted = formatError({
290
+ file: "file" in error ? error.file : undefined,
291
+ line: "line" in error ? error.line : undefined,
292
+ column: "column" in error ? error.column : undefined,
293
+ message: files > 1 ? `${error.message} (and the same from ${files - 1} more files)` : error.message,
294
+ name: error.name,
295
+ });
296
+ errors.push(formatted);
297
+ }
298
+ // Format warnings
299
+ for (const warning of result.warnings) {
300
+ warnings.push(formatWarning({ message: warning }));
301
+ }
302
+ // Run post-synth checks from plugins — each plugin only sees its own lexicon's output
303
+ //
304
+ // chant #1138 — every diagnostic collected below (a lexicon-shipped check's
305
+ // AND a project's `lint.policies`') is resolved against `lint.rules` before
306
+ // it becomes an error/warning line, through the exact same
307
+ // `applyConfiguredSeverity` (../../lint/post-synth.ts) that keys off
308
+ // `diag.checkId` the way `lintCommand` keys an AST/COMP* diagnostic off its
309
+ // rule id — so `lint.rules: { WAW019: "off" }` suppresses a post-synth
310
+ // finding just as it suppresses a pre-synth one. A finding it suppresses is
311
+ // counted, not dropped silently — see `suppressedPostSynthCount` below.
312
+ //
313
+ // chant #2111: every batch also goes through `applyInlineSuppressions`
314
+ // right after, so a `# chant-ignore` comment on an entity (terraform's HCL
315
+ // blocks today; any lexicon that attaches `suppressions` to its own
316
+ // entities tomorrow) suppresses identically regardless of which phase
317
+ // produced the diagnostic. Same counted-not-dropped contract, in its own
318
+ // `inlineSuppressedCount`, plus `suppressionMeta` for directives that are
319
+ // themselves worth a finding (expired, misplaced, denied by `ignorable: false`).
320
+ let suppressedPostSynthCount = 0;
321
+ let inlineSuppressedCount = 0;
322
+ const suppressionMeta = [];
323
+ // A rule a `lint.presets` preset excludes (chant #2113) is a distinct
324
+ // reason a finding doesn't reach the errors/warnings lists. The preset
325
+ // decided the rule shouldn't run at all under this project's configured
326
+ // tier, not that `lint.rules` downgraded it to "off", so it gets its own
327
+ // counter and its own summary line rather than folding into the one above.
328
+ let suppressedPresetCount = 0;
329
+ /**
330
+ * Apply every suppression/filtering surface to one batch, in order:
331
+ * `lint.presets` (chant #2113, which check ids are enabled at all; a
332
+ * no-op when `presetIds` is undefined, the case for every call site below
333
+ * except the per-plugin loop, which is the only one with a lexicon a
334
+ * preset could apply to), then `lint.rules` severity overrides (chant
335
+ * #1138), then inline `# chant-ignore` comments (chant #2111).
336
+ */
337
+ const resolvePostSynth = (diags, entities, presetIds) => {
338
+ const { diagnostics: afterPreset, suppressed: presetSuppressed } = applyConfiguredPreset(diags, presetIds, config.lint?.rules);
339
+ suppressedPresetCount += presetSuppressed.length;
340
+ const { diagnostics: afterConfig, suppressed: configSuppressed } = applyConfiguredSeverity(afterPreset, config.lint?.rules);
341
+ suppressedPostSynthCount += configSuppressed.length;
342
+ const { diagnostics: active, suppressed: inlineSuppressed, meta } = applyInlineSuppressions(afterConfig, entities, config.lint?.rules);
343
+ inlineSuppressedCount += inlineSuppressed.length;
344
+ suppressionMeta.push(...meta);
345
+ return active;
346
+ };
347
+ // Core-owned post-synth checks over effect receipts (#1833). Receipts are
348
+ // recognized by marker, lexicon-independently, so this set runs over the
349
+ // FULL build result — unscoped, and regardless of which plugins loaded.
350
+ // Same severity-resolution funnel as every other post-synth finding.
351
+ if (result.errors.length === 0) {
352
+ const receiptDiags = runPostSynthChecks(coreReceiptChecks(), result, env);
353
+ for (const diag of resolvePostSynth(receiptDiags, result.entities)) {
354
+ const prefix = diag.entity ? `[${diag.entity}] ` : "";
355
+ const lexiconSuffix = diag.lexicon ? ` (${diag.lexicon})` : "";
356
+ if (diag.severity === "error") {
357
+ errors.push(formatError({ message: `${prefix}${diag.message}${lexiconSuffix}` }));
358
+ }
359
+ else {
360
+ warnings.push(formatWarning({ message: `${prefix}${diag.message}${lexiconSuffix}` }));
361
+ }
362
+ }
363
+ }
364
+ // Core-owned post-synth check over serialized output text (#1526). The
365
+ // "[object Object]" marker means a reference got stringified instead of
366
+ // resolved; it can appear in any lexicon's emitted text, so this runs over
367
+ // the FULL build result the same way the receipt checks above do.
368
+ if (result.errors.length === 0) {
369
+ const outputDiags = runPostSynthChecks(coreOutputChecks(), result, env);
370
+ for (const diag of resolvePostSynth(outputDiags, result.entities)) {
371
+ const prefix = diag.entity ? `[${diag.entity}] ` : "";
372
+ const lexiconSuffix = diag.lexicon ? ` (${diag.lexicon})` : "";
373
+ if (diag.severity === "error") {
374
+ errors.push(formatError({ message: `${prefix}${diag.message}${lexiconSuffix}` }));
375
+ }
376
+ else {
377
+ warnings.push(formatWarning({ message: `${prefix}${diag.message}${lexiconSuffix}` }));
378
+ }
379
+ }
380
+ }
381
+ // Core-owned post-synth check over the project's OKF knowledge bundle
382
+ // (#1865, design #1059): a concept's `binds` naming no discovered entity is
383
+ // a stale binding, surfaced as a COR026 warning. `resolveKnowledgeDir` +
384
+ // `loadOkfBundle` never fail — a missing/absent `knowledge/` directory
385
+ // loads an empty bundle, so this is a no-op for a project that has none.
386
+ if (result.errors.length === 0) {
387
+ const bundle = await loadOkfBundle(resolveKnowledgeDir(config, configDir));
388
+ const knowledgeDiags = runPostSynthChecks(coreKnowledgeChecks(bundle), result, env);
389
+ for (const diag of resolvePostSynth(knowledgeDiags, result.entities)) {
390
+ const prefix = diag.entity ? `[${diag.entity}] ` : "";
391
+ const lexiconSuffix = diag.lexicon ? ` (${diag.lexicon})` : "";
392
+ if (diag.severity === "error") {
393
+ errors.push(formatError({ message: `${prefix}${diag.message}${lexiconSuffix}` }));
394
+ }
395
+ else {
396
+ warnings.push(formatWarning({ message: `${prefix}${diag.message}${lexiconSuffix}` }));
397
+ }
398
+ }
399
+ }
400
+ // Activity contracts across every loaded lexicon (chant #2101): core's own
401
+ // plus each lexicon's, by the same `@intentius/chant-lexicon-<name>/op/...`
402
+ // convention `loadActivities` resolves implementations with. OPS012/OPS013
403
+ // and a plugin's own checks merge this over their own tables, so a step
404
+ // calling a lexicon's activity is validated against that lexicon's contract
405
+ // instead of failing for the absence of one. Resolved once, for both check
406
+ // passes below.
407
+ const activityContracts = result.errors.length === 0 ? await loadActivityContracts(options.plugins ?? []) : undefined;
408
+ // Core-owned post-synth checks over the Op model (#2122, epic #2114
409
+ // sub-issue 6) — OPS012/OPS013/OPS014, ported from a hosting lexicon's
410
+ // own TMP012/TMP013/TMP014, and SYS010 over the decide steps and the
411
+ // backends in `decide.backends` (#2828). An Op is recognized by entity type
412
+ // (`OpResource`), not by which lexicon declared it, so this runs over the
413
+ // FULL build result regardless of which plugins loaded — same as the
414
+ // receipt/output/knowledge checks above.
415
+ if (result.errors.length === 0) {
416
+ const opDiags = runPostSynthChecks(coreOpChecks({ decideBackends: config.decide?.backends }), result, env, { activityContracts });
417
+ const { diagnostics: activeDiags, suppressed } = applyConfiguredSeverity(opDiags, config.lint?.rules);
418
+ suppressedPostSynthCount += suppressed.length;
419
+ for (const diag of activeDiags) {
420
+ const prefix = diag.entity ? `[${diag.entity}] ` : "";
421
+ const lexiconSuffix = diag.lexicon ? ` (${diag.lexicon})` : "";
422
+ if (diag.severity === "error") {
423
+ errors.push(formatError({ message: `${prefix}${diag.message}${lexiconSuffix}` }));
424
+ }
425
+ else {
426
+ warnings.push(formatWarning({ message: `${prefix}${diag.message}${lexiconSuffix}` }));
427
+ }
428
+ }
429
+ }
430
+ if (result.errors.length === 0 && options.plugins) {
431
+ for (const { plugin, diagnostics: postDiags } of runLexiconPostSynthChecks(options.plugins, result, env, { activityContracts, telemetry, projectDir: configDir, projectConfig: config })) {
432
+ // `lint.presets` (chant #2113) filters WHICH check ids are reported at
433
+ // all, before `lint.rules`/inline suppression act on the reported
434
+ // ones. It's a no-op for a lexicon that ships no `lintPresets()` (the
435
+ // common case today), since `resolvePresetIds` returns `undefined`
436
+ // for one. This is the only `resolvePostSynth` call site with a
437
+ // lexicon a preset could apply to; every other call below passes no
438
+ // `presetIds` at all.
439
+ const presetIds = resolvePresetIds(plugin.lintPresets?.(), config.lint?.presets?.[plugin.name] ?? "recommended");
440
+ for (const diag of resolvePostSynth(postDiags, result.entities, presetIds)) {
441
+ const prefix = diag.entity ? `[${diag.entity}] ` : "";
442
+ const lexiconSuffix = diag.lexicon ? ` (${diag.lexicon})` : "";
443
+ if (diag.severity === "error") {
444
+ errors.push(formatError({ message: `${prefix}${diag.message}${lexiconSuffix}` }));
445
+ }
446
+ else {
447
+ warnings.push(formatWarning({ message: `${prefix}${diag.message}${lexiconSuffix}` }));
448
+ }
449
+ }
450
+ }
451
+ // Project-authored organizational policy — cross-cutting, so it sees every
452
+ // lexicon's output at once (not scoped per-plugin), with the current env.
453
+ //
454
+ // #1131 — under `--sandbox` this is where the LAST piece of project-
455
+ // authored code the CLI used to execute in its own process moves behind
456
+ // the boundary: `runProjectPolicies` hands the merged, serialized build
457
+ // result to a post-merge sandboxed child, which imports the policy modules
458
+ // and runs their checks there, and only plain `PostSynthDiagnostic`s come
459
+ // back. Unsandboxed, it is the same in-process load-and-run as before.
460
+ //
461
+ // #1138 — `applyConfiguredSeverity` runs HERE, in the parent, after the
462
+ // sandboxed child (when armed) has already returned — never inside it.
463
+ // The child only knows the policy paths and the encoded build result, not
464
+ // this project's resolved `lint.rules`, and by design nothing about the
465
+ // suppression surface needs to cross that boundary: both the plain and
466
+ // the `--sandbox` path funnel through this identical call with the
467
+ // identical `config.lint?.rules`, so a sandboxed and an unsandboxed build
468
+ // of the same project apply the same config to the same diagnostics.
469
+ if (policies.length > 0) {
470
+ const policyDiags = await runProjectPolicies({
471
+ policies,
472
+ configDir,
473
+ buildResult: result,
474
+ env,
475
+ preloaded: preloadedPolicyChecks,
476
+ });
477
+ for (const diag of resolvePostSynth(policyDiags, result.entities)) {
478
+ const prefix = diag.entity ? `[${diag.entity}] ` : "";
479
+ const where = diag.lexicon ? ` (${diag.lexicon})` : "";
480
+ const msg = `[policy:${diag.checkId}] ${prefix}${diag.message}${where}`;
481
+ if (diag.severity === "error")
482
+ errors.push(formatError({ message: msg }));
483
+ else
484
+ warnings.push(formatWarning({ message: msg }));
485
+ }
486
+ }
487
+ if (suppressedPostSynthCount > 0) {
488
+ warnings.push(formatWarning({
489
+ message: `${suppressedPostSynthCount} post-synth finding(s) suppressed via lint.rules (severity "off")`,
490
+ }));
491
+ }
492
+ if (suppressedPresetCount > 0) {
493
+ warnings.push(formatWarning({
494
+ message: `${suppressedPresetCount} post-synth finding(s) not reported: excluded by the active lint.presets preset`,
495
+ }));
496
+ }
497
+ if (inlineSuppressedCount > 0) {
498
+ warnings.push(formatWarning({
499
+ message: `${inlineSuppressedCount} post-synth finding(s) suppressed via inline chant-ignore comments`,
500
+ }));
501
+ }
502
+ // Directives that are themselves worth a finding (expired, misplaced, or
503
+ // naming a rule id configured `ignorable: false`) are reported once
504
+ // each, never silently (chant #2111).
505
+ for (const m of suppressionMeta) {
506
+ warnings.push(formatWarning({ message: `[${m.checkId}] ${m.file}:${m.line} ${m.message}` }));
507
+ }
508
+ }
509
+ // Empty-output guard: source files were discovered but no lexicon produced
510
+ // any output. Almost always indicates broken imports resolving to undefined
511
+ // (e.g. missing root re-exports from a lexicon) or modules that exported no
512
+ // Declarables. Without this guard, chant writes "{}" and exits 0.
513
+ //
514
+ // An Op declaration is the honest exception (#2118): it belongs to no
515
+ // lexicon partition and its build output is the `op.json` written below,
516
+ // not a resource manifest, so an Ops-only project legitimately produces no
517
+ // serializer output and must not be reported as a broken import.
518
+ const declaredOps = [...result.entities.values()].filter(isOpEntity);
519
+ // The gate step's name key was renamed from `signalName` to `gate` in #2202.
520
+ // The old key is still read; a build that finds an Op still using it says so
521
+ // once, naming every Op involved, rather than once per gate step.
522
+ const opsOnOldGateKey = declaredOps
523
+ .map((entity) => entity.props)
524
+ .filter((config) => Boolean(config?.name) && opUsesDeprecatedGateKey(config))
525
+ .map((config) => config.name);
526
+ if (opsOnOldGateKey.length > 0) {
527
+ warnings.push(formatWarning({ message: `${DEPRECATED_GATE_KEY_WARNING} Ops: ${opsOnOldGateKey.join(", ")}.` }));
528
+ }
529
+ if (result.sourceFileCount > 0 &&
530
+ result.outputs.size === 0 &&
531
+ declaredOps.length === 0 &&
532
+ result.errors.length === 0 &&
533
+ errors.length === 0) {
534
+ errors.push(formatError({
535
+ message: `Discovered ${result.sourceFileCount} source file(s) but produced no output. Likely causes: imports resolving to undefined (missing exports from a lexicon root), or no Declarables/Composites exported. Check that imported names exist in the target package.`,
536
+ }));
537
+ }
538
+ // Handle output
539
+ if (result.errors.length === 0 && errors.length === 0) {
540
+ // Extract primary content and collect additional files from SerializerResult.
541
+ // Each entry remembers which lexicon produced it, so a same-basename
542
+ // collision between two sources (below) can name both.
543
+ const additionalFiles = new Map();
544
+ // Basenames (from some SerializerResult.files) that must reach disk
545
+ // BYTE-FOR-BYTE — e.g. committed ciphertext
546
+ // (`declareSecret({ provenance: "committed-encrypted", file })`). The
547
+ // additional-file writer below round-trips anything JSON.parse accepts,
548
+ // key-sorting it and possibly re-emitting it as YAML, which would break
549
+ // e.g. the `sops` MAC on committed ciphertext. A serializer opts a file
550
+ // out of that round trip structurally, via `SerializerResult.verbatimFiles`
551
+ // (chant#1937) — "the parse happens to fail" is not a safety guarantee.
552
+ const verbatimFiles = new Set();
553
+ // Basenames that hold a secret (`SerializerResult.secretFiles`): a build
554
+ // with no --output refuses rather than echo them (chant#3738). Verbatim
555
+ // alone does not mean secret, so this is its own set.
556
+ const secretFiles = new Set();
557
+ // A same basename emitted by two sources with different content would
558
+ // otherwise silently overwrite (last-writer-wins, since `additionalFiles`
559
+ // is keyed by basename alone). Identical content from two sources is
560
+ // fine — dedup — but differing content is refused, naming both sources,
561
+ // the same way the committed-encrypted resolution stage refuses a
562
+ // basename collision among its own declarations.
563
+ function addAdditionalFile(filename, content, source) {
564
+ const existing = additionalFiles.get(filename);
565
+ if (existing === undefined) {
566
+ additionalFiles.set(filename, { content, source });
567
+ return;
568
+ }
569
+ if (existing.content === content)
570
+ return;
571
+ errors.push(formatError({
572
+ message: `Additional file "${filename}" collides: "${existing.source}" and "${source}" ` +
573
+ `both emit it with different content — additional files share one flat ` +
574
+ `namespace, so two sources whose filenames match would otherwise silently ` +
575
+ `overwrite each other.`,
576
+ }));
577
+ }
578
+ function getPrimaryContent(raw, source) {
579
+ if (typeof raw === "string")
580
+ return raw;
581
+ if (raw.files) {
582
+ for (const [filename, content] of Object.entries(raw.files)) {
583
+ addAdditionalFile(filename, content, source);
584
+ }
585
+ }
586
+ if (raw.verbatimFiles) {
587
+ for (const filename of raw.verbatimFiles) {
588
+ verbatimFiles.add(filename);
589
+ }
590
+ }
591
+ if (raw.secretFiles) {
592
+ for (const filename of raw.secretFiles) {
593
+ secretFiles.add(filename);
594
+ }
595
+ }
596
+ return raw.primary;
597
+ }
598
+ // Try to parse content as JSON; return raw string if not JSON.
599
+ function tryParseJson(content) {
600
+ try {
601
+ return { json: JSON.parse(content) };
602
+ }
603
+ catch {
604
+ return { raw: content };
605
+ }
606
+ }
607
+ // Single lexicon: output the template directly
608
+ // Multiple lexicons: wrap in lexicon keys
609
+ let output = "{}";
610
+ if (result.outputs.size === 1) {
611
+ const [lexiconName, raw] = [...result.outputs.entries()][0];
612
+ const content = getPrimaryContent(raw, lexiconName);
613
+ const parsed = tryParseJson(content);
614
+ if ("json" in parsed) {
615
+ output = JSON.stringify(parsed.json, sortedJsonReplacer, 2);
616
+ if (options.format === "yaml") {
617
+ output = jsonToYaml(JSON.parse(output));
618
+ }
619
+ }
620
+ else {
621
+ output = parsed.raw;
622
+ }
623
+ }
624
+ else {
625
+ // Multiple lexicons: JSON outputs get combined under lexicon keys,
626
+ // non-JSON outputs (e.g. YAML) are appended after a separator.
627
+ const combined = {};
628
+ const nonJsonSections = [];
629
+ const sortedLexiconNames = [...result.outputs.keys()].sort();
630
+ for (const lexiconName of sortedLexiconNames) {
631
+ const content = getPrimaryContent(result.outputs.get(lexiconName), lexiconName);
632
+ const parsed = tryParseJson(content);
633
+ if ("json" in parsed) {
634
+ combined[lexiconName] = parsed.json;
635
+ }
636
+ else {
637
+ nonJsonSections.push(`# --- ${lexiconName} ---\n${parsed.raw}`);
638
+ }
639
+ }
640
+ const parts = [];
641
+ if (Object.keys(combined).length > 0) {
642
+ let jsonOutput = JSON.stringify(combined, sortedJsonReplacer, 2);
643
+ if (options.format === "yaml") {
644
+ jsonOutput = jsonToYaml(JSON.parse(jsonOutput));
645
+ }
646
+ parts.push(jsonOutput);
647
+ }
648
+ parts.push(...nonJsonSections);
649
+ if (parts.length > 0) {
650
+ output = parts.join("\n\n");
651
+ }
652
+ }
653
+ // Anything a serializer emits under `ops/` always goes to
654
+ // `<project>/dist/ops/` — the fixed place an Op's build output is read
655
+ // from, alongside the `op.json` core writes below — independent of
656
+ // `--output`, which routes the primary resource manifest. Without this, a
657
+ // bare `chant build` only printed them to stderr and `--output foo.yaml`
658
+ // scattered them next to `foo.yaml`.
659
+ const projectDist = resolve(options.path ?? ".", "dist");
660
+ let opsWritten = 0;
661
+ for (const [filename, entry] of [...additionalFiles]) {
662
+ if (!filename.startsWith("ops/"))
663
+ continue;
664
+ additionalFiles.delete(filename);
665
+ try {
666
+ const targetPath = join(projectDist, filename);
667
+ mkdirSync(dirname(targetPath), { recursive: true });
668
+ writeFileSync(targetPath, entry.content);
669
+ opsWritten += 1;
670
+ }
671
+ catch (err) {
672
+ errors.push(formatError({
673
+ message: `Failed to write Op output file ${filename}: ${err instanceof Error ? err.message : String(err)}`,
674
+ }));
675
+ }
676
+ }
677
+ if (opsWritten > 0) {
678
+ console.error(formatInfo(`Wrote ${opsWritten} Op output file(s) under ${join(options.path ?? ".", "dist", "ops")}/`));
679
+ }
680
+ // `dist/ops/<name>/op.json` — the Op IR (#1289), written here by core
681
+ // rather than emitted by a lexicon serializer (#2118). An Op declaration
682
+ // is core's own entity now (`Chant::Op`, lexicon `chant`) and is held out
683
+ // of `partitionByLexicon` entirely, so this is the one place its build
684
+ // output is produced: a deterministic, engine-neutral restatement of the
685
+ // step graph that anything can read without importing chant.
686
+ let irWritten = 0;
687
+ for (const entity of declaredOps) {
688
+ const config = entity.props;
689
+ if (!config?.name)
690
+ continue;
691
+ try {
692
+ const targetPath = join(projectDist, "ops", config.name, "op.json");
693
+ mkdirSync(dirname(targetPath), { recursive: true });
694
+ writeFileSync(targetPath, serializeOpIR(config));
695
+ irWritten += 1;
696
+ }
697
+ catch (err) {
698
+ errors.push(formatError({
699
+ message: `Failed to write op.json for Op "${config.name}": ${err instanceof Error ? err.message : String(err)}`,
700
+ }));
701
+ }
702
+ }
703
+ if (irWritten > 0) {
704
+ console.error(formatInfo(`Wrote ${irWritten} op.json file(s) under ${join(options.path ?? ".", "dist", "ops")}/`));
705
+ }
706
+ if (options.output) {
707
+ // Write to file — ensure parent directories exist for both the primary
708
+ // output path and any nested additional-file paths (e.g. ops/<name>/...).
709
+ try {
710
+ const outputPath = resolve(options.output);
711
+ mkdirSync(dirname(outputPath), { recursive: true });
712
+ writeFileSync(outputPath, output);
713
+ // Write additional files (e.g. nested stack templates) alongside the primary output
714
+ if (additionalFiles.size > 0) {
715
+ const outputDir = dirname(outputPath);
716
+ for (const [filename, entry] of additionalFiles) {
717
+ let fileContent = entry.content;
718
+ // Format additional files consistently — except the ones declared
719
+ // verbatim, which are copied exactly as they were committed.
720
+ if (!verbatimFiles.has(filename)) {
721
+ try {
722
+ const fileParsed = JSON.parse(entry.content);
723
+ fileContent = JSON.stringify(fileParsed, sortedJsonReplacer, 2);
724
+ if (options.format === "yaml") {
725
+ fileContent = jsonToYaml(JSON.parse(fileContent));
726
+ }
727
+ }
728
+ catch {
729
+ // If not JSON, write as-is
730
+ }
731
+ }
732
+ const targetPath = join(outputDir, filename);
733
+ mkdirSync(dirname(targetPath), { recursive: true });
734
+ writeFileSync(targetPath, fileContent);
735
+ }
736
+ }
737
+ }
738
+ catch (err) {
739
+ errors.push(formatError({
740
+ message: `Failed to write output file: ${err instanceof Error ? err.message : String(err)}`,
741
+ }));
742
+ }
743
+ }
744
+ else if (secretFiles.size > 0) {
745
+ // A build carrying committed ciphertext and no --output has nowhere to
746
+ // put the sidecar. Echoing it to a terminal is not useful and dropping
747
+ // it silently is worse: the primary output would reference a Secret
748
+ // whose file never got written, and the miss would surface as a pod
749
+ // failing to start, far from its cause. Refuse, naming the flag.
750
+ const names = [...secretFiles].sort().join(", ");
751
+ errors.push(formatError({
752
+ message: `This build emits committed-encrypted secret file(s) (${names}) as sidecars, ` +
753
+ `which need a directory to be written into. Re-run with --output <path> ` +
754
+ `(the sidecars land beside it).`,
755
+ }));
756
+ }
757
+ else {
758
+ // Print to stdout
759
+ console.log(output);
760
+ // Log additional files to stderr if any
761
+ for (const [filename, entry] of additionalFiles) {
762
+ console.error(`\n--- ${filename} ---`);
763
+ console.error(entry.content);
764
+ }
765
+ }
766
+ }
767
+ const resourceCount = result.entities.size;
768
+ const fileCount = result.sourceFileCount;
769
+ // A build root (a lexicon's own source files, a rendered overlay) can declare everything without one .ts file.
770
+ if (fileCount === 0 && resourceCount === 0 && errors.length === 0) {
771
+ console.error(formatInfo("No source files found — create .ts files in the target directory"));
772
+ }
773
+ if (options.verbose && errors.length === 0) {
774
+ console.error(formatSuccess(`Built ${formatBold(String(resourceCount))} resources successfully`));
775
+ }
776
+ return {
777
+ success: errors.length === 0,
778
+ resourceCount,
779
+ fileCount,
780
+ errors,
781
+ warnings,
782
+ buildParams: paramsResolution.provenance,
783
+ };
784
+ }
785
+ /**
786
+ * `fold: 8 files folded, 13 ran (--verbose for reasons)` — the non-verbose
787
+ * report of a fold build's per-file decisions (#1424). The "(--verbose for
788
+ * reasons)" hint appears only when something ran, since that is the only case
789
+ * with a reason to read.
790
+ */
791
+ export function summarizeFoldDecisions(decisions) {
792
+ const folded = decisions.filter((d) => d.mode === "fold").length;
793
+ const ran = decisions.length - folded;
794
+ const files = (n) => `${n} file${n === 1 ? "" : "s"}`;
795
+ const hint = ran > 0 ? " (--verbose for reasons)" : "";
796
+ return `fold: ${files(folded)} folded, ${ran} ran${hint}`;
797
+ }
798
+ /**
799
+ * `chant build --fold --fold-rank`'s text report (chant #1083): blockers
800
+ * ranked by dominator retained-count, highest first, then the reverse-taint
801
+ * bucket (#1044) called out separately since the tree can't express that
802
+ * edge (see `../../discovery/fold-rank.ts`'s module doc).
803
+ */
804
+ export function formatFoldRanking(ranking, infraPath) {
805
+ const rel = (file) => relative(infraPath, file) || file;
806
+ const lines = [];
807
+ if (ranking.blockers.length === 0) {
808
+ lines.push("fold-rank: no run-mode files to rank");
809
+ }
810
+ else {
811
+ lines.push(`fold-rank: ${ranking.blockers.length} blocker(s), ${ranking.totalBlocked} file(s) blocked`);
812
+ for (const b of ranking.blockers) {
813
+ const via = b.topLevel ? "" : ` (behind ${rel(b.dominatedBy)})`;
814
+ const reason = b.reason ? ` — ${b.reason}` : "";
815
+ lines.push(` retained ${b.retained}: ${rel(b.file)}${via}${reason}`);
816
+ }
817
+ }
818
+ if (ranking.reverseTainted.length > 0) {
819
+ lines.push(`fold-rank: ${ranking.reverseTainted.length} file(s) held back only by the reverse rule (#1044) — would fold in isolation, blocked by a run-mode importer, not modeled in the tree above:`);
820
+ for (const t of ranking.reverseTainted) {
821
+ lines.push(` ${rel(t.file)}`);
822
+ }
823
+ }
824
+ return lines.join("\n");
825
+ }
826
+ /**
827
+ * Simple JSON to YAML converter
828
+ */
829
+ function jsonToYaml(obj, indent = 0) {
830
+ const spaces = " ".repeat(indent);
831
+ if (obj === null)
832
+ return "null";
833
+ if (obj === undefined)
834
+ return "~";
835
+ if (typeof obj === "boolean")
836
+ return obj ? "true" : "false";
837
+ if (typeof obj === "number")
838
+ return String(obj);
839
+ if (typeof obj === "string") {
840
+ // Quote strings that need it
841
+ if (obj.includes("\n") || obj.includes(":") || obj.includes("#")) {
842
+ return `"${obj.replace(/"/g, '\\"')}"`;
843
+ }
844
+ return obj;
845
+ }
846
+ if (Array.isArray(obj)) {
847
+ if (obj.length === 0)
848
+ return "[]";
849
+ return obj
850
+ .map((item) => `${spaces}- ${jsonToYaml(item, indent + 1).trimStart()}`)
851
+ .join("\n");
852
+ }
853
+ if (typeof obj === "object") {
854
+ const entries = Object.entries(obj).sort(([a], [b]) => a.localeCompare(b));
855
+ if (entries.length === 0)
856
+ return "{}";
857
+ return entries
858
+ .map(([key, value]) => {
859
+ const yamlValue = jsonToYaml(value, indent + 1);
860
+ // A non-empty container (object OR array) renders as a block: the key on
861
+ // its own line, the value indented beneath it. Arrays were previously
862
+ // excluded here, which inlined `Tags: - Key: t` as invalid YAML.
863
+ const isContainer = typeof value === "object" && value !== null;
864
+ const isEmpty = isContainer && (Array.isArray(value) ? value.length === 0 : Object.keys(value).length === 0);
865
+ if (isContainer && !isEmpty) {
866
+ return `${spaces}${key}:\n${yamlValue}`;
867
+ }
868
+ return `${spaces}${key}: ${yamlValue.trimStart()}`;
869
+ })
870
+ .join("\n");
871
+ }
872
+ return String(obj);
873
+ }
874
+ /**
875
+ * Print errors to stderr
876
+ */
877
+ export function printErrors(errors) {
878
+ for (const error of errors) {
879
+ console.error(error);
880
+ }
881
+ }
882
+ /**
883
+ * Print warnings to stderr
884
+ */
885
+ export function printWarnings(warnings) {
886
+ for (const warning of warnings) {
887
+ console.error(warning);
888
+ }
889
+ }
890
+ /**
891
+ * Run build in watch mode. Runs an initial build, then watches for changes
892
+ * and triggers rebuilds. Returns a cleanup function.
893
+ */
894
+ export function buildCommandWatch(options, onRebuild) {
895
+ const infraPath = resolve(options.path);
896
+ console.error(formatInfo(`[${formatTimestamp()}] Watching for changes...`));
897
+ // Run initial build
898
+ buildCommand(options).then((result) => {
899
+ printWarnings(result.warnings);
900
+ printErrors(result.errors);
901
+ onRebuild?.(result);
902
+ console.error(formatInfo(`[${formatTimestamp()}] Waiting for changes...`));
903
+ });
904
+ // Watch for changes and trigger rebuilds
905
+ const cleanup = watchDirectory(infraPath, async (changedFiles) => {
906
+ console.error("");
907
+ console.error(formatInfo(`[${formatTimestamp()}] Changes detected: ${formatChangedFiles(changedFiles, infraPath)}`));
908
+ try {
909
+ const result = await buildCommand(options);
910
+ printWarnings(result.warnings);
911
+ printErrors(result.errors);
912
+ onRebuild?.(result);
913
+ }
914
+ catch (err) {
915
+ console.error(formatError({ message: err instanceof Error ? err.message : String(err) }));
916
+ }
917
+ console.error(formatInfo(`[${formatTimestamp()}] Waiting for changes...`));
918
+ });
919
+ return cleanup;
920
+ }