@intentius/chant 0.57.0 → 0.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (504) hide show
  1. package/dist/audit/catalog.d.ts +51 -1
  2. package/dist/audit/catalog.d.ts.map +1 -1
  3. package/dist/audit/core.d.ts +20 -1
  4. package/dist/audit/core.d.ts.map +1 -1
  5. package/dist/audit/discover.d.ts +14 -8
  6. package/dist/audit/discover.d.ts.map +1 -1
  7. package/dist/audit/lineage.d.ts +10 -0
  8. package/dist/audit/lineage.d.ts.map +1 -0
  9. package/dist/audit/prior-art.d.ts +385 -0
  10. package/dist/audit/prior-art.d.ts.map +1 -0
  11. package/dist/audit/proof.d.ts +16 -0
  12. package/dist/audit/proof.d.ts.map +1 -1
  13. package/dist/audit/report-html.d.ts.map +1 -1
  14. package/dist/audit/report-model.d.ts +8 -1
  15. package/dist/audit/report-model.d.ts.map +1 -1
  16. package/dist/audit/report.d.ts.map +1 -1
  17. package/dist/audit/rules-doc.d.ts +3 -0
  18. package/dist/audit/rules-doc.d.ts.map +1 -1
  19. package/dist/audit/secrets.d.ts +15 -0
  20. package/dist/audit/secrets.d.ts.map +1 -1
  21. package/dist/audit/terraform-state.d.ts +46 -0
  22. package/dist/audit/terraform-state.d.ts.map +1 -0
  23. package/dist/build.d.ts +17 -1
  24. package/dist/build.d.ts.map +1 -1
  25. package/dist/claimed-fields.d.ts +161 -0
  26. package/dist/claimed-fields.d.ts.map +1 -0
  27. package/dist/cli/build-params-cli.d.ts +2 -2
  28. package/dist/cli/command-group.d.ts +14 -0
  29. package/dist/cli/command-group.d.ts.map +1 -1
  30. package/dist/cli/commands/audit.d.ts +17 -1
  31. package/dist/cli/commands/audit.d.ts.map +1 -1
  32. package/dist/cli/commands/build.d.ts.map +1 -1
  33. package/dist/cli/commands/check-lexicon-docs.d.ts +1 -1
  34. package/dist/cli/commands/check-lexicon-examples.d.ts +16 -6
  35. package/dist/cli/commands/check-lexicon-examples.d.ts.map +1 -1
  36. package/dist/cli/commands/init-lexicon/templates/codegen.d.ts +1 -0
  37. package/dist/cli/commands/init-lexicon/templates/codegen.d.ts.map +1 -1
  38. package/dist/cli/commands/init-lexicon/templates/project.d.ts +7 -0
  39. package/dist/cli/commands/init-lexicon/templates/project.d.ts.map +1 -1
  40. package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
  41. package/dist/cli/commands/init.d.ts.map +1 -1
  42. package/dist/cli/commands/lint.d.ts.map +1 -1
  43. package/dist/cli/commands/onboard.d.ts +2 -0
  44. package/dist/cli/commands/onboard.d.ts.map +1 -1
  45. package/dist/cli/handlers/build.d.ts.map +1 -1
  46. package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
  47. package/dist/cli/handlers/operator.d.ts +82 -16
  48. package/dist/cli/handlers/operator.d.ts.map +1 -1
  49. package/dist/cli/handlers/run.d.ts +49 -42
  50. package/dist/cli/handlers/run.d.ts.map +1 -1
  51. package/dist/cli/main.d.ts +28 -1
  52. package/dist/cli/main.d.ts.map +1 -1
  53. package/dist/cli/mcp/op-tools.d.ts +16 -1
  54. package/dist/cli/mcp/op-tools.d.ts.map +1 -1
  55. package/dist/cli/mcp/resource-handlers.d.ts.map +1 -1
  56. package/dist/cli/mcp/resources/context.d.ts.map +1 -1
  57. package/dist/cli/registry.d.ts +26 -9
  58. package/dist/cli/registry.d.ts.map +1 -1
  59. package/dist/codegen/generate-post-synth-barrel.d.ts +1 -1
  60. package/dist/components/auto-release.d.ts +10 -20
  61. package/dist/components/auto-release.d.ts.map +1 -1
  62. package/dist/components/capability.d.ts +4 -4
  63. package/dist/components/cli-support.d.ts +20 -21
  64. package/dist/components/cli-support.d.ts.map +1 -1
  65. package/dist/components/component.d.ts +3 -3
  66. package/dist/components/component.d.ts.map +1 -1
  67. package/dist/components/driver-output.d.ts.map +1 -1
  68. package/dist/components/driver.d.ts +66 -36
  69. package/dist/components/driver.d.ts.map +1 -1
  70. package/dist/components/index.d.ts +1 -2
  71. package/dist/components/index.d.ts.map +1 -1
  72. package/dist/components/manifest-persistence.d.ts +1 -9
  73. package/dist/components/manifest-persistence.d.ts.map +1 -1
  74. package/dist/components/run-progress.d.ts +6 -6
  75. package/dist/components/run-progress.d.ts.map +1 -1
  76. package/dist/components/verbs/run-agent.d.ts +9 -15
  77. package/dist/components/verbs/run-agent.d.ts.map +1 -1
  78. package/dist/components/verbs/verify.d.ts +2 -2
  79. package/dist/deep-observation.d.ts +17 -0
  80. package/dist/deep-observation.d.ts.map +1 -1
  81. package/dist/discovery/files.d.ts +4 -4
  82. package/dist/discovery/fold-import.d.ts.map +1 -1
  83. package/dist/discovery/param-deps.d.ts +33 -0
  84. package/dist/discovery/param-deps.d.ts.map +1 -1
  85. package/dist/discovery/sandbox/bundle.d.ts.map +1 -1
  86. package/dist/discovery/sandbox/config-wire.d.ts +2 -2
  87. package/dist/fold/foldable-helpers.d.ts +5 -1
  88. package/dist/fold/foldable-helpers.d.ts.map +1 -1
  89. package/dist/fold-provenance.d.ts +236 -0
  90. package/dist/fold-provenance.d.ts.map +1 -0
  91. package/dist/graph-ops.d.ts +1 -1
  92. package/dist/held-elsewhere.d.ts +85 -0
  93. package/dist/held-elsewhere.d.ts.map +1 -0
  94. package/dist/index.d.ts +3 -0
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/kubectl-context.d.ts +3 -3
  97. package/dist/lexicon-config.d.ts +4 -4
  98. package/dist/lexicon-plugin-helpers.d.ts +1 -1
  99. package/dist/lexicon.d.ts +104 -14
  100. package/dist/lexicon.d.ts.map +1 -1
  101. package/dist/lifecycle/change-set.d.ts +13 -0
  102. package/dist/lifecycle/change-set.d.ts.map +1 -1
  103. package/dist/lifecycle/deep-diff.d.ts +133 -6
  104. package/dist/lifecycle/deep-diff.d.ts.map +1 -1
  105. package/dist/lifecycle/deep-observe.d.ts.map +1 -1
  106. package/dist/lifecycle/gate-ledger.d.ts +71 -3
  107. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  108. package/dist/lifecycle/index.d.ts +1 -0
  109. package/dist/lifecycle/index.d.ts.map +1 -1
  110. package/dist/lifecycle/release-ledger.d.ts +2 -2
  111. package/dist/lifecycle/run-ledger.d.ts +53 -0
  112. package/dist/lifecycle/run-ledger.d.ts.map +1 -0
  113. package/dist/lifecycle/symptoms.d.ts +3 -3
  114. package/dist/lifecycle/symptoms.d.ts.map +1 -1
  115. package/dist/lint/config.d.ts +81 -2
  116. package/dist/lint/config.d.ts.map +1 -1
  117. package/dist/lint/post-synth.d.ts +55 -2
  118. package/dist/lint/post-synth.d.ts.map +1 -1
  119. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts +1 -1
  120. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts.map +1 -1
  121. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts +1 -1
  122. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts.map +1 -1
  123. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts +44 -0
  124. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts.map +1 -0
  125. package/dist/lint/rules/comp/index.d.ts +1 -1
  126. package/dist/lint/rules/comp/index.d.ts.map +1 -1
  127. package/dist/lint/rules/op/index.d.ts +16 -0
  128. package/dist/lint/rules/op/index.d.ts.map +1 -0
  129. package/dist/lint/rules/op/ops012-activity-contract.d.ts +27 -0
  130. package/dist/lint/rules/op/ops012-activity-contract.d.ts.map +1 -0
  131. package/dist/lint/rules/op/ops013-step-output-ref.d.ts +61 -0
  132. package/dist/lint/rules/op/ops013-step-output-ref.d.ts.map +1 -0
  133. package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts +55 -0
  134. package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts.map +1 -0
  135. package/dist/lint/rules/op/support.d.ts +12 -0
  136. package/dist/lint/rules/op/support.d.ts.map +1 -0
  137. package/dist/lint/suppressions.d.ts +108 -0
  138. package/dist/lint/suppressions.d.ts.map +1 -0
  139. package/dist/live-endpoint.d.ts +1 -1
  140. package/dist/op/activities/activity-contracts.d.ts +54 -0
  141. package/dist/op/activities/activity-contracts.d.ts.map +1 -0
  142. package/dist/op/activities/apply.d.ts +262 -0
  143. package/dist/op/activities/apply.d.ts.map +1 -0
  144. package/dist/op/activities/build.d.ts +13 -0
  145. package/dist/op/activities/build.d.ts.map +1 -0
  146. package/dist/op/activities/converge.d.ts +110 -0
  147. package/dist/op/activities/converge.d.ts.map +1 -0
  148. package/dist/op/activities/env-teardown.d.ts +76 -0
  149. package/dist/op/activities/env-teardown.d.ts.map +1 -0
  150. package/dist/op/activities/guard-validate.d.ts +64 -0
  151. package/dist/op/activities/guard-validate.d.ts.map +1 -0
  152. package/dist/op/activities/http-check.d.ts +34 -0
  153. package/dist/op/activities/http-check.d.ts.map +1 -0
  154. package/dist/op/activities/index.d.ts +31 -0
  155. package/dist/op/activities/index.d.ts.map +1 -0
  156. package/dist/op/activities/lexicon-upgrade.d.ts +182 -0
  157. package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -0
  158. package/dist/op/activities/lifecycle.d.ts +42 -0
  159. package/dist/op/activities/lifecycle.d.ts.map +1 -0
  160. package/dist/op/activities/pipeline-audit.d.ts +84 -0
  161. package/dist/op/activities/pipeline-audit.d.ts.map +1 -0
  162. package/dist/op/activities/policy.d.ts +17 -0
  163. package/dist/op/activities/policy.d.ts.map +1 -0
  164. package/dist/op/activities/reconcile.d.ts +89 -0
  165. package/dist/op/activities/reconcile.d.ts.map +1 -0
  166. package/dist/op/activities/shell.d.ts +13 -0
  167. package/dist/op/activities/shell.d.ts.map +1 -0
  168. package/dist/op/activities/teardown.d.ts +10 -0
  169. package/dist/op/activities/teardown.d.ts.map +1 -0
  170. package/dist/op/activities/util.d.ts +7 -0
  171. package/dist/op/activities/util.d.ts.map +1 -0
  172. package/dist/op/activities/wait.d.ts +28 -0
  173. package/dist/op/activities/wait.d.ts.map +1 -0
  174. package/dist/op/activities/workflow-audit.d.ts +92 -0
  175. package/dist/op/activities/workflow-audit.d.ts.map +1 -0
  176. package/dist/op/activity-contract-registry.d.ts +76 -0
  177. package/dist/op/activity-contract-registry.d.ts.map +1 -0
  178. package/dist/op/activity-contract.d.ts +25 -18
  179. package/dist/op/activity-contract.d.ts.map +1 -1
  180. package/dist/op/activity-failure.d.ts +28 -0
  181. package/dist/op/activity-failure.d.ts.map +1 -0
  182. package/dist/op/activity-profiles.d.ts +118 -0
  183. package/dist/op/activity-profiles.d.ts.map +1 -0
  184. package/dist/op/activity-registry.d.ts +22 -38
  185. package/dist/op/activity-registry.d.ts.map +1 -1
  186. package/dist/op/activity-runtime.d.ts +3 -14
  187. package/dist/op/activity-runtime.d.ts.map +1 -1
  188. package/dist/op/builders.d.ts +84 -29
  189. package/dist/op/builders.d.ts.map +1 -1
  190. package/dist/op/composites/apply-op.d.ts +113 -0
  191. package/dist/op/composites/apply-op.d.ts.map +1 -0
  192. package/dist/op/composites/converge-op.d.ts +120 -0
  193. package/dist/op/composites/converge-op.d.ts.map +1 -0
  194. package/dist/op/composites/index.d.ts +26 -0
  195. package/dist/op/composites/index.d.ts.map +1 -0
  196. package/dist/op/composites/lexicon-upgrade-op.d.ts +78 -0
  197. package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -0
  198. package/dist/op/composites/pipeline-audit-op.d.ts +50 -0
  199. package/dist/op/composites/pipeline-audit-op.d.ts.map +1 -0
  200. package/dist/op/composites/reconcile-op.d.ts +57 -0
  201. package/dist/op/composites/reconcile-op.d.ts.map +1 -0
  202. package/dist/op/composites/watch-op.d.ts +60 -0
  203. package/dist/op/composites/watch-op.d.ts.map +1 -0
  204. package/dist/op/composites/workflow-audit-op.d.ts +57 -0
  205. package/dist/op/composites/workflow-audit-op.d.ts.map +1 -0
  206. package/dist/op/converge-rule.d.ts +12 -10
  207. package/dist/op/converge-rule.d.ts.map +1 -1
  208. package/dist/op/cron.d.ts +51 -0
  209. package/dist/op/cron.d.ts.map +1 -0
  210. package/dist/op/discover.d.ts +9 -0
  211. package/dist/op/discover.d.ts.map +1 -1
  212. package/dist/op/duration.d.ts +11 -0
  213. package/dist/op/duration.d.ts.map +1 -0
  214. package/dist/op/emulator-lifecycle.d.ts.map +1 -1
  215. package/dist/op/gate.d.ts +90 -0
  216. package/dist/op/gate.d.ts.map +1 -0
  217. package/dist/op/generate-pipeline.d.ts +9 -0
  218. package/dist/op/generate-pipeline.d.ts.map +1 -1
  219. package/dist/op/index.d.ts +23 -7
  220. package/dist/op/index.d.ts.map +1 -1
  221. package/dist/op/local-executor.d.ts +114 -28
  222. package/dist/op/local-executor.d.ts.map +1 -1
  223. package/dist/op/local-output.d.ts +11 -1
  224. package/dist/op/local-output.d.ts.map +1 -1
  225. package/dist/op/op-ir.d.ts +184 -0
  226. package/dist/op/op-ir.d.ts.map +1 -0
  227. package/dist/op/op-verb-class.d.ts +10 -2
  228. package/dist/op/op-verb-class.d.ts.map +1 -1
  229. package/dist/op/operator.d.ts +30 -5
  230. package/dist/op/operator.d.ts.map +1 -1
  231. package/dist/op/receipt-store.d.ts +1 -1
  232. package/dist/op/receipt-store.d.ts.map +1 -1
  233. package/dist/op/resource.d.ts +15 -1
  234. package/dist/op/resource.d.ts.map +1 -1
  235. package/dist/op/runtime.d.ts +200 -0
  236. package/dist/op/runtime.d.ts.map +1 -0
  237. package/dist/op/runtimes/local.d.ts +29 -0
  238. package/dist/op/runtimes/local.d.ts.map +1 -0
  239. package/dist/op/step-output-ref.d.ts +15 -13
  240. package/dist/op/step-output-ref.d.ts.map +1 -1
  241. package/dist/op/types.d.ts +79 -27
  242. package/dist/op/types.d.ts.map +1 -1
  243. package/dist/ownership.d.ts +1 -1
  244. package/dist/provenance.d.ts +21 -0
  245. package/dist/provenance.d.ts.map +1 -1
  246. package/dist/serializer-walker.d.ts.map +1 -1
  247. package/package.json +6 -1
  248. package/src/audit/catalog.test.ts +79 -3
  249. package/src/audit/catalog.ts +111 -13
  250. package/src/audit/core.test.ts +26 -0
  251. package/src/audit/core.ts +61 -17
  252. package/src/audit/discover.test.ts +39 -0
  253. package/src/audit/discover.ts +91 -15
  254. package/src/audit/lineage.ts +100 -0
  255. package/src/audit/prior-art.ts +153 -0
  256. package/src/audit/proof.test.ts +67 -0
  257. package/src/audit/proof.ts +70 -0
  258. package/src/audit/report-html.ts +9 -4
  259. package/src/audit/report-model.ts +16 -2
  260. package/src/audit/report.test.ts +33 -0
  261. package/src/audit/report.ts +5 -3
  262. package/src/audit/rules-doc.test.ts +34 -2
  263. package/src/audit/rules-doc.ts +82 -9
  264. package/src/audit/secrets.ts +15 -3
  265. package/src/audit/terraform-state.test.ts +144 -0
  266. package/src/audit/terraform-state.ts +131 -0
  267. package/src/build.ts +31 -1
  268. package/src/claimed-fields.test.ts +145 -0
  269. package/src/claimed-fields.ts +208 -0
  270. package/src/cli/build-params-cli.ts +2 -2
  271. package/src/cli/command-group.ts +14 -0
  272. package/src/cli/commands/__fixtures__/audit-terraform/infra/.terraform/providers/lock.txt +1 -0
  273. package/src/cli/commands/__fixtures__/audit-terraform/infra/main.tf +1 -0
  274. package/src/cli/commands/__fixtures__/audit-terraform/infra/modules/foo/main.tf +1 -0
  275. package/src/cli/commands/__fixtures__/audit-terraform/infra/variables.tf +3 -0
  276. package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +13 -4
  277. package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/docs-cli.ts +4 -0
  278. package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/package.ts +1 -0
  279. package/src/cli/commands/__fixtures__/init-lexicon-output/src/package-cli.ts +21 -0
  280. package/src/cli/commands/__snapshots__/init-lexicon.test.ts.snap +1 -0
  281. package/src/cli/commands/audit.test.ts +189 -11
  282. package/src/cli/commands/audit.ts +73 -27
  283. package/src/cli/commands/build.test.ts +292 -9
  284. package/src/cli/commands/build.ts +156 -24
  285. package/src/cli/commands/check-lexicon-docs.ts +1 -1
  286. package/src/cli/commands/check-lexicon-examples.test.ts +29 -1
  287. package/src/cli/commands/check-lexicon-examples.ts +42 -10
  288. package/src/cli/commands/init-lexicon/templates/codegen.ts +9 -0
  289. package/src/cli/commands/init-lexicon/templates/project.ts +44 -4
  290. package/src/cli/commands/init-lexicon.test.ts +97 -2
  291. package/src/cli/commands/init-lexicon.ts +4 -2
  292. package/src/cli/commands/init.test.ts +35 -1
  293. package/src/cli/commands/init.ts +14 -3
  294. package/src/cli/commands/lint.test.ts +48 -0
  295. package/src/cli/commands/lint.ts +123 -0
  296. package/src/cli/commands/onboard.test.ts +75 -0
  297. package/src/cli/commands/onboard.ts +54 -23
  298. package/src/cli/handlers/build.test.ts +81 -1
  299. package/src/cli/handlers/build.ts +15 -1
  300. package/src/cli/handlers/graph.test.ts +3 -3
  301. package/src/cli/handlers/lifecycle.test.ts +195 -12
  302. package/src/cli/handlers/lifecycle.ts +123 -6
  303. package/src/cli/handlers/misc.ts +1 -1
  304. package/src/cli/handlers/operator.test.ts +183 -11
  305. package/src/cli/handlers/operator.ts +260 -55
  306. package/src/cli/handlers/run.test.ts +431 -1287
  307. package/src/cli/handlers/run.ts +365 -915
  308. package/src/cli/main.test.ts +23 -15
  309. package/src/cli/main.ts +88 -33
  310. package/src/cli/mcp/op-tools.ts +147 -88
  311. package/src/cli/mcp/resource-handlers.ts +10 -37
  312. package/src/cli/mcp/resources/context.ts +11 -12
  313. package/src/cli/mcp/server.test.ts +25 -27
  314. package/src/cli/mcp/server.ts +2 -2
  315. package/src/cli/registry.ts +26 -9
  316. package/src/codegen/docs.ts +1 -1
  317. package/src/codegen/generate-post-synth-barrel.test.ts +1 -1
  318. package/src/codegen/generate-post-synth-barrel.ts +1 -1
  319. package/src/components/README.md +3 -2
  320. package/src/components/auto-release.test.ts +4 -20
  321. package/src/components/auto-release.ts +17 -42
  322. package/src/components/capability.ts +4 -4
  323. package/src/components/cli-support.test.ts +10 -5
  324. package/src/components/cli-support.ts +52 -44
  325. package/src/components/component.schema.json +2 -2
  326. package/src/components/component.ts +3 -3
  327. package/src/components/driver-output.ts +14 -2
  328. package/src/components/driver.test.ts +92 -22
  329. package/src/components/driver.ts +193 -83
  330. package/src/components/index.ts +1 -6
  331. package/src/components/manifest-persistence.test.ts +2 -20
  332. package/src/components/manifest-persistence.ts +4 -24
  333. package/src/components/pilots/pilots-lint-clean.test.ts +11 -10
  334. package/src/components/run-progress.ts +6 -6
  335. package/src/components/verbs/run-agent.ts +11 -17
  336. package/src/components/verbs/verify.ts +2 -2
  337. package/src/deep-observation.test.ts +75 -0
  338. package/src/deep-observation.ts +48 -0
  339. package/src/discovery/collect.test.ts +3 -3
  340. package/src/discovery/files.ts +4 -4
  341. package/src/discovery/fold-import.ts +105 -2
  342. package/src/discovery/param-deps.test.ts +112 -1
  343. package/src/discovery/param-deps.ts +193 -0
  344. package/src/discovery/sandbox/bundle.ts +15 -1
  345. package/src/discovery/sandbox/config-wire.test.ts +2 -2
  346. package/src/discovery/sandbox/config-wire.ts +2 -2
  347. package/src/fold/fold.test.ts +56 -0
  348. package/src/fold/foldable-helpers.ts +81 -1
  349. package/src/fold-provenance-exclusion.test.ts +186 -0
  350. package/src/fold-provenance.test.ts +495 -0
  351. package/src/fold-provenance.ts +441 -0
  352. package/src/graph-ops.test.ts +2 -2
  353. package/src/graph-ops.ts +1 -1
  354. package/src/held-elsewhere.test.ts +102 -0
  355. package/src/held-elsewhere.ts +114 -0
  356. package/src/index.ts +3 -0
  357. package/src/kubectl-context.ts +3 -3
  358. package/src/lexicon-config.test.ts +5 -5
  359. package/src/lexicon-config.ts +4 -4
  360. package/src/lexicon-plugin-helpers.ts +1 -1
  361. package/src/lexicon.ts +120 -14
  362. package/src/lifecycle/change-set.test.ts +49 -0
  363. package/src/lifecycle/change-set.ts +67 -0
  364. package/src/lifecycle/converge-ledger.ts +1 -1
  365. package/src/lifecycle/deep-diff.test.ts +267 -14
  366. package/src/lifecycle/deep-diff.ts +217 -14
  367. package/src/lifecycle/deep-observe.test.ts +3 -1
  368. package/src/lifecycle/deep-observe.ts +16 -6
  369. package/src/lifecycle/gate-ledger.test.ts +74 -2
  370. package/src/lifecycle/gate-ledger.ts +143 -36
  371. package/src/lifecycle/index.ts +1 -0
  372. package/src/lifecycle/release-ledger.ts +2 -2
  373. package/src/lifecycle/run-ledger.test.ts +268 -0
  374. package/src/lifecycle/run-ledger.ts +201 -0
  375. package/src/lifecycle/symptoms.ts +3 -3
  376. package/src/lint/config.test.ts +82 -1
  377. package/src/lint/config.ts +112 -3
  378. package/src/lint/policy.test.ts +1 -1
  379. package/src/lint/post-synth.test.ts +31 -0
  380. package/src/lint/post-synth.ts +54 -1
  381. package/src/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.ts +2 -2
  382. package/src/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.ts +1 -1
  383. package/src/lint/rules/comp/comp.test.ts +1 -1
  384. package/src/lint/rules/comp/comp004-gate-needs-durable-runtime.ts +74 -0
  385. package/src/lint/rules/comp/index.ts +3 -3
  386. package/src/lint/rules/op/index.ts +23 -0
  387. package/src/lint/rules/op/ops012-activity-contract.test.ts +161 -0
  388. package/src/lint/rules/op/ops012-activity-contract.ts +64 -0
  389. package/src/lint/rules/op/ops013-step-output-ref.test.ts +237 -0
  390. package/src/lint/rules/op/ops013-step-output-ref.ts +98 -0
  391. package/src/lint/rules/op/ops014-converge-rule-refusals.test.ts +263 -0
  392. package/src/lint/rules/op/ops014-converge-rule-refusals.ts +179 -0
  393. package/src/lint/rules/op/support.ts +11 -0
  394. package/src/lint/suppressions.test.ts +163 -0
  395. package/src/lint/suppressions.ts +204 -0
  396. package/src/live-endpoint.ts +1 -1
  397. package/src/op/activities/activity-contracts.ts +66 -0
  398. package/src/op/activities/apply.test.ts +567 -0
  399. package/src/op/activities/apply.ts +662 -0
  400. package/src/op/activities/build.ts +26 -0
  401. package/src/op/activities/converge.test.ts +330 -0
  402. package/src/op/activities/converge.ts +449 -0
  403. package/src/op/activities/env-teardown.test.ts +187 -0
  404. package/src/op/activities/env-teardown.ts +171 -0
  405. package/src/op/activities/guard-validate.test.ts +139 -0
  406. package/src/op/activities/guard-validate.ts +223 -0
  407. package/src/op/activities/http-check.test.ts +48 -0
  408. package/src/op/activities/http-check.ts +55 -0
  409. package/src/op/activities/index.ts +119 -0
  410. package/src/op/activities/lexicon-upgrade.test.ts +492 -0
  411. package/src/op/activities/lexicon-upgrade.ts +673 -0
  412. package/src/op/activities/lifecycle.ts +85 -0
  413. package/src/op/activities/pipeline-audit.test.ts +67 -0
  414. package/src/op/activities/pipeline-audit.ts +201 -0
  415. package/src/op/activities/policy.test.ts +19 -0
  416. package/src/op/activities/policy.ts +37 -0
  417. package/src/op/activities/reconcile.test.ts +81 -0
  418. package/src/op/activities/reconcile.ts +187 -0
  419. package/src/op/activities/shell.ts +26 -0
  420. package/src/op/activities/teardown.ts +22 -0
  421. package/src/op/activities/util.ts +6 -0
  422. package/src/op/activities/wait.ts +69 -0
  423. package/src/op/activities/workflow-audit.test.ts +90 -0
  424. package/src/op/activities/workflow-audit.ts +203 -0
  425. package/src/op/activity-contract-registry.test.ts +98 -0
  426. package/src/op/activity-contract-registry.ts +114 -0
  427. package/src/op/activity-contract.test.ts +1 -1
  428. package/src/op/activity-contract.ts +37 -33
  429. package/src/op/activity-failure.ts +34 -0
  430. package/src/op/activity-profiles.test.ts +56 -0
  431. package/src/op/activity-profiles.ts +116 -0
  432. package/src/op/activity-registry.test.ts +37 -28
  433. package/src/op/activity-registry.ts +27 -56
  434. package/src/op/activity-runtime.ts +3 -47
  435. package/src/op/builders-exports.test.ts +0 -49
  436. package/src/op/builders-typed.test.ts +164 -0
  437. package/src/op/builders.ts +123 -39
  438. package/src/op/composites/apply-op.ts +208 -0
  439. package/src/op/composites/composites.test.ts +366 -0
  440. package/src/op/composites/converge-op.test.ts +168 -0
  441. package/src/op/composites/converge-op.ts +214 -0
  442. package/src/op/composites/index.ts +26 -0
  443. package/src/op/composites/lexicon-upgrade-op.test.ts +68 -0
  444. package/src/op/composites/lexicon-upgrade-op.ts +134 -0
  445. package/src/op/composites/pipeline-audit-op.test.ts +25 -0
  446. package/src/op/composites/pipeline-audit-op.ts +78 -0
  447. package/src/op/composites/reconcile-op.test.ts +51 -0
  448. package/src/op/composites/reconcile-op.ts +107 -0
  449. package/src/op/composites/watch-op.ts +108 -0
  450. package/src/op/composites/workflow-audit-op.test.ts +25 -0
  451. package/src/op/composites/workflow-audit-op.ts +88 -0
  452. package/src/op/converge-rule.ts +12 -10
  453. package/src/op/cron.test.ts +128 -0
  454. package/src/op/cron.ts +149 -0
  455. package/src/op/discover-root.test.ts +105 -1
  456. package/src/op/discover.test.ts +6 -2
  457. package/src/op/discover.ts +84 -16
  458. package/src/op/duration.ts +21 -0
  459. package/src/op/effect-step.test.ts +26 -11
  460. package/src/op/emulator-lifecycle.ts +1 -2
  461. package/src/op/gate.ts +155 -0
  462. package/src/op/generate-pipeline.test.ts +65 -3
  463. package/src/op/generate-pipeline.ts +19 -2
  464. package/src/op/index.ts +39 -6
  465. package/src/op/local-executor.test.ts +163 -34
  466. package/src/op/local-executor.ts +370 -102
  467. package/src/op/local-output.test.ts +95 -11
  468. package/src/op/local-output.ts +33 -4
  469. package/src/op/op-ir.test.ts +281 -0
  470. package/src/op/op-ir.ts +417 -0
  471. package/src/op/op-verb-class.ts +19 -5
  472. package/src/op/op.test.ts +26 -5
  473. package/src/op/operator.test.ts +175 -6
  474. package/src/op/operator.ts +63 -16
  475. package/src/op/receipt-store.ts +1 -1
  476. package/src/op/resource.ts +20 -2
  477. package/src/op/runtime.ts +203 -0
  478. package/src/op/runtimes/local.test.ts +181 -0
  479. package/src/op/runtimes/local.ts +212 -0
  480. package/src/op/step-output-ref.ts +15 -13
  481. package/src/op/types.ts +84 -24
  482. package/src/ownership.ts +1 -1
  483. package/src/provenance.test.ts +6 -0
  484. package/src/provenance.ts +21 -1
  485. package/src/serializer-walker.test.ts +42 -0
  486. package/src/serializer-walker.ts +21 -2
  487. package/dist/cli/handlers/op-progress.d.ts +0 -90
  488. package/dist/cli/handlers/op-progress.d.ts.map +0 -1
  489. package/dist/cli/handlers/run-client.d.ts +0 -127
  490. package/dist/cli/handlers/run-client.d.ts.map +0 -1
  491. package/dist/cli/handlers/run-report.d.ts +0 -5
  492. package/dist/cli/handlers/run-report.d.ts.map +0 -1
  493. package/dist/components/temporal-codegen-loader.d.ts +0 -27
  494. package/dist/components/temporal-codegen-loader.d.ts.map +0 -1
  495. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts +0 -37
  496. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts.map +0 -1
  497. package/src/cli/handlers/op-progress.test.ts +0 -268
  498. package/src/cli/handlers/op-progress.ts +0 -248
  499. package/src/cli/handlers/run-client.test.ts +0 -82
  500. package/src/cli/handlers/run-client.ts +0 -219
  501. package/src/cli/handlers/run-report.test.ts +0 -62
  502. package/src/cli/handlers/run-report.ts +0 -122
  503. package/src/components/temporal-codegen-loader.ts +0 -41
  504. package/src/lint/rules/comp/comp004-gate-needs-temporal.ts +0 -66
