@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,889 @@
1
+ /**
2
+ * `chant workspace upgrade <scope>`: bring one lineage scope to a newer
3
+ * version of its template (#2550, D9, ws-005, ws-032).
4
+ *
5
+ * The upgrade is a core command, never an Op the template ships, so the
6
+ * template cannot change the rules that judge its own upgrade. It works in the
7
+ * six steps of D9:
8
+ *
9
+ * 1. Fetch the target version of the template. For a git source that is one
10
+ * `git fetch` of the target ref, plus the commit the scope was made from.
11
+ * This is the command's only network step, catalogued in
12
+ * `test/egress-catalogue.ts`. A local repository reaches nothing, and
13
+ * neither does a directory source (#2647), which reads `--to <dir>`.
14
+ * 2. Rebuild the merge base offline: each recorded file's content at the base
15
+ * commit, kept only when it has the hash the lock recorded. A file the
16
+ * project never edited is its own merge base. Vendor sources keep no
17
+ * history, so only unedited vendored files have a base.
18
+ * 3. Migrate in a separate git worktree, checked out at HEAD under
19
+ * `.chant/upgrade/`. The chain is planned from the template's
20
+ * `.chant/migrations/`, and a gap refuses the upgrade.
21
+ * 4. Merge per file (ws-005): an edited file takes the new version only when
22
+ * every hunk merges cleanly. Otherwise it stays as it was, with one manual
23
+ * step. The worktree never holds conflict markers.
24
+ * Then rebuild each CI workflow a chant member's package.json builds with
25
+ * `chant build ... -o <workflow>` (#3244), with the chant doing the
26
+ * upgrade, so the committed workflow follows that chant's composites.
27
+ * 5. Check the worktree: `chant build` and `chant lint` when the project is a
28
+ * chant project, and the lineage checks of `chant workspace check`.
29
+ * 6. Bind the gate to the digest of the resulting patch: the pending fact and
30
+ * the approval name it, so an approval covers exactly this patch.
31
+ *
32
+ * The project's own tree changes only once the gate is approved, when the
33
+ * patch is applied to it. A patch that changes governance files (Op files,
34
+ * `chant.config`, CI workflows, CODEOWNERS) needs human approvals, as many as
35
+ * the strictest gate in the Op files it changes asks for at HEAD. The
36
+ * upgraded Op files never decide their own gate.
37
+ */
38
+ import { execFileSync, spawn } from "node:child_process";
39
+ import { chmodSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
40
+ import { tmpdir } from "node:os";
41
+ import { basename, dirname, join, relative, resolve, sep } from "node:path";
42
+ import { computePlanDigest } from "../lifecycle/plan-digest.js";
43
+ import { checkLineage, findingKey } from "./lineage-check.js";
44
+ import { dirLabel, git, parseDirSpec, parseTemplateSource, portableUrl, readTemplateDir, readTemplateTree, recordedDirPath } from "./lineage-init.js";
45
+ import { LOCK_FILE, LockError, contentDigest, fileHash, readLock, renderLock, scopeKey, writeLock, } from "./lineage-lock.js";
46
+ import { mergeFile } from "./lineage-merge.js";
47
+ import { reportPlan, runChantMigrations } from "./chant-migrations.js";
48
+ import { readDeclaration, readerVersion, WorkspaceReadError } from "./declaration.js";
49
+ import { assertCodeAllowed, planMigrations, runMigration, splitMigrations } from "./lineage-migrations.js";
50
+ import { applyUpstream } from "./lineage-update.js";
51
+ import { pathsInsideNested } from "./nesting.js";
52
+ import { carryParameters, readManifest, substituteParameters } from "./template-manifest.js";
53
+ import { repinSubstituted } from "./template-pins.js";
54
+ import { workingTree } from "./tree.js";
55
+ import { splitCommandLine } from "./checks/generated.js";
56
+ /** The kind the patch digest is taken under, so it never collides with another kind of plan. */
57
+ export const UPGRADE_PLAN_KIND = "workspace-upgrade";
58
+ /** Where staging worktrees live, relative to the project root. */
59
+ export const UPGRADE_DIR = ".chant/upgrade";
60
+ export class UpgradeError extends LockError {
61
+ constructor() {
62
+ super(...arguments);
63
+ this.name = "UpgradeError";
64
+ }
65
+ }
66
+ /**
67
+ * The default runner: this same chant, in a child process. The child sees the
68
+ * worktree's sources and resolves packages the way the project does, since the
69
+ * worktree sits inside the project.
70
+ */
71
+ export const spawnChant = (command, cwd, args = []) => new Promise((resolvePromise, reject) => {
72
+ const entry = process.argv[1];
73
+ if (!entry) {
74
+ reject(new UpgradeError("cannot find the chant entry point to run build and lint in the worktree"));
75
+ return;
76
+ }
77
+ const child = spawn(process.execPath, [...process.execArgv, entry, command, ...args], { cwd, stdio: ["ignore", "pipe", "pipe"], env: process.env });
78
+ const out = [];
79
+ child.stdout.on("data", (c) => out.push(c));
80
+ child.stderr.on("data", (c) => out.push(c));
81
+ child.on("error", reject);
82
+ child.on("close", (code) => resolvePromise({ exitCode: code ?? 1, output: Buffer.concat(out).toString("utf-8") }));
83
+ });
84
+ /** A CI workflow path a forge reads, relative to the repository root. The governance list's pipeline entries. */
85
+ const CI_WORKFLOW = [/(^|\/)\.github\/workflows\/[^/]+\.ya?ml$/, /(^|\/)\.forgejo\/workflows\/[^/]+\.ya?ml$/, /(^|\/)\.gitea\/workflows\/[^/]+\.ya?ml$/, /(^|\/)\.gitlab-ci\.ya?ml$/];
86
+ /**
87
+ * The CI workflows the chant members under `worktreeProject` build: each
88
+ * package.json script that is one `chant build ... -o <file>` command (no
89
+ * shell, no `&&`), whose output is a committed CI workflow inside the scope.
90
+ * The studio kit's template has `"ci:build": "chant build ci --lexicon github
91
+ * -o ../.github/workflows/ci.yml"` in delivery/, and its CI fails when the
92
+ * committed workflow differs from what ci/ci.ts builds.
93
+ */
94
+ function workflowBuilds(worktree, worktreeProject, scopeRepoPath) {
95
+ const out = [];
96
+ for (const member of chantMemberDirs(worktreeProject)) {
97
+ const dir = member === "." ? worktreeProject : join(worktreeProject, member);
98
+ let scripts;
99
+ try {
100
+ scripts = JSON.parse(readFileSync(join(dir, "package.json"), "utf-8")).scripts ?? {};
101
+ }
102
+ catch {
103
+ continue;
104
+ }
105
+ for (const [script, line] of Object.entries(scripts)) {
106
+ if (typeof line !== "string")
107
+ continue;
108
+ const words = splitCommandLine(line);
109
+ if (!words || words[0] !== "chant" || words[1] !== "build")
110
+ continue;
111
+ const flag = words.findIndex((w) => w === "-o" || w === "--output");
112
+ const target = flag >= 0 ? words[flag + 1] : words.find((w) => w.startsWith("--output="))?.slice("--output=".length);
113
+ if (!target)
114
+ continue;
115
+ const abs = resolve(dir, target);
116
+ const path = relative(worktree, abs).split(sep).join("/");
117
+ if (path.startsWith("../") || !CI_WORKFLOW.some((re) => re.test(path)))
118
+ continue;
119
+ if (scopeRepoPath !== "." && !path.startsWith(`${scopeRepoPath}/`))
120
+ continue;
121
+ if (!existsSync(abs))
122
+ continue;
123
+ out.push({ member, script, command: line, args: words.slice(2), abs, path });
124
+ }
125
+ }
126
+ return out;
127
+ }
128
+ /**
129
+ * Rebuild the CI workflows {@link workflowBuilds} finds (#3244), each in its
130
+ * member's directory of the staging worktree with that member's node_modules
131
+ * linked in from the project. A workflow is built from the member's sources
132
+ * through the lexicon's composites, so upgrading chant can change it with no
133
+ * change to the sources (#2621 moved Checkout and SetupNode from v4 to v7),
134
+ * and a committed copy then fails the project's own ci:check. Rebuilding it
135
+ * here puts the new workflow in the patch the gate approves. The links are
136
+ * removed before the patch is taken. A build that fails leaves the file as
137
+ * the merge left it.
138
+ */
139
+ async function rebuildWorkflows(root, worktree, worktreeProject, scopeRepoPath, run) {
140
+ const builds = workflowBuilds(worktree, worktreeProject, scopeRepoPath);
141
+ if (builds.length === 0)
142
+ return [];
143
+ const linked = [];
144
+ const results = [];
145
+ try {
146
+ for (const member of new Set(builds.map((b) => b.member))) {
147
+ if (member === ".")
148
+ continue;
149
+ const from = join(root, member, "node_modules");
150
+ const to = join(worktreeProject, member, "node_modules");
151
+ if (existsSync(from) && !existsSync(to) && existsSync(dirname(to))) {
152
+ symlinkSync(from, to, "dir");
153
+ linked.push(to);
154
+ }
155
+ }
156
+ for (const b of builds) {
157
+ const before = readFileSync(b.abs);
158
+ const r = await run("build", b.member === "." ? worktreeProject : join(worktreeProject, b.member), b.args);
159
+ const base = { member: b.member, script: b.script, path: b.path, command: b.command };
160
+ if (r.exitCode !== 0) {
161
+ writeFileSync(b.abs, before);
162
+ results.push({ ...base, status: "failed", detail: tail(r.output) });
163
+ continue;
164
+ }
165
+ const after = existsSync(b.abs) ? readFileSync(b.abs) : null;
166
+ if (after === null) {
167
+ writeFileSync(b.abs, before);
168
+ results.push({ ...base, status: "failed", detail: `\`${b.command}\` exited 0 and wrote no ${b.path}` });
169
+ continue;
170
+ }
171
+ results.push({ ...base, status: after.equals(before) ? "unchanged" : "rebuilt" });
172
+ }
173
+ }
174
+ finally {
175
+ for (const l of linked) {
176
+ try {
177
+ if (lstatSync(l).isSymbolicLink())
178
+ unlinkSync(l);
179
+ }
180
+ catch {
181
+ // Already gone.
182
+ }
183
+ }
184
+ }
185
+ return results;
186
+ }
187
+ /**
188
+ * The template's files as the project would have them (#2627): the manifest
189
+ * removed and the parameters substituted, with the recorded values and the
190
+ * defaults of parameters this version adds. Records that pin a substituted
191
+ * file are re-pinned as init re-pinned them (#2549), for the base and the
192
+ * target alike, so an unedited record compares equal to its base.
193
+ */
194
+ function instantiate(raw, recorded, label) {
195
+ try {
196
+ const manifest = readManifest(raw);
197
+ const parameters = carryParameters(manifest, recorded);
198
+ const { files, repinned } = repinSubstituted(raw, substituteParameters(raw, manifest, parameters), manifest?.files ?? []);
199
+ return { files, parameters, repinned };
200
+ }
201
+ catch (err) {
202
+ throw new UpgradeError(`${label}: ${err.message.replace(/; pass --param .*$/, "")}`);
203
+ }
204
+ }
205
+ /**
206
+ * Fetch the target ref, and the commit the scope was made from, of a git
207
+ * source into a scratch repository, and read both trees. The base fetch may
208
+ * fail (a server that refuses fetches by commit); the base is then left empty,
209
+ * and every edited file the template changed becomes a manual step.
210
+ */
211
+ function fetchGit(root, lineage, ref, onto) {
212
+ const source = lineage.source;
213
+ if (source.type !== "git")
214
+ throw new UpgradeError("not a git source");
215
+ const baseUrl = source.url.startsWith(".") ? resolve(root, source.url) : source.url;
216
+ // With --source (#2551) the target comes from the other template; the base always from the scope's own.
217
+ const url = onto ? onto.url : baseUrl;
218
+ const label = `${onto ? onto.repo : source.repo}@${ref}`;
219
+ const scratch = mkdtempSync(join(tmpdir(), "chant-upgrade-"));
220
+ try {
221
+ git(scratch, ["init", "-q"]);
222
+ try {
223
+ // The network step of `chant workspace upgrade`, catalogued in test/egress-catalogue.ts.
224
+ git(scratch, ["fetch", "-q", "--depth", "1", url, ref]);
225
+ }
226
+ catch (err) {
227
+ const stderr = err.stderr?.toString().trim();
228
+ throw new UpgradeError(`could not fetch ${label}${stderr ? `: ${stderr}` : ""}`);
229
+ }
230
+ const commit = git(scratch, ["rev-parse", "FETCH_HEAD^{commit}"]);
231
+ const target = readTemplateTree(scratch, commit, onto ? onto.path : source.path, label);
232
+ const raw = new Map();
233
+ const executable = new Set();
234
+ for (const [path, f] of target.files) {
235
+ raw.set(path, f.data);
236
+ if (f.executable)
237
+ executable.add(path);
238
+ }
239
+ // The target with the scope's parameters substituted (#2627), so an
240
+ // unedited file that carries a value compares equal to its base.
241
+ const instantiated = instantiate(raw, lineage.parameters, label);
242
+ let base = new Map();
243
+ const baseCommit = lineage.address?.commit;
244
+ if (baseCommit && baseCommit !== commit) {
245
+ try {
246
+ git(scratch, ["fetch", "-q", "--depth", "1", baseUrl, baseCommit]);
247
+ const oldLabel = `${source.repo}@${baseCommit.slice(0, 12)}`;
248
+ const old = readTemplateTree(scratch, baseCommit, source.path, oldLabel);
249
+ // The base is rebuilt the way init wrote it: the old version's
250
+ // manifest, with the values the lock recorded.
251
+ base = instantiate(new Map([...old.files].map(([path, f]) => [path, f.data])), lineage.parameters, oldLabel).files;
252
+ }
253
+ catch {
254
+ // No base from the source; the tree still supplies it for unedited files.
255
+ }
256
+ }
257
+ else if (baseCommit) {
258
+ base = new Map(instantiated.files);
259
+ }
260
+ const split = splitMigrations(instantiated.files);
261
+ return {
262
+ files: split.files,
263
+ executable,
264
+ base,
265
+ migrations: split.migrations,
266
+ modules: split.modules,
267
+ commit,
268
+ tree: target.tree,
269
+ parameters: instantiated.parameters,
270
+ repinned: instantiated.repinned,
271
+ };
272
+ }
273
+ finally {
274
+ rmSync(scratch, { recursive: true, force: true });
275
+ }
276
+ }
277
+ /**
278
+ * Why a directory scope cannot be upgraded, with the way out. A directory
279
+ * has no history, so the merge base exists only while the files the scope
280
+ * was made from are still on disk.
281
+ */
282
+ function dirRefusal(lineage, why) {
283
+ const source = lineage.source;
284
+ return new UpgradeError(`${why}. The scope was made from the directory ${dirLabel(source.path, source.member)}, which has no git history to rebuild a merge base from. ` +
285
+ `Upgrade with --to <dir> while ${source.path} still holds the files the scope was made from, or move the scope onto the git repository the directory was copied from with \`chant workspace adopt-lineage --from <repo>[#<member>]\`.`);
286
+ }
287
+ /**
288
+ * The upstream of a directory source (#2647): the new version from the
289
+ * directory `to` names, and the merge base from the recorded directory, used
290
+ * only when its files, instantiated with the recorded parameters, still have
291
+ * the recorded digest. Anything else is refused: a base that is not the one
292
+ * the scope was made from would turn the project's edits into upstream
293
+ * changes. Reaches no network.
294
+ */
295
+ function readDir(root, lineage, to) {
296
+ const source = lineage.source;
297
+ if (source.type !== "dir")
298
+ throw new UpgradeError("not a directory source");
299
+ if (!to)
300
+ throw dirRefusal(lineage, "no --to directory");
301
+ let target;
302
+ try {
303
+ target = parseDirSpec(to);
304
+ }
305
+ catch {
306
+ target = null;
307
+ }
308
+ if (!target)
309
+ throw new UpgradeError(`--to ${to}: a scope made from a directory upgrades from a directory, and ${to} is not one`);
310
+ const member = to.includes("#") ? target.member : source.member;
311
+ const label = dirLabel(target.path, member);
312
+ const read = readTemplateDir(target.abs, member, label);
313
+ const raw = new Map();
314
+ const executable = new Set();
315
+ for (const [path, f] of read.files) {
316
+ raw.set(path, f.data);
317
+ if (f.executable)
318
+ executable.add(path);
319
+ }
320
+ const instantiated = instantiate(raw, lineage.parameters, label);
321
+ // The merge base: the recorded directory, only while it holds exactly what the scope was made from.
322
+ const original = resolve(root, source.path);
323
+ const originalLabel = dirLabel(source.path, source.member);
324
+ let base;
325
+ try {
326
+ const old = readTemplateDir(original, source.member, originalLabel);
327
+ base = splitMigrations(instantiate(new Map([...old.files].map(([path, f]) => [path, f.data])), lineage.parameters, originalLabel).files).files;
328
+ }
329
+ catch {
330
+ throw dirRefusal(lineage, `${originalLabel} is gone`);
331
+ }
332
+ if (!lineage.address || contentDigest(base) !== lineage.address.digest) {
333
+ throw dirRefusal(lineage, `${originalLabel} no longer holds the files the scope was made from (its digest is not ${lineage.address?.digest ?? "recorded"})`);
334
+ }
335
+ const split = splitMigrations(instantiated.files);
336
+ return {
337
+ files: split.files,
338
+ executable,
339
+ base,
340
+ migrations: split.migrations,
341
+ modules: split.modules,
342
+ parameters: instantiated.parameters,
343
+ repinned: instantiated.repinned,
344
+ source: { type: "dir", path: recordedDirPath(target.path, target.abs, root), ...(member ? { member } : {}) },
345
+ };
346
+ }
347
+ async function fetchUpstream(root, lineage, ref, onto) {
348
+ const source = lineage.source;
349
+ if (source.type === "git") {
350
+ if (!ref)
351
+ throw new UpgradeError("the scope records no ref; pass --to <ref>");
352
+ return fetchGit(root, lineage, ref, onto);
353
+ }
354
+ if (source.type === "local" || source.type === "archive") {
355
+ const { resolveVendorSource } = await import("../cli/commands/vendor.js");
356
+ const files = await resolveVendorSource(source, root);
357
+ return { files, executable: new Set(), base: new Map(), migrations: [], modules: new Map() };
358
+ }
359
+ if (source.type === "dir")
360
+ return readDir(root, lineage, ref);
361
+ throw new UpgradeError(`scope made by \`chant init --template\` (${lineage.template}) is refused: it came from a lexicon's built-in template, which has no versioned source to fetch, and the merge base would be the render of the chant version that wrote it, which chant cannot rebuild offline. Scopes made by \`chant init --from\` (a git repository or a directory) and \`chant vendor\` scopes upgrade.`);
362
+ }
363
+ /** The merge base per recorded file: from the source's old version, or from an unedited file in the tree. */
364
+ function rebuildBase(scopeDir, lineage, fromSource) {
365
+ const base = new Map();
366
+ for (const [path, entry] of Object.entries(lineage.files)) {
367
+ const old = fromSource.get(path);
368
+ if (old && fileHash(old) === entry.sha256) {
369
+ base.set(path, old);
370
+ continue;
371
+ }
372
+ const abs = join(scopeDir, path);
373
+ if (existsSync(abs)) {
374
+ const data = readFileSync(abs);
375
+ if (fileHash(data) === entry.sha256)
376
+ base.set(path, data);
377
+ }
378
+ }
379
+ return base;
380
+ }
381
+ // ── Governance ───────────────────────────────────────────────────────────────
382
+ const GOVERNANCE = [
383
+ /(^|\/)[^/]+\.op\.[cm]?[jt]s$/,
384
+ /(^|\/)chant\.config\.(ts|js|mjs|cjs|json)$/,
385
+ /(^|\/)chant\.workspace\.jsonc?$/,
386
+ /(^|\/)\.github\/workflows\//,
387
+ /(^|\/)\.forgejo\/workflows\//,
388
+ /(^|\/)\.gitea\/workflows\//,
389
+ /(^|\/)\.gitlab-ci\.ya?ml$/,
390
+ /(^|\/)CODEOWNERS$/,
391
+ ];
392
+ /** Whether a repository path is a governance file: one that decides gates, pipelines or review. */
393
+ export function isGovernancePath(path) {
394
+ return GOVERNANCE.some((re) => re.test(path));
395
+ }
396
+ /**
397
+ * The approval an upgrade gate asks for when the patch changes governance
398
+ * files. Only human approvals count, and the gate needs as many as the
399
+ * strictest gate declared at HEAD in any Op file the patch changes, at least
400
+ * one. The Op files are read from the project's tree, which the upgrade
401
+ * requires to match HEAD for every path the patch touches.
402
+ */
403
+ async function rulesAtHead(root, repo, paths) {
404
+ const opFiles = new Set(paths.filter((p) => GOVERNANCE[0].test(p)));
405
+ let count = 1;
406
+ let roles;
407
+ if (opFiles.size > 0) {
408
+ const { discoverOps } = await import("../op/discover.js");
409
+ const { ops } = await discoverOps({ cwd: root });
410
+ for (const { config, filePath } of ops.values()) {
411
+ const rel = relative(repo, filePath).split(sep).join("/");
412
+ if (!opFiles.has(rel))
413
+ continue;
414
+ for (const approval of gateApprovals(config)) {
415
+ const need = approval.quorum?.count ?? 1;
416
+ if (need > count) {
417
+ count = need;
418
+ roles = approval.quorum?.roles;
419
+ }
420
+ }
421
+ }
422
+ }
423
+ return { mode: "log-only", quorum: { count, ...(roles && roles.length > 0 ? { roles } : {}) } };
424
+ }
425
+ function gateApprovals(config) {
426
+ const out = [];
427
+ const visit = (step) => {
428
+ if (step.kind === "gate")
429
+ out.push(step.approval ?? {});
430
+ if (step.kind === "effect")
431
+ (step.steps ?? []).forEach(visit);
432
+ };
433
+ for (const p of [...(config.phases ?? []), ...(config.onFailure ?? [])])
434
+ p.steps.forEach(visit);
435
+ return out;
436
+ }
437
+ // ── Stage ────────────────────────────────────────────────────────────────────
438
+ function gitOut(cwd, args) {
439
+ return execFileSync("git", args, { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"], maxBuffer: 256 * 1024 * 1024 });
440
+ }
441
+ function isChantProject(dir) {
442
+ return ["chant.config.ts", "chant.config.json", "chant.config.js", "chant.config.mjs"].some((f) => existsSync(join(dir, f)));
443
+ }
444
+ function tail(text, lines = 30) {
445
+ return text.trimEnd().split("\n").slice(-lines).join("\n");
446
+ }
447
+ /**
448
+ * The `chant` members `chant.workspace.json` declares in `dir` (#2804): a
449
+ * template built as a workspace, such as the studio kit's, keeps its chant
450
+ * project in a member (`delivery`), not at the scope's root, and the root
451
+ * itself never has a `chant.config`. Empty when `dir` declares no workspace,
452
+ * or the declaration cannot be read: the caller then falls back to `dir`
453
+ * itself.
454
+ */
455
+ function chantMemberDirs(dir) {
456
+ try {
457
+ return readDeclaration(workingTree(dir))
458
+ .members.filter((m) => m.kind === "chant")
459
+ .map((m) => m.dir);
460
+ }
461
+ catch (err) {
462
+ if (err instanceof WorkspaceReadError)
463
+ return [];
464
+ throw err;
465
+ }
466
+ }
467
+ /**
468
+ * Resolve the scope argument against `root` (#2550). A scope the lock at
469
+ * `root` holds is used as it is. Otherwise a member the workspace
470
+ * declaration names (by name or directory) that keeps a lock of its own is
471
+ * upgraded from its directory, as the project it is, so its patch, gate and
472
+ * build stay inside it. A member without a lock was not made from a template.
473
+ */
474
+ export function resolveUpgradeTarget(root, scopeArg) {
475
+ const scope = scopeKey(scopeArg ?? ".");
476
+ const lock = readLock(root);
477
+ if (lock?.scopes[scope])
478
+ return { root, scope };
479
+ if (scope !== ".") {
480
+ let declared = [];
481
+ try {
482
+ declared = readDeclaration(workingTree(root)).members;
483
+ }
484
+ catch (err) {
485
+ if (!(err instanceof WorkspaceReadError))
486
+ throw err;
487
+ }
488
+ const hit = declared.find((m) => m.dir !== "." && (m.name === scopeArg || scopeKey(m.dir) === scope));
489
+ if (hit?.kind === "workspace") {
490
+ // A nested workspace upgrades itself; the outer one never writes inside it (D2, #2551).
491
+ throw new UpgradeError(`member "${hit.name}" is a nested workspace, which upgrades itself: run chant workspace upgrade in ${hit.dir}`);
492
+ }
493
+ if (hit) {
494
+ const memberRoot = join(root, hit.dir);
495
+ if (readLock(memberRoot))
496
+ return { root: memberRoot, scope: ".", member: hit.name };
497
+ throw new UpgradeError(`member "${hit.name}" (${hit.dir}) has no ${LOCK_FILE}, so it was not made from a template and has nothing to upgrade. \`chant init --from <template> ${hit.dir}\` writes one; \`chant workspace adopt-lineage\` is for an older member.`);
498
+ }
499
+ }
500
+ return { root, scope };
501
+ }
502
+ /**
503
+ * Stage an upgrade: steps 1 to 5 and the digest of step 6. Nothing in the
504
+ * project's tree changes. The caller decides the gate, then applies the patch
505
+ * with {@link applyStagedUpgrade} or commits it with {@link commitStagedUpgrade},
506
+ * and always calls `dispose()`.
507
+ */
508
+ export async function stageUpgrade(options) {
509
+ const { root, scope, member } = resolveUpgradeTarget(resolve(options.root), options.scope);
510
+ const lock = readLock(root);
511
+ if (!lock)
512
+ throw new UpgradeError(`no ${LOCK_FILE} in ${root}`);
513
+ const lineage = lock.scopes[scope];
514
+ if (!lineage) {
515
+ throw new UpgradeError(`${LOCK_FILE} has no scope "${scope}" (scopes: ${Object.keys(lock.scopes).join(", ") || "none"})`);
516
+ }
517
+ if (lineage.manualSteps.length > 0) {
518
+ throw new UpgradeError(`scope "${scope}" has ${lineage.manualSteps.length} open manual step(s) from its last update (${lineage.manualSteps.map((s) => s.path).join(", ")}). Merge them and run \`chant workspace lineage resolve <path>\` first.`);
519
+ }
520
+ let repo;
521
+ let head;
522
+ try {
523
+ repo = gitOut(root, ["rev-parse", "--show-toplevel"]).trim();
524
+ head = gitOut(root, ["rev-parse", "HEAD"]).trim();
525
+ }
526
+ catch {
527
+ throw new UpgradeError("chant workspace upgrade stages its change in a git worktree, so the project must be in a git repository with at least one commit");
528
+ }
529
+ const projectRel = relative(repo, root).split(sep).join("/");
530
+ const scopeRepoPath = [projectRel, scope === "." ? "" : scope].filter(Boolean).join("/") || ".";
531
+ const lockRepoPath = [projectRel, LOCK_FILE].filter(Boolean).join("/");
532
+ let lockTracked = true;
533
+ try {
534
+ gitOut(repo, ["ls-files", "--error-unmatch", "--", lockRepoPath]);
535
+ }
536
+ catch {
537
+ lockTracked = false;
538
+ }
539
+ const dirty = gitOut(repo, ["status", "--porcelain", "--untracked-files=all", "--", scopeRepoPath, lockRepoPath])
540
+ .split("\n")
541
+ .filter(Boolean)
542
+ .filter((line) => !line.slice(3).startsWith(`${[projectRel, UPGRADE_DIR].filter(Boolean).join("/")}/`));
543
+ if (dirty.length > 0) {
544
+ throw new UpgradeError(`the scope has uncommitted changes (${dirty.slice(0, 5).map((l) => l.slice(3)).join(", ")}${dirty.length > 5 ? ", …" : ""}). Commit or stash them: the upgrade stages from HEAD and applies its patch to the tree.`);
545
+ }
546
+ // A move to another template (#2551): a git scope only, and to a named ref.
547
+ let onto;
548
+ if (options.source !== undefined) {
549
+ const spec = parseTemplateSource(options.source, root, "--source");
550
+ if (spec.ref !== undefined)
551
+ throw new UpgradeError(`--source ${options.source}: name the version with --to, not "@${spec.ref}"`);
552
+ if (options.to === undefined)
553
+ throw new UpgradeError("--source moves the scope to another template, so it needs --to <ref>: a version of that template");
554
+ if (lineage.source.type !== "git") {
555
+ throw new UpgradeError(`scope "${scope}" has a ${lineage.source.type} source; only a git scope moves to another template. A directory scope moves onto git with chant workspace adopt-lineage first.`);
556
+ }
557
+ onto = { url: spec.url, repo: spec.repo, ...(spec.member ? { path: spec.member } : {}), id: spec.id };
558
+ }
559
+ const switching = onto !== undefined && onto.id !== lineage.template;
560
+ // 1. Fetch. A directory source has no ref: `--to` names the directory.
561
+ const fromDir = lineage.source.type === "dir";
562
+ const ref = fromDir ? undefined : options.to ?? lineage.ref;
563
+ const upstream = await fetchUpstream(root, lineage, fromDir ? options.to : ref, onto);
564
+ // 2. The merge base, offline from here on.
565
+ const base = rebuildBase(join(root, scope), lineage, upstream.base);
566
+ // Plan the chain before anything is staged, so a gap refuses early.
567
+ const plan = lineage.kind === "template" ? planMigrations(lineage, ref, upstream.migrations, onto?.id) : { chain: [] };
568
+ assertCodeAllowed(plan.chain, !!options.allowCode);
569
+ // 3. The worktree, inside the project so the project's packages resolve.
570
+ const holder = join(root, UPGRADE_DIR);
571
+ mkdirSync(holder, { recursive: true });
572
+ const worktree = mkdtempSync(join(holder, `${scope === "." ? "root" : basename(scope)}-`));
573
+ let disposed = false;
574
+ const dispose = () => {
575
+ if (disposed)
576
+ return;
577
+ disposed = true;
578
+ try {
579
+ gitOut(repo, ["worktree", "remove", "--force", worktree]);
580
+ }
581
+ catch {
582
+ // Fall through to the directory removal and a prune.
583
+ }
584
+ rmSync(worktree, { recursive: true, force: true });
585
+ try {
586
+ gitOut(repo, ["worktree", "prune"]);
587
+ }
588
+ catch {
589
+ // Nothing to prune.
590
+ }
591
+ if (existsSync(holder) && readdirSync(holder).length === 0)
592
+ rmSync(holder, { recursive: true, force: true });
593
+ };
594
+ try {
595
+ gitOut(repo, ["worktree", "add", "-q", "--detach", worktree, head]);
596
+ const worktreeProject = projectRel ? join(worktree, projectRel) : worktree;
597
+ const scopeDir = join(worktreeProject, scope);
598
+ const next = structuredClone(lock);
599
+ const staged = next.scopes[scope];
600
+ const scratch = mkdtempSync(join(tmpdir(), "chant-upgrade-code-"));
601
+ try {
602
+ for (const m of plan.chain) {
603
+ await runMigration(m, {
604
+ dir: scopeDir,
605
+ lineage: staged,
606
+ modules: upstream.modules,
607
+ allowCode: !!options.allowCode,
608
+ scratch,
609
+ onMove: (from, to) => {
610
+ const data = base.get(from);
611
+ base.delete(from);
612
+ if (data)
613
+ base.set(to, data);
614
+ },
615
+ });
616
+ }
617
+ }
618
+ finally {
619
+ rmSync(scratch, { recursive: true, force: true });
620
+ }
621
+ // chant's own migrations (#2737): planned from what the scope holds, and
622
+ // applied only when the plan has no conflict. A conflict fails the checks.
623
+ // Each is planned from the tree the ones before it left.
624
+ const chantRuns = lineage.kind === "template" ? runChantMigrations({ dir: scopeDir, lineage: staged, chantVersion: readerVersion() }) : [];
625
+ const chantMigrations = chantRuns.map((r) => reportPlan(r.plan, r.applied));
626
+ // 4. Merge per file.
627
+ const result = applyUpstream(scopeDir, staged, upstream.files, { base, merge: mergeFile });
628
+ for (const path of result.written)
629
+ if (upstream.executable.has(path))
630
+ chmodSync(join(scopeDir, path), 0o755);
631
+ if (ref !== undefined)
632
+ staged.ref = ref;
633
+ if (upstream.parameters)
634
+ staged.parameters = upstream.parameters;
635
+ if (upstream.repinned) {
636
+ // The records this version re-pins, among the files the scope keeps (#2549).
637
+ const kept = upstream.repinned.filter((r) => staged.files[r.record] !== undefined || existsSync(join(scopeDir, r.record)));
638
+ if (kept.length > 0)
639
+ staged.repinned = kept;
640
+ else
641
+ delete staged.repinned;
642
+ }
643
+ if (upstream.commit)
644
+ staged.address = { ...staged.address, commit: upstream.commit, tree: upstream.tree };
645
+ if (upstream.source)
646
+ staged.source = upstream.source;
647
+ if (onto) {
648
+ staged.template = onto.id;
649
+ staged.source = { type: "git", repo: onto.repo, url: portableUrl(onto.url, root), ...(onto.path ? { path: onto.path } : {}) };
650
+ }
651
+ writeLock(worktreeProject, next);
652
+ const lockText = renderLock(next);
653
+ // The CI workflows a chant member builds, rebuilt with this chant (#3244),
654
+ // before the patch is taken so the gate approves them with the rest.
655
+ const workflows = lineage.kind === "template" ? await rebuildWorkflows(root, worktree, worktreeProject, scopeRepoPath, options.runChant ?? spawnChant) : [];
656
+ // The patch, taken before anything else runs in the worktree.
657
+ gitOut(worktree, ["add", "-A"]);
658
+ if (!lockTracked)
659
+ gitOut(worktree, ["rm", "--cached", "-q", "--ignore-unmatch", "--", lockRepoPath]);
660
+ const patch = gitOut(worktree, ["diff", "--cached", "--binary", "--full-index", "--no-color", "--no-ext-diff", head]);
661
+ const changedPaths = gitOut(worktree, ["diff", "--cached", "--name-only", "-z", head]).split("\0").filter(Boolean).sort();
662
+ // An upgrade writes inside its scope and the lock that records it, and nowhere else.
663
+ const outside = changedPaths.filter((p) => scopeRepoPath !== "." && p !== lockRepoPath && p !== scopeRepoPath && !p.startsWith(`${scopeRepoPath}/`));
664
+ if (outside.length > 0) {
665
+ throw new UpgradeError(`the upgrade would change ${outside.slice(0, 5).join(", ")}${outside.length > 5 ? ", ..." : ""}, outside the scope "${scopeRepoPath}". An upgrade writes only inside its own scope.`);
666
+ }
667
+ const lockChanged = !lockTracked && lockText !== readFileSync(join(root, LOCK_FILE), "utf-8");
668
+ const changed = patch.length > 0 || lockChanged;
669
+ const digest = computePlanDigest(UPGRADE_PLAN_KIND, lockTracked ? { scope, patch } : { scope, patch, lock: lockText });
670
+ // The outer workspace never writes inside a nested one (D2, #2551): that one upgrades itself.
671
+ const inNested = pathsInsideNested(worktreeProject, projectRel, changedPaths);
672
+ if (inNested.length > 0) {
673
+ throw new UpgradeError(`the upgrade would change files inside the nested workspace ${inNested[0].member} (${inNested.slice(0, 5).map((p) => p.path).join(", ")}). A nested workspace upgrades itself with its own chant workspace upgrade, and the outer one never writes inside it.`);
674
+ }
675
+ // Governance: decided by the rules at HEAD, never by the upgraded files.
676
+ const governed = changedPaths.filter(isGovernancePath);
677
+ let governance = null;
678
+ if (governed.length > 0) {
679
+ const existing = governed.filter((p) => existsSync(join(repo, p)));
680
+ const touched = existing.length === 0 ? [] : gitOut(repo, ["status", "--porcelain", "--", ...existing]).split("\n").filter(Boolean);
681
+ if (touched.length > 0) {
682
+ throw new UpgradeError(`the upgrade changes governance files that have uncommitted edits (${touched.map((l) => l.slice(3)).join(", ")}). Commit them first: their gates are read at HEAD.`);
683
+ }
684
+ governance = { paths: governed, approval: await rulesAtHead(root, repo, governed), rules: head };
685
+ }
686
+ // 5. Checks.
687
+ const checks = [];
688
+ for (const w of workflows.filter((w) => w.status === "failed")) {
689
+ checks.push({
690
+ name: "build",
691
+ status: "failed",
692
+ member: w.member,
693
+ detail: `${w.path} could not be rebuilt with \`${w.command}\` (the ${w.script} script), so it may differ from what this chant builds:\n${w.detail ?? ""}`,
694
+ });
695
+ }
696
+ for (const m of chantMigrations.filter((m) => !m.applied)) {
697
+ checks.push({
698
+ name: "migration",
699
+ status: "failed",
700
+ detail: `${m.id} was not applied: ${m.conflicts.map((c) => `${c.path}: ${c.reason}`).join("\n")}`,
701
+ });
702
+ }
703
+ if (changed) {
704
+ // Every `chant` member chant.workspace.json declares, so a template
705
+ // whose chant project sits in a member (the studio kit's `delivery/`)
706
+ // is built and linted there, not skipped for having no chant.config at
707
+ // the scope's root (#2804). A scope with no workspace declaration falls
708
+ // back to the root, as before.
709
+ const members = chantMemberDirs(worktreeProject);
710
+ const targets = members.length > 0 ? members : isChantProject(worktreeProject) ? ["."] : [];
711
+ if (targets.length > 0) {
712
+ const run = options.runChant ?? spawnChant;
713
+ const namedMember = targets.length > 1 || targets[0] !== ".";
714
+ // A member that installs its packages in its own directory resolves them from its node_modules, which is not
715
+ // an ancestor of the staging worktree: link it in from the project (#2847). The patch and its digest are
716
+ // computed above, so the links never reach them, and dispose() removes them with the worktree.
717
+ for (const member of targets) {
718
+ if (member === ".")
719
+ continue;
720
+ const from = join(root, member, "node_modules");
721
+ const to = join(worktreeProject, member, "node_modules");
722
+ if (existsSync(from) && !existsSync(to) && existsSync(dirname(to)))
723
+ symlinkSync(from, to, "dir");
724
+ }
725
+ for (const member of targets) {
726
+ const dir = member === "." ? worktreeProject : join(worktreeProject, member);
727
+ const at = namedMember ? { member } : {};
728
+ for (const command of ["build", "lint"]) {
729
+ const r = await run(command, dir);
730
+ checks.push(r.exitCode === 0 ? { name: command, status: "passed", ...at } : { name: command, status: "failed", detail: tail(r.output), ...at });
731
+ }
732
+ }
733
+ }
734
+ else {
735
+ for (const name of ["build", "lint"])
736
+ checks.push({ name, status: "skipped", detail: "not a chant project (no chant.config)" });
737
+ }
738
+ checks.push(lineageCheck(root, worktreeProject, result.manualSteps, scope));
739
+ }
740
+ return {
741
+ scope,
742
+ ...(member !== undefined ? { member } : {}),
743
+ gate: member ?? scope,
744
+ template: lineage.template,
745
+ ...(switching ? { switchedTo: onto.id } : {}),
746
+ kind: lineage.kind,
747
+ from: fromDir ? sourcePin(lineage.source) : lineage.ref ?? null,
748
+ to: fromDir ? sourcePin(staged.source) : staged.ref ?? null,
749
+ ...(upstream.commit ? { commit: { ...(lineage.address?.commit ? { from: lineage.address.commit } : {}), to: upstream.commit } } : {}),
750
+ migrations: [...plan.chain.map((m) => m.migration.id), ...chantMigrations.filter((m) => m.applied).map((m) => m.id)],
751
+ chantMigrations,
752
+ workflows,
753
+ written: result.written,
754
+ merged: result.merged,
755
+ removed: result.removed,
756
+ kept: result.kept,
757
+ skipped: result.skipped,
758
+ manualSteps: result.manualSteps,
759
+ changedPaths,
760
+ patch,
761
+ lock: { path: lockRepoPath, tracked: lockTracked, text: lockText },
762
+ changed,
763
+ digest,
764
+ governance,
765
+ checks,
766
+ checksOk: checks.every((c) => c.status !== "failed"),
767
+ repo,
768
+ head,
769
+ worktree,
770
+ worktreeProject,
771
+ dispose,
772
+ };
773
+ }
774
+ catch (err) {
775
+ dispose();
776
+ throw err;
777
+ }
778
+ }
779
+ /** A directory source's pin, for the summary: the directory it reads. */
780
+ function sourcePin(source) {
781
+ return source.type === "dir" ? dirLabel(source.path, source.member) : null;
782
+ }
783
+ /**
784
+ * `chant workspace check` in the worktree. A finding already present at HEAD
785
+ * is not the upgrade's doing, and the upgrade's own manual steps are what the
786
+ * gate approves; any other finding fails the check.
787
+ */
788
+ function lineageCheck(root, worktreeProject, ownSteps, scope) {
789
+ const before = new Set(checkLineage(root).findings.map(findingKey));
790
+ const own = new Set(ownSteps.map((s) => (scope === "." ? s.path : `${scope}/${s.path}`)));
791
+ const report = checkLineage(worktreeProject);
792
+ const fresh = report.findings.filter((f) => !before.has(findingKey(f)) && !(f.code === "manual-step-open" && f.path !== undefined && own.has(f.path)));
793
+ if (fresh.length === 0)
794
+ return { name: "workspace check", status: "passed" };
795
+ return { name: "workspace check", status: "failed", detail: fresh.map((f) => `${f.path ?? f.scope ?? ""}: ${f.message}`).join("\n") };
796
+ }
797
+ // ── Apply or propose ─────────────────────────────────────────────────────────
798
+ /** Apply the staged patch to the project's tree. Leaves it uncommitted. */
799
+ export function applyStagedUpgrade(staged) {
800
+ if (!staged.lock.tracked)
801
+ writeFileSync(join(staged.repo, staged.lock.path), staged.lock.text);
802
+ if (!staged.patch)
803
+ return;
804
+ const file = join(mkdtempSync(join(tmpdir(), "chant-upgrade-patch-")), "upgrade.patch");
805
+ try {
806
+ writeFileSync(file, staged.patch);
807
+ execFileSync("git", ["apply", "--binary", "--whitespace=nowarn", file], { cwd: staged.repo, stdio: ["ignore", "pipe", "pipe"] });
808
+ }
809
+ catch (err) {
810
+ const stderr = err.stderr?.toString().trim();
811
+ throw new UpgradeError(`the approved patch no longer applies to the tree${stderr ? `: ${stderr}` : ""}`);
812
+ }
813
+ finally {
814
+ rmSync(join(file, ".."), { recursive: true, force: true });
815
+ }
816
+ }
817
+ /**
818
+ * Commit the staged patch in the worktree and point `branch` at it. Returns
819
+ * the commit. The caller has already refused the default branch.
820
+ */
821
+ export function commitStagedUpgrade(staged, branch, message) {
822
+ const identity = [];
823
+ const has = (key) => {
824
+ try {
825
+ return gitOut(staged.worktree, ["config", key]).trim().length > 0;
826
+ }
827
+ catch {
828
+ return false;
829
+ }
830
+ };
831
+ if (!has("user.name"))
832
+ identity.push("-c", "user.name=chant");
833
+ if (!has("user.email"))
834
+ identity.push("-c", "user.email=chant@localhost");
835
+ // An ignored lock is still part of the proposal: the branch starts tracking it.
836
+ if (!staged.lock.tracked)
837
+ gitOut(staged.worktree, ["add", "-f", "--", staged.lock.path]);
838
+ gitOut(staged.worktree, [...identity, "commit", "-q", "--no-verify", "-m", message]);
839
+ const commit = gitOut(staged.worktree, ["rev-parse", "HEAD"]).trim();
840
+ gitOut(staged.repo, ["branch", "-f", branch, commit]);
841
+ return commit;
842
+ }
843
+ /** One line per staged change, for the terminal and for a PR body. */
844
+ export function describeStaged(staged) {
845
+ const lines = [];
846
+ const at = (p) => (staged.scope === "." ? p : `${staged.scope}/${p}`);
847
+ lines.push(`${staged.gate} ${staged.template} ${staged.from ?? "(no ref)"} -> ${staged.to ?? "(no ref)"}`);
848
+ if (staged.switchedTo)
849
+ lines.push(` template: ${staged.template} -> ${staged.switchedTo}`);
850
+ const chantIds = new Set(staged.chantMigrations.map((m) => m.id));
851
+ for (const id of staged.migrations)
852
+ if (!chantIds.has(id))
853
+ lines.push(` migration: ${id}`);
854
+ for (const m of staged.chantMigrations) {
855
+ lines.push(` chant migration: ${m.id} (${m.applied ? "applied" : "not applied: it has conflicts"}), to ${m.description}`);
856
+ for (const c of m.changes)
857
+ lines.push(` ${c.action === "delete" ? "delete" : "write"}: ${at(c.path)} (${c.why}${c.edited ? "; it was edited since the template, and the edit stays in git history" : ""})`);
858
+ for (const n of m.notMoved)
859
+ lines.push(` not moved: ${n.what} -> ${n.where}`);
860
+ for (const c of m.conflicts)
861
+ lines.push(` conflict: ${at(c.path)}: ${c.reason}`);
862
+ }
863
+ for (const w of staged.workflows) {
864
+ if (w.status !== "unchanged")
865
+ lines.push(` workflow ${w.status === "rebuilt" ? "rebuilt" : "not rebuilt"}: ${w.path} (${w.script}: ${w.command})`);
866
+ }
867
+ for (const p of staged.written)
868
+ lines.push(` updated: ${at(p)}`);
869
+ for (const p of staged.merged)
870
+ lines.push(` merged: ${at(p)}`);
871
+ for (const p of staged.removed)
872
+ lines.push(` removed: ${at(p)}`);
873
+ for (const s of staged.skipped) {
874
+ if (s.class === "generated")
875
+ lines.push(` generated, not merged: ${at(s.path)}${s.command ? ` (rebuild with ${s.command})` : ""}`);
876
+ }
877
+ for (const s of staged.manualSteps)
878
+ lines.push(` manual step: ${at(s.path)} (${s.reason})`);
879
+ if (staged.governance) {
880
+ const q = staged.governance.approval.quorum;
881
+ lines.push(` governance: ${staged.governance.paths.join(", ")}; needs ${q.count} human approval(s)${q.roles ? ` with a role in ${q.roles.join(", ")}` : ""}, from the rules at ${staged.governance.rules.slice(0, 12)}`);
882
+ }
883
+ for (const c of staged.checks) {
884
+ const label = c.member !== undefined ? `${c.name} (${c.member})` : c.name;
885
+ lines.push(` ${label}: ${c.status}${c.status === "skipped" && c.detail ? ` (${c.detail})` : ""}`);
886
+ }
887
+ lines.push(` patch: ${staged.changedPaths.length} file(s)${staged.lock.tracked ? "" : ` and the untracked ${LOCK_FILE}`}, ${staged.digest}`);
888
+ return lines;
889
+ }