@@ -0,0 +1,119 @@
1
+ export { chantBuild } from "./build";
2
+ export type { ChantBuildArgs } from "./build";
3
+
4
+ // kubectl activity relocated to the k8s lexicon (#809) — loadActivities(["k8s"])
5
+ // provides kubectlApply. The kubectlApply step builder stays in core.
6
+
7
+ // helm activity relocated to the helm lexicon (#809) — loadActivities(["helm"])
8
+ // provides helmInstall. The helmInstall step builder stays in core.
9
+
10
+ export { waitForStack } from "./wait";
11
+ export type { WaitForStackArgs } from "./wait";
12
+
13
+ // gitlab activity relocated to the gitlab lexicon (#809) — loadActivities(["gitlab"])
14
+ // provides gitlabPipeline. The gitlabPipeline step builder stays in core.
15
+
16
+ export { shellCmd } from "./shell";
17
+ export type { ShellCmdArgs } from "./shell";
18
+
19
+ export { httpCheck, statusOk } from "./http-check";
20
+ export type { HttpCheckArgs, HttpFetch } from "./http-check";
21
+
22
+ export { lifecycleSnapshot, lifecycleDiff } from "./lifecycle";
23
+ export type { LifecycleSnapshotArgs, LifecycleDiffArgs, LifecycleDiffResult } from "./lifecycle";
24
+
25
+ export { chantTeardown } from "./teardown";
26
+ export type { ChantTeardownArgs } from "./teardown";
27
+
28
+ export { envTeardown } from "./env-teardown";
29
+ export type { EnvTeardownArgs, EnvTeardownResult, EnvTeardownDeps } from "./env-teardown";
30
+
31
+ // k3d activities relocated to the k8s lexicon (#809), then to their own k3d
32
+ // lexicon (#1410) — loadActivities(["k3d"]) provides k3dUp/k3dDown. The step
33
+ // builders stay in core.
34
+
35
+ // Sprites (Fly product) moved to the fly lexicon — a lexicon owns its own
36
+ // product's activities. `loadActivities(["fly"])` now provides the sprite
37
+ // activities + the spritzer emulator lifecycle. See lexicons/fly/src/op/activities.
38
+ //
39
+ // Cloud/k8s-specific activities likewise live in their own lexicons (aws → floci,
40
+ // gcp → gcpApply, azure → az group, k8s → kubectl/k3d/argo) and are loaded from
41
+ // there by the activity registry per the project's configured lexicons. What is
42
+ // here is the product-agnostic base every runtime needs, core's own since #2114:
43
+ // the registry imports this module statically, so a project that installs
44
+ // nothing but chant still resolves every step below.
45
+
46
+ export { reconcilePr } from "./reconcile";
47
+ export type { ReconcilePrArgs, ReconcileResult, ReconcileMode, ReconcileEntry } from "./reconcile";
48
+
49
+ export { nativeApply, compensateApply, hasNativeRollback } from "./apply";
50
+ export type {
51
+ NativeApplyArgs,
52
+ NativeApplyResult,
53
+ CompensateApplyArgs,
54
+ CompensateApplyResult,
55
+ ApplyTarget,
56
+ DeleteMode,
57
+ K8sApplier,
58
+ AzureApplier,
59
+ GcpApplier,
60
+ FlyApplier,
61
+ AwsApplier,
62
+ AwsRollback,
63
+ } from "./apply";
64
+
65
+ // argo activity (waitForArgoSync) relocated to the k8s lexicon (#809) —
66
+ // loadActivities(["k8s"]) provides it. Argo CD is Kubernetes-native.
67
+
68
+ export { policyGate } from "./policy";
69
+ export type { PolicyGateArgs } from "./policy";
70
+
71
+ export { guardValidate, parseGuardFindings } from "./guard-validate";
72
+ export type { GuardValidateArgs, GuardValidateResult, GuardFinding } from "./guard-validate";
73
+
74
+ export { workflowSupplyChainAudit, collectAuditRefs, defaultActionRefResolver } from "./workflow-audit";
75
+ export type {
76
+ WorkflowAuditArgs,
77
+ WorkflowAuditResult,
78
+ WorkflowAuditMode,
79
+ WorkflowAuditFinding,
80
+ WorkflowAuditFindingKind,
81
+ ActionRefResolver,
82
+ ActionRefResolution,
83
+ } from "./workflow-audit";
84
+
85
+ export { pipelineSupplyChainAudit, collectPipelineRefs, defaultGitlabRefResolver } from "./pipeline-audit";
86
+ export type {
87
+ PipelineAuditArgs,
88
+ PipelineAuditResult,
89
+ PipelineAuditMode,
90
+ PipelineAuditFinding,
91
+ PipelineAuditFindingKind,
92
+ PipelineRefKind,
93
+ GitlabRefResolver,
94
+ PipelineRefResolution,
95
+ } from "./pipeline-audit";
96
+
97
+ export { convergeTick, planConvergeTick } from "./converge";
98
+ export type { ConvergeTickArgs, ConvergeTickResult, ConvergeTickPlan, SerializedConvergeRule } from "./converge";
99
+
100
+ export {
101
+ lexiconUpgrade,
102
+ isPinned,
103
+ isRolling,
104
+ severityToLabel,
105
+ upgradeBranchName,
106
+ upgradePrTitle,
107
+ buildUpgradeSummary,
108
+ } from "./lexicon-upgrade";
109
+ export type {
110
+ LexiconUpgradeArgs,
111
+ LexiconUpgradeResult,
112
+ LexiconUpgradeMode,
113
+ SupportedLexicon,
114
+ SemverLabel,
115
+ CheckPinnedFn,
116
+ CheckRollingFn,
117
+ GhRunner,
118
+ ApplyBumpFn,
119
+ } from "./lexicon-upgrade";
@@ -0,0 +1,492 @@
1
+ import { describe, test, expect, vi } from "vitest";
2
+ import {
3
+ lexiconUpgrade,
4
+ isPinned,
5
+ isRolling,
6
+ severityToLabel,
7
+ upgradeBranchName,
8
+ upgradePrTitle,
9
+ buildUpgradeSummary,
10
+ computeBumpedVersion,
11
+ bumpPackageJsonVersion,
12
+ type CheckPinnedFn,
13
+ type CheckRollingFn,
14
+ type BumpPackageVersionFn,
15
+ } from "./lexicon-upgrade";
16
+ import type { UpgradeCheckResult } from "../../codegen/pinned-upgrade";
17
+ import type { RollingUpgradeResult } from "../../codegen/rolling-upgrade";
18
+ import { tmpdir } from "node:os";
19
+ import { join } from "node:path";
20
+ import { writeFileSync, readFileSync } from "node:fs";
21
+
22
+ // ── Classification ────────────────────────────────────────────────────
23
+
24
+ describe("pinned vs rolling classification", () => {
25
+ test("pinned lexicons", () => {
26
+ for (const l of ["k8s", "gcp", "docker", "gitlab"] as const) {
27
+ expect(isPinned(l)).toBe(true);
28
+ expect(isRolling(l)).toBe(false);
29
+ }
30
+ });
31
+
32
+ test("rolling lexicons", () => {
33
+ for (const l of ["aws", "azure", "github"] as const) {
34
+ expect(isRolling(l)).toBe(true);
35
+ expect(isPinned(l)).toBe(false);
36
+ }
37
+ });
38
+ });
39
+
40
+ // ── Semver label mapping ──────────────────────────────────────────────
41
+
42
+ describe("severityToLabel", () => {
43
+ test("additive → minor", () => expect(severityToLabel("additive")).toBe("minor"));
44
+ test("breaking → breaking", () => expect(severityToLabel("breaking")).toBe("breaking"));
45
+ test("none → null", () => expect(severityToLabel("none")).toBeNull());
46
+ test("unknown → null", () => expect(severityToLabel("wibble")).toBeNull());
47
+ });
48
+
49
+ // ── Naming helpers ────────────────────────────────────────────────────
50
+
51
+ describe("branch / PR naming", () => {
52
+ test("long-lived branch per lexicon", () => {
53
+ expect(upgradeBranchName("k8s")).toBe("lexicon-upgrade/k8s");
54
+ expect(upgradeBranchName("aws")).toBe("lexicon-upgrade/aws");
55
+ });
56
+
57
+ test("PR title with from/to", () => {
58
+ expect(upgradePrTitle("k8s", "v1.32.0", "v1.33.0")).toBe(
59
+ "feat(k8s): upgrade spec v1.32.0 to v1.33.0",
60
+ );
61
+ });
62
+
63
+ test("PR title without version (rolling)", () => {
64
+ expect(upgradePrTitle("aws")).toBe("feat(aws): upgrade to latest spec");
65
+ });
66
+ });
67
+
68
+ // ── Summary builder ───────────────────────────────────────────────────
69
+
70
+ describe("buildUpgradeSummary", () => {
71
+ test("additive upgrade renders delta + label", () => {
72
+ const s = buildUpgradeSummary({
73
+ lexicon: "aws",
74
+ deltaText: "Added: AWS::S3::Bucket",
75
+ semverLabel: "minor",
76
+ validationOk: true,
77
+ });
78
+ expect(s).toContain("Lexicon upgrade: aws");
79
+ expect(s).toContain("minor");
80
+ expect(s).toContain("Added: AWS::S3::Bucket");
81
+ });
82
+
83
+ test("validation failure renders failures block", () => {
84
+ const s = buildUpgradeSummary({
85
+ lexicon: "gitlab",
86
+ deltaText: "",
87
+ semverLabel: null,
88
+ validationOk: false,
89
+ failures: [{ step: "build", output: "tsc exploded" }],
90
+ });
91
+ expect(s).toContain("Validation failures");
92
+ expect(s).toContain("tsc exploded");
93
+ });
94
+
95
+ test("reports examples lint clean when no example failures (#604)", () => {
96
+ const s = buildUpgradeSummary({
97
+ lexicon: "aws",
98
+ deltaText: "Added: AWS::S3::Bucket",
99
+ semverLabel: "minor",
100
+ validationOk: true,
101
+ failures: [],
102
+ });
103
+ expect(s).toContain("**Examples:** lint clean");
104
+ });
105
+
106
+ test("flags failing examples when a lint/examples step fails (#604)", () => {
107
+ const s = buildUpgradeSummary({
108
+ lexicon: "k8s",
109
+ deltaText: "",
110
+ semverLabel: "breaking",
111
+ validationOk: false,
112
+ failures: [{ step: "lint", output: "example web.ts: cannot find name 'Hub'" }],
113
+ });
114
+ expect(s).toContain("**Examples:** ⚠️");
115
+ expect(s).toContain("check(s) failing");
116
+ // The example failure detail is still rendered in the failures block.
117
+ expect(s).toContain("cannot find name 'Hub'");
118
+ });
119
+ });
120
+
121
+ // ── Mock builders ─────────────────────────────────────────────────────
122
+
123
+ function pinnedResult(over: Partial<UpgradeCheckResult> = {}): UpgradeCheckResult {
124
+ return {
125
+ lexicon: "k8s",
126
+ hasUpgrade: true,
127
+ from: "v1.32.0",
128
+ to: "v1.33.0",
129
+ validation: {
130
+ ok: true,
131
+ changed: true,
132
+ severity: "additive",
133
+ delta: { added: [], changed: [], removed: [], renamed: [], severity: "additive" },
134
+ deltaText: "Added: apps/v1 Deployment field",
135
+ failures: [],
136
+ freshSnapshot: null,
137
+ },
138
+ fetchError: null,
139
+ ...over,
140
+ };
141
+ }
142
+
143
+ function rollingResult(over: Partial<RollingUpgradeResult> = {}): RollingUpgradeResult {
144
+ return {
145
+ lexicon: "aws",
146
+ hasUpgrade: true,
147
+ severity: "breaking",
148
+ delta: { added: [], changed: [], removed: [], renamed: [], severity: "breaking" },
149
+ deltaText: "Removed: AWS::Foo::Bar",
150
+ validationOk: true,
151
+ failures: [],
152
+ apiVersionDelta: [],
153
+ freshSnapshot: null,
154
+ ...over,
155
+ };
156
+ }
157
+
158
+ // A gh runner that records the commands it was asked to run.
159
+ function recordingGh() {
160
+ const calls: string[] = [];
161
+ const gh = vi.fn(async (cmd: string) => {
162
+ calls.push(cmd);
163
+ if (cmd.includes("gh pr create")) return { stdout: "https://gh/pr/1", stderr: "" };
164
+ if (cmd.includes("gh issue create")) return { stdout: "https://gh/issue/1", stderr: "" };
165
+ // gh pr view with no open PR → empty
166
+ return { stdout: "", stderr: "" };
167
+ });
168
+ return { gh, calls };
169
+ }
170
+
171
+ // ── report mode (default, no external services) ───────────────────────
172
+
173
+ describe("lexiconUpgrade report mode", () => {
174
+ test("pinned: dispatches to checkPinnedUpgrade, reports delta + label", async () => {
175
+ const checkPinned: CheckPinnedFn = vi.fn(async () => pinnedResult());
176
+ const { gh, calls } = recordingGh();
177
+
178
+ const r = await lexiconUpgrade({
179
+ lexicon: "k8s",
180
+ mode: "report",
181
+ _checkPinned: checkPinned,
182
+ _gh: gh,
183
+ });
184
+
185
+ expect(checkPinned).toHaveBeenCalledOnce();
186
+ expect(r.hasUpgrade).toBe(true);
187
+ expect(r.semverLabel).toBe("minor");
188
+ expect(r.validationOk).toBe(true);
189
+ expect(r.deltaText).toContain("apps/v1");
190
+ // report mode must not touch gh
191
+ expect(calls).toHaveLength(0);
192
+ });
193
+
194
+ test("rolling: dispatches to checkRollingUpgrade, breaking → breaking label", async () => {
195
+ const checkRolling: CheckRollingFn = vi.fn(async () => rollingResult());
196
+ const { gh } = recordingGh();
197
+
198
+ const r = await lexiconUpgrade({
199
+ lexicon: "aws",
200
+ mode: "report",
201
+ _checkRolling: checkRolling,
202
+ _gh: gh,
203
+ });
204
+
205
+ expect(checkRolling).toHaveBeenCalledOnce();
206
+ expect(r.semverLabel).toBe("breaking");
207
+ expect(r.deltaText).toContain("AWS::Foo::Bar");
208
+ });
209
+
210
+ test("no upgrade → hasUpgrade false, no label", async () => {
211
+ const checkRolling: CheckRollingFn = vi.fn(async () =>
212
+ rollingResult({ hasUpgrade: false, severity: "none", deltaText: "" }),
213
+ );
214
+ const r = await lexiconUpgrade({
215
+ lexicon: "github",
216
+ mode: "report",
217
+ _checkRolling: checkRolling,
218
+ });
219
+ expect(r.hasUpgrade).toBe(false);
220
+ expect(r.semverLabel).toBeNull();
221
+ });
222
+ });
223
+
224
+ // ── issue mode ────────────────────────────────────────────────────────
225
+
226
+ describe("lexiconUpgrade issue mode", () => {
227
+ test("opens an issue for a ready upgrade", async () => {
228
+ const checkPinned: CheckPinnedFn = vi.fn(async () => pinnedResult());
229
+ const { gh, calls } = recordingGh();
230
+
231
+ const r = await lexiconUpgrade({
232
+ lexicon: "gcp",
233
+ mode: "issue",
234
+ _checkPinned: checkPinned,
235
+ _gh: gh,
236
+ });
237
+
238
+ expect(r.issueUrl).toBe("https://gh/issue/1");
239
+ expect(calls.some((c) => c.includes("gh issue create"))).toBe(true);
240
+ expect(calls.some((c) => c.includes("gh pr create"))).toBe(false);
241
+ });
242
+ });
243
+
244
+ // ── validation failure never becomes a PR ─────────────────────────────
245
+
246
+ describe("lexiconUpgrade breakage handling", () => {
247
+ test("failing validation in pull-request mode falls back to an issue, never a PR", async () => {
248
+ const checkPinned: CheckPinnedFn = vi.fn(async () =>
249
+ pinnedResult({
250
+ validation: {
251
+ ok: false,
252
+ changed: true,
253
+ severity: "breaking",
254
+ delta: { added: [], changed: [], removed: [], renamed: [], severity: "breaking" },
255
+ deltaText: "Removed: v1 Pod",
256
+ failures: [{ step: "build", output: "type error" }],
257
+ freshSnapshot: null,
258
+ },
259
+ }),
260
+ );
261
+ const { gh, calls } = recordingGh();
262
+
263
+ const r = await lexiconUpgrade({
264
+ lexicon: "k8s",
265
+ mode: "pull-request",
266
+ _checkPinned: checkPinned,
267
+ _gh: gh,
268
+ });
269
+
270
+ expect(r.validationOk).toBe(false);
271
+ expect(r.issueUrl).toBe("https://gh/issue/1");
272
+ expect(r.prUrl).toBeUndefined();
273
+ // must NOT open a PR, must NOT push
274
+ expect(calls.some((c) => c.includes("gh pr create"))).toBe(false);
275
+ expect(calls.some((c) => c.includes("gh issue create"))).toBe(true);
276
+ // the issue body carries the failure diff
277
+ expect(r.summary).toContain("type error");
278
+ });
279
+
280
+ test("upstream fetch error surfaces as a non-upgrade report, never a PR", async () => {
281
+ const checkPinned: CheckPinnedFn = vi.fn(async () =>
282
+ pinnedResult({ hasUpgrade: false, validation: null, fetchError: "GitHub 403" }),
283
+ );
284
+ const { gh, calls } = recordingGh();
285
+
286
+ const r = await lexiconUpgrade({
287
+ lexicon: "docker",
288
+ mode: "pull-request",
289
+ _checkPinned: checkPinned,
290
+ _gh: gh,
291
+ });
292
+
293
+ expect(r.hasUpgrade).toBe(false);
294
+ expect(r.validationOk).toBe(false);
295
+ expect(r.summary).toContain("GitHub 403");
296
+ expect(calls).toHaveLength(0);
297
+ });
298
+ });
299
+
300
+ // ── out-of-scope rejection ────────────────────────────────────────────
301
+
302
+ describe("out-of-scope lexicons", () => {
303
+ test("helm/forgejo throw", async () => {
304
+ for (const l of ["helm", "forgejo"]) {
305
+ await expect(
306
+ lexiconUpgrade({ lexicon: l as never, mode: "report" }),
307
+ ).rejects.toThrow(/not supported/);
308
+ }
309
+ });
310
+ });
311
+
312
+ // ── pull-request idempotency short-circuit ────────────────────────────
313
+
314
+ describe("lexiconUpgrade pull-request idempotency", () => {
315
+ test("when the open PR body already matches, skip git entirely and return the existing PR", async () => {
316
+ // A pinned lexicon (k8s) — pull-request idempotency applies to the version-bump
317
+ // PR path; rolling lexicons route to issues (#546).
318
+ const checkPinned: CheckPinnedFn = vi.fn(async () => pinnedResult());
319
+ // Compute what the summary will be so the mock can echo it back — must match
320
+ // the activity's own buildUpgradeSummary args for pinnedResult().
321
+ const expectedSummary = buildUpgradeSummary({
322
+ lexicon: "k8s",
323
+ from: "v1.32.0",
324
+ to: "v1.33.0",
325
+ deltaText: "Added: apps/v1 Deployment field",
326
+ semverLabel: "minor",
327
+ validationOk: true,
328
+ failures: [],
329
+ });
330
+
331
+ const calls: string[] = [];
332
+ const gh = vi.fn(async (cmd: string) => {
333
+ calls.push(cmd);
334
+ // Body query returns the current summary → idempotent, no re-PR.
335
+ if (cmd.includes("gh pr view") && cmd.includes("body")) {
336
+ return { stdout: expectedSummary, stderr: "" };
337
+ }
338
+ if (cmd.includes("gh pr view") && cmd.includes("url")) {
339
+ return { stdout: "https://gh/pr/existing", stderr: "" };
340
+ }
341
+ return { stdout: "", stderr: "" };
342
+ });
343
+
344
+ const r = await lexiconUpgrade({
345
+ lexicon: "k8s",
346
+ mode: "pull-request",
347
+ _checkPinned: checkPinned,
348
+ _applyBump: vi.fn(() => ({ filePath: "/tmp/k8s/versions.ts" })),
349
+ _bumpPackageVersion: vi.fn(),
350
+ _gh: gh,
351
+ });
352
+
353
+ expect(r.prUrl).toBe("https://gh/pr/existing");
354
+ // Idempotent path must not create or edit a PR, and must not push.
355
+ expect(calls.some((c) => c.includes("gh pr create"))).toBe(false);
356
+ expect(calls.some((c) => c.includes("gh pr edit"))).toBe(false);
357
+ expect(calls.every((c) => c.startsWith("gh pr view"))).toBe(true);
358
+ });
359
+ });
360
+
361
+ // ── computeBumpedVersion ──────────────────────────────────────────────
362
+
363
+ describe("computeBumpedVersion", () => {
364
+ test("pre-1.0 (0.x): breaking → minor, additive → patch, never 1.0.0", () => {
365
+ expect(computeBumpedVersion("0.13.1", "breaking")).toBe("0.14.0");
366
+ expect(computeBumpedVersion("0.13.1", "minor")).toBe("0.13.2");
367
+ expect(computeBumpedVersion("0.9.9", "breaking")).toBe("0.10.0"); // never promotes to 1.0.0
368
+ expect(computeBumpedVersion("0.0.1", "minor")).toBe("0.0.2");
369
+ });
370
+
371
+ test(">= 1.0.0: minor label → minor bump", () => {
372
+ expect(computeBumpedVersion("1.0.0", "minor")).toBe("1.1.0");
373
+ expect(computeBumpedVersion("2.5.9", "minor")).toBe("2.6.0");
374
+ });
375
+
376
+ test(">= 1.0.0: breaking label → major bump", () => {
377
+ expect(computeBumpedVersion("1.2.3", "breaking")).toBe("2.0.0");
378
+ expect(computeBumpedVersion("10.0.0", "breaking")).toBe("11.0.0");
379
+ });
380
+
381
+ test("strips leading v prefix", () => {
382
+ expect(computeBumpedVersion("v0.13.1", "minor")).toBe("0.13.2"); // 0.x → patch
383
+ expect(computeBumpedVersion("v0.13.1", "breaking")).toBe("0.14.0"); // 0.x → minor
384
+ expect(computeBumpedVersion("v2.0.0", "breaking")).toBe("3.0.0");
385
+ });
386
+
387
+ test("returns null for unparseable version strings", () => {
388
+ expect(computeBumpedVersion("", "minor")).toBeNull();
389
+ expect(computeBumpedVersion("not-a-version", "minor")).toBeNull();
390
+ expect(computeBumpedVersion("1.2", "minor")).toBeNull(); // only two parts
391
+ expect(computeBumpedVersion("1.x.0", "minor")).toBeNull(); // NaN segment
392
+ });
393
+ });
394
+
395
+ // ── bumpPackageJsonVersion ────────────────────────────────────────────
396
+
397
+ describe("bumpPackageJsonVersion", () => {
398
+ test("writes the new version and preserves other fields", () => {
399
+ const path = join(tmpdir(), `chant-test-pkg-${Date.now()}.json`);
400
+ const original = { name: "@intentius/chant-lexicon-k8s", version: "0.13.1", private: false };
401
+ writeFileSync(path, JSON.stringify(original, null, 2) + "\n", "utf-8");
402
+
403
+ bumpPackageJsonVersion(path, "0.14.0");
404
+
405
+ const updated = JSON.parse(readFileSync(path, "utf-8")) as typeof original;
406
+ expect(updated.version).toBe("0.14.0");
407
+ expect(updated.name).toBe("@intentius/chant-lexicon-k8s");
408
+ expect(updated.private).toBe(false);
409
+ });
410
+
411
+ test("output is valid JSON with trailing newline", () => {
412
+ const path = join(tmpdir(), `chant-test-pkg-${Date.now()}.json`);
413
+ writeFileSync(path, JSON.stringify({ version: "1.0.0" }, null, 2) + "\n", "utf-8");
414
+
415
+ bumpPackageJsonVersion(path, "2.0.0");
416
+
417
+ const raw = readFileSync(path, "utf-8");
418
+ expect(raw.endsWith("\n")).toBe(true);
419
+ expect(() => JSON.parse(raw)).not.toThrow();
420
+ });
421
+ });
422
+
423
+ // ── version-bump in pull-request mode (pinned lexicons) ──────────────
424
+
425
+ describe("lexiconUpgrade pull-request mode: package.json version bump", () => {
426
+ test("pinned lexicon: calls _bumpPackageVersion with computed version", async () => {
427
+ // Create a real temp directory with a package.json so the activity can
428
+ // read the current version before delegating the write to the mock.
429
+ const lexiconDir = join(tmpdir(), `chant-test-lexicon-k8s-${Date.now()}`);
430
+ const { mkdirSync } = await import("node:fs");
431
+ mkdirSync(lexiconDir, { recursive: true });
432
+ const pkgPath = join(lexiconDir, "package.json");
433
+ writeFileSync(pkgPath, JSON.stringify({ name: "@intentius/chant-lexicon-k8s", version: "0.13.1" }, null, 2) + "\n", "utf-8");
434
+
435
+ const checkPinned: CheckPinnedFn = vi.fn(async () => pinnedResult());
436
+ const bumps: Array<{ path: string; version: string }> = [];
437
+ const bumpFn: BumpPackageVersionFn = vi.fn((path, version) => {
438
+ bumps.push({ path, version });
439
+ });
440
+
441
+ // gh mock: no existing PR body, returns PR URL on create.
442
+ const gh = vi.fn(async (cmd: string) => {
443
+ if (cmd.includes("gh pr create")) return { stdout: "https://gh/pr/2", stderr: "" };
444
+ return { stdout: "", stderr: "" };
445
+ });
446
+
447
+ await lexiconUpgrade({
448
+ lexicon: "k8s",
449
+ mode: "pull-request",
450
+ lexiconDir,
451
+ _checkPinned: checkPinned,
452
+ _applyBump: vi.fn(() => ({ filePath: join(lexiconDir, "versions.ts") })),
453
+ _bumpPackageVersion: bumpFn,
454
+ _gh: gh,
455
+ });
456
+
457
+ // pinnedResult has severity "additive" → label "minor". Current version is
458
+ // "0.13.1" (pre-1.0) → additive bumps the patch → "0.13.2" (0.x-aware, #549).
459
+ expect(bumps.length).toBe(1);
460
+ expect(bumps[0]!.path).toBe(pkgPath);
461
+ expect(bumps[0]!.version).toBe("0.13.2");
462
+ });
463
+
464
+ test("rolling lexicon (aws) in pull-request mode opens an issue, not a PR (#546)", async () => {
465
+ const checkRolling: CheckRollingFn = vi.fn(async () => rollingResult());
466
+ const bumpFn: BumpPackageVersionFn = vi.fn();
467
+
468
+ const calls: string[] = [];
469
+ const gh = vi.fn(async (cmd: string) => {
470
+ calls.push(cmd);
471
+ if (cmd.includes("gh issue create")) return { stdout: "https://gh/issue/9", stderr: "" };
472
+ if (cmd.includes("gh pr create")) return { stdout: "https://gh/pr/3", stderr: "" };
473
+ return { stdout: "", stderr: "" };
474
+ });
475
+
476
+ const r = await lexiconUpgrade({
477
+ lexicon: "aws",
478
+ mode: "pull-request",
479
+ _checkRolling: checkRolling,
480
+ _bumpPackageVersion: bumpFn,
481
+ _gh: gh,
482
+ });
483
+
484
+ // Rolling drift → issue, never a baseline-only PR, a branch push, or a bump.
485
+ expect(r.mode).toBe("issue");
486
+ expect(r.issueUrl).toBe("https://gh/issue/9");
487
+ expect(calls.some((c) => c.includes("gh issue create"))).toBe(true);
488
+ expect(calls.some((c) => c.includes("gh pr create"))).toBe(false);
489
+ expect(calls.some((c) => c.startsWith("git "))).toBe(false);
490
+ expect(bumpFn).not.toHaveBeenCalled();
491
+ });
492
+ });