@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
@@ -1,30 +1,62 @@
1
1
  /**
2
- * Op type definitions — the data model for a named, phased Temporal workflow.
2
+ * Op type definitions — the data model for a named, phased Op.
3
3
  *
4
- * These types are intentionally free of Temporal SDK imports so they can live
5
- * in core without pulling in @temporalio/* as a dependency.
4
+ * These types are intentionally free of any runtime SDK's imports, so they can
5
+ * live in core without core depending on a runtime.
6
6
  */
7
7
  import type { EffectReceiptRef } from "./receipt-store.js";
8
+ import type { ActivityProfileName } from "./activity-profiles.js";
8
9
  export interface OpConfig {
9
- /** Kebab-case identifier. Used as the workflow function name (camelCase) and output directory name. */
10
+ /** Kebab-case identifier. Names the Op's output directory (`dist/ops/<name>/`), and is the name `chant run <name>` and another Op's `depends` refer to. */
10
11
  name: string;
11
12
  /** Human-readable description shown in `chant run list` and deployment reports. */
12
13
  overview: string;
13
- /** Temporal task queue. Defaults to `name`. */
14
- taskQueue?: string;
15
- /** Temporal namespace. Defaults to chant.config.ts defaultProfile's namespace. */
16
- namespace?: string;
17
14
  /** Ordered list of execution phases. */
18
15
  phases: PhaseDefinition[];
19
16
  /** Other Op names that must be complete before this Op can run. */
20
17
  depends?: string[];
21
18
  /** Compensation phases executed on terminal failure (run in reverse order). */
22
19
  onFailure?: PhaseDefinition[];
23
- /** Search attributes to upsert at workflow start. */
24
- searchAttributes?: Record<string, string>;
20
+ /**
21
+ * Discovery keys for this Op — free-form `name: value` pairs a reader
22
+ * filters on. `ConvergeOp` sets `Converge: "true"` and `Env`, `WatchOp`
23
+ * sets `Watch`, and `discoverConvergeOps` (`./operator.ts`) reads both;
24
+ * `chant run list` prints whatever is here.
25
+ *
26
+ * These are the discovery half of what `searchAttributes` used to carry
27
+ * (#2118). The other half — a run's own outcome (`Phase`, `Drift`,
28
+ * `Approver`, `RollbackFailed`) — is not a property of the declaration at
29
+ * all and now lands on the run ledger as a fact
30
+ * (`../lifecycle/run-ledger.ts`), written per run rather than declared once.
31
+ */
32
+ labels?: Record<string, string>;
33
+ /**
34
+ * The cadence this Op runs on, when it has one (#2120). Runtime-neutral
35
+ * data, not a scheduler: the github/gitlab/forgejo lexicons render it as a
36
+ * CI cron ({@link ScheduledOpSpec}), `chant operator` reads it as this Op's
37
+ * tick cadence, a hosting lexicon hands it to its own scheduler, and the
38
+ * local one-shot executor ignores it.
39
+ */
40
+ schedule?: OpSchedule;
41
+ }
42
+ /**
43
+ * An Op's cadence (#2120). The cron is validated at `Op()` construction by
44
+ * the permissive 5-/6-field parser in `./cron.ts`, the same one a lexicon's
45
+ * own post-synth cron check imports.
46
+ */
47
+ export interface OpSchedule {
48
+ /** 5- or 6-field cron expression, read in the running host's local time. */
49
+ cron: string;
50
+ /**
51
+ * What a fire does while the previous run is still going. `"skip"` is the
52
+ * only value — and the default — because that is what a level-triggered
53
+ * tick wants: the next fire re-observes everything anyway, so queueing a
54
+ * backlog buys nothing a single later tick does not.
55
+ */
56
+ overlap?: "skip";
25
57
  }
26
58
  export interface PhaseDefinition {
27
- /** Display name shown in progress output and Temporal UI. */
59
+ /** Display name shown in progress output. */
28
60
  name: string;
29
61
  /** Ordered steps within the phase. */
30
62
  steps: StepDefinition[];
@@ -56,27 +88,47 @@ export interface ActivityStep {
56
88
  */
57
89
  args?: Record<string, unknown>;
58
90
  /**
59
- * Key from TEMPORAL_ACTIVITY_PROFILES controlling timeout + retry.
91
+ * Key from {@link ACTIVITY_PROFILES} controlling timeout + retry.
60
92
  * Default: "fastIdempotent"
61
93
  */
62
- profile?: "fastIdempotent" | "longInfra" | "k8sWait" | "humanGate" | "argoSync" | "policyCheck";
94
+ profile?: ActivityProfileName;
63
95
  /**
64
- * Surface this activity's return value as a workflow search attribute.
96
+ * Surface this activity's return value as a named run outcome.
65
97
  *
66
- * The serializer captures the awaited result into a temporary, then emits
67
- * `upsertSearchAttributes({ <name>: [String(<from-path>)] })` immediately
68
- * after. Useful for filtering runs by outcome (e.g. `Drift: "true"/"false"`
69
- * from a lifecycleDiff activity).
98
+ * The local executor captures it into the step's record and folds it into
99
+ * the run ledger's `outcomes` (`../lifecycle/run-ledger.ts`); a hosting
100
+ * lexicon's serializer may additionally publish it to whatever index that
101
+ * runtime queries by. Useful for reading back a run by outcome (e.g. `Drift:
102
+ * "true"/"false"` from a lifecycleDiff activity).
103
+ *
104
+ * An array publishes several attributes off the same result in one upsert
105
+ * (#2105): one activity can answer more than one question about a run, and
106
+ * `choudoufuLivePlan`'s drift boolean plus its unowned and adoptable counts
107
+ * are three attributes over a single live read that nothing would be gained
108
+ * by splitting into three steps. A single object is the same thing with one
109
+ * entry, and stays the authored form everywhere one attribute is enough.
70
110
  *
71
111
  * `from` is a dot-path into the return value (e.g. `"drifted"` for
72
112
  * `{ drifted: boolean }`); when omitted, the whole return value is
73
- * stringified.
113
+ * recorded.
74
114
  */
75
- outcomeAttribute?: {
76
- name: string;
77
- from?: string;
78
- };
115
+ outcomeAttribute?: OutcomeAttribute | OutcomeAttribute[];
79
116
  }
117
+ /** One named run outcome published off a step's return value. */
118
+ export interface OutcomeAttribute {
119
+ /** The outcome's name, as it appears in the run ledger's `outcomes`. */
120
+ name: string;
121
+ /** Dot-path into the activity's return value; the whole value when omitted. */
122
+ from?: string;
123
+ }
124
+ /**
125
+ * {@link ActivityStep.outcomeAttribute} as a list, whichever form it was
126
+ * authored in. `[]` when the step publishes none, so every consumer can
127
+ * iterate without first asking which of the two shapes it is holding.
128
+ */
129
+ export declare function outcomeAttributesOf(step: {
130
+ outcomeAttribute?: OutcomeAttribute | OutcomeAttribute[];
131
+ }): OutcomeAttribute[];
80
132
  /**
81
133
  * Read-compare-run-write over an effect receipt (#1834, epic #1703). The
82
134
  * runtime reads the live receipt through the receipt store, compares it
@@ -99,18 +151,18 @@ export interface EffectStep {
99
151
  expectation?: string;
100
152
  /**
101
153
  * Steps run when the live receipt does not match, in authored order. A gate
102
- * authored here pauses only when the effect will fire. Effect steps do not
154
+ * authored here is reached only when the effect will fire. Effect steps do not
103
155
  * nest.
104
156
  */
105
157
  steps: Array<ActivityStep | GateStep>;
106
- /** Annotation carried into the generated workflow as a comment. */
158
+ /** Annotation carried into the Op's build output as a comment. */
107
159
  description?: string;
108
160
  }
109
161
  export interface GateStep {
110
162
  kind: "gate";
111
- /** Signal name. The generated workflow waits for this signal before continuing. */
163
+ /** The gate's name — what `chant approve <op> <gate>` resolves. */
112
164
  signalName: string;
113
- /** Temporal duration string. Default: "48h". */
165
+ /** How long a recorded pending gate stays valid, as a duration string. Default: "48h". */
114
166
  timeout?: string;
115
167
  /** Human-readable description of the action required to unblock this gate. */
116
168
  description?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/op/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExD,MAAM,WAAW,QAAQ;IACvB,uGAAuG;IACvG,IAAI,EAAE,MAAM,CAAC;IACb,mFAAmF;IACnF,QAAQ,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,eAAe,EAAE,CAAC;IAC9B,qDAAqD;IACrD,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,eAAe;IAC9B,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,QAAQ,GAAG,UAAU,CAAC;AAElE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,UAAU,CAAC;IACjB;;;;;OAKG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,gFAAgF;IAChF,EAAE,EAAE,MAAM,CAAC;IACX;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B;;;OAGG;IACH,OAAO,CAAC,EAAE,gBAAgB,GAAG,WAAW,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,aAAa,CAAC;IAChG;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACpD;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,QAAQ,CAAC;IACf,4EAA4E;IAC5E,OAAO,EAAE,gBAAgB,CAAC;IAC1B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,KAAK,EAAE,KAAK,CAAC,YAAY,GAAG,QAAQ,CAAC,CAAC;IACtC,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,mFAAmF;IACnF,UAAU,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/op/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,MAAM,WAAW,QAAQ;IACvB,2JAA2J;IAC3J,IAAI,EAAE,MAAM,CAAC;IACb,mFAAmF;IACnF,QAAQ,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,eAAe,EAAE,CAAC;IAC9B;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,UAAU,CAAC;CACvB;AAED;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,QAAQ,GAAG,UAAU,CAAC;AAElE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,UAAU,CAAC;IACjB;;;;;OAKG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,gFAAgF;IAChF,EAAE,EAAE,MAAM,CAAC;IACX;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B;;;OAGG;IACH,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,CAAC;CAC1D;AAED,iEAAiE;AACjE,MAAM,WAAW,gBAAgB;IAC/B,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IAAE,gBAAgB,CAAC,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,CAAA;CAAE,GAAG,gBAAgB,EAAE,CAI1H;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,QAAQ,CAAC;IACf,4EAA4E;IAC5E,OAAO,EAAE,gBAAgB,CAAC;IAC1B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,KAAK,EAAE,KAAK,CAAC,YAAY,GAAG,QAAQ,CAAC,CAAC;IACtC,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAC;IACnB,0FAA0F;IAC1F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB"}
@@ -40,7 +40,7 @@ export interface ChannelKeys {
40
40
  /**
41
41
  * The label-based ownership convention (`app.kubernetes.io/managed-by` +
42
42
  * `chant.intentius.io/{stack,env}`) — the default, shared by every label-based
43
- * lexicon (k8s, gcp, helm, and the Temporal apply activity's `kubectl --prune`
43
+ * lexicon (k8s, gcp, helm, and the `k8sApply` activity's `kubectl --prune`
44
44
  * selector). AWS and Azure tag keys are defined in their own lexicons.
45
45
  */
46
46
  export declare const LABEL_OWNERSHIP_KEYS: ChannelKeys;
@@ -67,6 +67,20 @@ export interface EntityProvenance {
67
67
  * is governed by `tier`, which is what an editor needs to know. Under-reports
68
68
  * (a shape the collector does not follow drops a dependency) and never
69
69
  * over-reports a parameter the expression does not mention.
70
+ * - `composite-parameter` — the fold interpreted the composite's factory body,
71
+ * and the expression for this path reads the named factory parameter paths
72
+ * (chant #2161). Same syntactic-dependency discipline as `build-param`, and
73
+ * for the same reason: a shape the collector does not follow drops a
74
+ * parameter, it never invents one.
75
+ * - `composite-literal` — the fold interpreted the factory body and the
76
+ * expression for this path reads no parameter at all. The composite fixes
77
+ * this field, and no argument at the call site moves it.
78
+ *
79
+ * The coarse `composite` and the two fine kinds are not alternatives. A build
80
+ * records `composite` when it expanded a composite without interpreting its
81
+ * body (the run path, an inadmissible factory), and that is why
82
+ * ./fold-provenance.ts answers `unknown` there rather than falling through to a
83
+ * direct declaration.
70
84
  */
71
85
  export type PathOrigin = {
72
86
  kind: "authored";
@@ -77,6 +91,13 @@ export type PathOrigin = {
77
91
  } | {
78
92
  kind: "build-param";
79
93
  params: string[];
94
+ } | {
95
+ kind: "composite-parameter";
96
+ composite: string;
97
+ parameters: string[];
98
+ } | {
99
+ kind: "composite-literal";
100
+ composite: string;
80
101
  };
81
102
  /**
82
103
  * Merge provenance onto an entity. Non-enumerable so it is invisible to
@@ -1 +1 @@
1
- {"version":3,"file":"provenance.d.ts","sourceRoot":"","sources":["../src/provenance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,MAAM,WAAW,gBAAgB;IAC/B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACpC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GACpB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC1D;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAW9C;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAqB1E;AAED,6DAA6D;AAC7D,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAE1E;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAExF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,SAAS,CAQxF;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,GAAG,SAAS,EACvD,IAAI,EAAE,MAAM,GACX,UAAU,GAAG,SAAS,CAQxB;AAED,wDAAwD;AACxD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAS7D;AAED;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAC;IACb,yFAAyF;IACzF,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IACjC,sCAAsC;IACtC,MAAM,EAAE,KAAK,GAAG,aAAa,GAAG,KAAK,GAAG,SAAS,CAAC;CACnD"}
1
+ {"version":3,"file":"provenance.d.ts","sourceRoot":"","sources":["../src/provenance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,MAAM,WAAW,gBAAgB;IAC/B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACpC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GACpB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC1D;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,qBAAqB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,GACxE;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAWrD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAqB1E;AAED,6DAA6D;AAC7D,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAE1E;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAExF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,SAAS,CAQxF;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,GAAG,SAAS,EACvD,IAAI,EAAE,MAAM,GACX,UAAU,GAAG,SAAS,CAQxB;AAED,wDAAwD;AACxD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAa7D;AAED;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAC;IACb,yFAAyF;IACzF,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IACjC,sCAAsC;IACtC,MAAM,EAAE,KAAK,GAAG,aAAa,GAAG,KAAK,GAAG,SAAS,CAAC;CACnD"}
@@ -1 +1 @@
1
- {"version":3,"file":"serializer-walker.d.ts","sourceRoot":"","sources":["../src/serializer-walker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAM/C,MAAM,WAAW,iBAAiB;IAChC,4DAA4D;IAC5D,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IACzD,mEAAmE;IACnE,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1C,+DAA+D;IAC/D,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,GAAG,OAAO,CAAC;CAChF;AAED;;;GAGG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,OAAO,EACd,WAAW,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,EACpC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAuET"}
1
+ {"version":3,"file":"serializer-walker.d.ts","sourceRoot":"","sources":["../src/serializer-walker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAO/C,MAAM,WAAW,iBAAiB;IAChC,4DAA4D;IAC5D,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IACzD,mEAAmE;IACnE,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1C,+DAA+D;IAC/D,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,GAAG,OAAO,CAAC;CAChF;AAED;;;GAGG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,OAAO,EACd,WAAW,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,EACpC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAyFT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentius/chant",
3
- "version": "0.57.0",
3
+ "version": "0.58.0",
4
4
  "description": "Declarative infrastructure-as-code toolkit — TypeScript on Node.js",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://intentius.io/chant",
@@ -59,6 +59,11 @@
59
59
  "types": "./dist/op/index.d.ts",
60
60
  "default": "./src/op/index.ts"
61
61
  },
62
+ "./op/activities": {
63
+ "development": "./src/op/activities/index.ts",
64
+ "types": "./dist/op/activities/index.d.ts",
65
+ "default": "./src/op/activities/index.ts"
66
+ },
62
67
  "./components": {
63
68
  "development": "./src/components/index.ts",
64
69
  "types": "./dist/components/index.d.ts",
@@ -1,14 +1,14 @@
1
1
  import { describe, test, expect } from "vitest";
2
2
  import { readdirSync } from "fs";
3
3
  import { join } from "path";
4
- import { RULE_CATALOG, RULE_CATEGORY, auditRule, resolveAuditCatalog } from "./catalog";
4
+ import { PRIOR_ART, RULE_CATALOG, RULE_CATEGORY, auditRule, resolveAuditCatalog, canonicalRuleId } from "./catalog";
5
5
  import { loadPlugins } from "../cli/plugins";
6
6
 
7
7
  /**
8
8
  * Every lexicon in the repo, enumerated rather than listed (#1346).
9
9
  *
10
10
  * This was nine hardcoded names. It missed fountain, which contributes a
11
- * catalog, and could not notice fly and temporal, which did not — so their six
11
+ * catalog, and could not notice fly, which did not — so their six
12
12
  * post-synth checks reached `chant audit` with no title, tier, fix kind, or
13
13
  * category, and the guard meant to catch exactly that was blind to them. A
14
14
  * thirteenth lexicon would have been invisible to it on arrival.
@@ -67,6 +67,11 @@ describe("RULE_CATALOG (aggregated: core static + lexicon-contributed, #687)", (
67
67
  .filter((id) => !shipped.has(id))
68
68
  // Core's own cross-cutting ids are not any one lexicon's to ship.
69
69
  .filter((id) => !(id in RULE_CATALOG))
70
+ // A deprecated rule is deliberately kept in the catalog after its check
71
+ // stops shipping (chant #2113). That's the whole point of `deprecated`
72
+ // over deleting the entry, so it's not "stale" the way an orphaned
73
+ // entry with no explanation is.
74
+ .filter((id) => !catalog[id]?.deprecated)
70
75
  .sort();
71
76
  expect(stale).toEqual([]);
72
77
  });
@@ -123,6 +128,33 @@ describe("RULE_CATALOG (aggregated: core static + lexicon-contributed, #687)", (
123
128
  }
124
129
  });
125
130
 
131
+ test("lineage entries key into PRIOR_ART, link over https, and use a known relation", async () => {
132
+ const relations = new Set(["equivalent", "overlaps", "extends"]);
133
+ for (const [id, m] of Object.entries(await aggregate())) {
134
+ for (const l of m.lineage ?? []) {
135
+ expect(l.tool in PRIOR_ART, `${id} credits unregistered tool "${l.tool}"`).toBe(true);
136
+ expect(l.url.startsWith("https://"), `${id} lineage url ${l.url}`).toBe(true);
137
+ expect(relations.has(l.relation), `${id} lineage relation ${l.relation}`).toBe(true);
138
+ }
139
+ }
140
+ });
141
+
142
+ test("lineage is credit, not authority: it never forces a category or tier", () => {
143
+ const m = auditRule("ZZZ001", "report-only", "guidance", "t", "r", {
144
+ lineage: [{ tool: Object.keys(PRIOR_ART)[0] as never, url: "https://example.invalid/x", relation: "overlaps" }],
145
+ });
146
+ expect(m.category).toBe("best-practice");
147
+ expect(m.tier).toBe("report-only");
148
+ expect(m.lineage?.length).toBe(1);
149
+ });
150
+
151
+ test("every registered prior-art tool is credited by at least one rule", async () => {
152
+ const used = new Set<string>();
153
+ for (const m of Object.values(await aggregate())) for (const l of m.lineage ?? []) used.add(l.tool);
154
+ const idle = Object.keys(PRIOR_ART).filter((k) => !used.has(k)).sort();
155
+ expect(idle, "PRIOR_ART entries no rule credits").toEqual([]);
156
+ });
157
+
126
158
  test("flagship security rules carry an authority citation", async () => {
127
159
  const catalog = await aggregate();
128
160
  const flagship = ["GHA017", "GHA021", "GHA029", "GHA033", "GHA034", "GHA036", "GHA037", "WGL016", "WGL029"];
@@ -134,13 +166,34 @@ describe("RULE_CATALOG (aggregated: core static + lexicon-contributed, #687)", (
134
166
  }
135
167
  });
136
168
 
169
+ test("a deprecated id must still resolve (chant #2113): the inverse of the every-check-has-metadata test above", async () => {
170
+ // A retired check ships no runtime PostSynthCheck any more, so it is
171
+ // absent from `realCheckIds()`/`shippedRuleIds()` — that's what makes it
172
+ // "deprecated" rather than merely renamed. The catalog entry, and its
173
+ // resolution, must survive that removal.
174
+ const catalog = {
175
+ ...RULE_CATALOG,
176
+ ZZZ900: auditRule("ZZZ900", "report-only", "guidance", "Retired check", "No longer applicable.", {
177
+ category: "best-practice",
178
+ }),
179
+ };
180
+ catalog.ZZZ900.deprecated = "superseded by ZZZ901";
181
+ expect(catalog.ZZZ900).toBeDefined();
182
+ expect(catalog.ZZZ900.deprecated).toBe("superseded by ZZZ901");
183
+ expect(canonicalRuleId("ZZZ900", catalog)).toBe("ZZZ900");
184
+ });
185
+
137
186
  test("deterministic fixes are limited to the safe mechanical set", async () => {
138
187
  const deterministic = Object.values(await aggregate())
139
188
  .filter((m) => m.fixKind === "deterministic")
140
189
  .map((m) => m.id)
141
190
  .sort();
191
+ // TF016 and TF019 (#2110) are the first report-only rules in the set: both
192
+ // unquote or delete exactly the flagged line, which is as mechanical as
193
+ // pinning an action, and `report-model.ts` renders them as quick wins for
194
+ // that reason. Every entry here needs a case in `proof.ts`'s `proveFix`.
142
195
  expect(deterministic).toEqual(
143
- ["GHA017", "GHA021", "GHA029", "GHA030", "GHA033", "WGL031"].sort(),
196
+ ["GHA017", "GHA021", "GHA029", "GHA030", "GHA033", "TF016", "TF019", "WGL031"].sort(),
144
197
  );
145
198
  });
146
199
  });
@@ -164,6 +217,29 @@ describe("auditRule (lexicon-facing catalog constructor, #687)", () => {
164
217
  });
165
218
  });
166
219
 
220
+ describe("canonicalRuleId (chant #2113, alias resolution)", () => {
221
+ const catalog: Record<string, ReturnType<typeof auditRule>> = {
222
+ NEW001: { ...auditRule("NEW001", "report-only", "guidance", "T", "r"), aliases: ["OLD001", "LEGACY_OLD"] },
223
+ };
224
+
225
+ test("a canonical id passes through unchanged", () => {
226
+ expect(canonicalRuleId("NEW001", catalog)).toBe("NEW001");
227
+ });
228
+
229
+ test("an alias resolves to the canonical id", () => {
230
+ expect(canonicalRuleId("OLD001", catalog)).toBe("NEW001");
231
+ expect(canonicalRuleId("LEGACY_OLD", catalog)).toBe("NEW001");
232
+ });
233
+
234
+ test("an id that is neither a key nor an alias passes through unchanged", () => {
235
+ expect(canonicalRuleId("NOBODY_KNOWS_THIS", catalog)).toBe("NOBODY_KNOWS_THIS");
236
+ });
237
+
238
+ test("defaults to the static core RULE_CATALOG when no catalog is given", () => {
239
+ expect(canonicalRuleId("SEC001")).toBe("SEC001");
240
+ });
241
+ });
242
+
167
243
  describe("resolveAuditCatalog (#687 aggregation seam)", () => {
168
244
  test("with no lexicons, returns a copy of the static core catalog", async () => {
169
245
  const resolved = await resolveAuditCatalog([]);
@@ -17,6 +17,11 @@
17
17
  * test asserts the aggregate stays in sync with the lexicons' post-synth checks.
18
18
  */
19
19
 
20
+ import type { Lineage } from "./prior-art";
21
+ import { applyLineage as attachLineage } from "./prior-art";
22
+ import { coreAuditLineage } from "./lineage";
23
+ export { PRIOR_ART, applyLineage, lineageLabel, type Lineage, type LineageRelation, type PriorArtEntry, type PriorArtTool } from "./prior-art";
24
+
20
25
  export type Tier = "merge-worthy" | "report-only";
21
26
 
22
27
  /** deterministic = safe auto-fix/diff; guidance = report text only (needs judgment). */
@@ -48,14 +53,42 @@ export interface RuleMeta {
48
53
  title: string;
49
54
  /** External backing so a finding isn't just chant's opinion. */
50
55
  authority?: Authority[];
56
+ /**
57
+ * Prior art: the open-source tools whose rules check the same condition
58
+ * (./prior-art.ts). Credit, not authority — never affects tier or category.
59
+ */
60
+ lineage?: Lineage[];
51
61
  /** One-line fix guidance (always present). */
52
62
  remediation: string;
53
63
  /**
54
64
  * False if the check reads the chant model (`ctx.entities`) rather than the
55
65
  * emitted YAML (`ctx.outputs`) — such a check won't fire on audited YAML.
56
- * All current post-synth checks are output-based, so this is true.
66
+ * Most post-synth checks are output-based, but cpln, fly, fountain, k3s
67
+ * and render all ship model-based checks with this false.
57
68
  */
58
69
  yamlBased: boolean;
70
+ /**
71
+ * Retired ids this rule used to ship under (chant #2113). A rule id is
72
+ * public the day it ships. trivy's checks carry `id`, `long_id` and
73
+ * `aliases` for exactly this reason, so a rename or a scheme migration
74
+ * doesn't strand every existing reference to the old id. An alias resolves
75
+ * to this entry wherever a rule id is looked up by a human or a config.
76
+ * `canonicalRuleId()` (below) is the shared resolver; a `lint.rules` key
77
+ * and #2111's HCL suppression both go through it (or will, since #2111
78
+ * lands separately and is not touched by this change).
79
+ */
80
+ aliases?: string[];
81
+ /**
82
+ * Set when this rule is retired: `true`, or a string explaining what
83
+ * replaced it / why it no longer fires. A deprecated rule stays in the
84
+ * catalog rather than being deleted. trivy's `deprecated: true` field lets
85
+ * a ruleset retire a check without breaking every existing suppression or
86
+ * dashboard that still names it, so its id keeps resolving (via `aliases`
87
+ * on whichever rule superseded it, when there is one) and the rules page
88
+ * still lists it, greyed out, instead of the id going dark with no
89
+ * explanation.
90
+ */
91
+ deprecated?: boolean | string;
59
92
  }
60
93
 
61
94
  // ── Authority references ─────────────────────────────────────────────
@@ -147,6 +180,10 @@ export const CWE_HARDCODED_CREDS: Authority = {
147
180
  name: "CWE-798 — Use of Hard-coded Credentials",
148
181
  url: "https://cwe.mitre.org/data/definitions/798.html",
149
182
  };
183
+ export const HASHICORP_STYLE_GITIGNORE: Authority = {
184
+ name: "HashiCorp Terraform style guide — .gitignore",
185
+ url: "https://developer.hashicorp.com/terraform/language/style#gitignore",
186
+ };
150
187
  export const CWE_CLEARTEXT: Authority = {
151
188
  name: "CWE-319 — Cleartext Transmission of Sensitive Information",
152
189
  url: "https://cwe.mitre.org/data/definitions/319.html",
@@ -159,13 +196,14 @@ function meta(
159
196
  title: string,
160
197
  remediation: string,
161
198
  authority?: Authority[],
199
+ lineage?: Lineage[],
162
200
  ): RuleMeta {
163
201
  // An authority citation is the strongest security signal, so it wins. Otherwise
164
202
  // the curated RULE_CATEGORY map (defined below, before RULE_CATALOG runs)
165
203
  // decides correctness vs best-practice vs security-without-authority; the drift
166
204
  // test guarantees every id is mapped, so the fallback is only a type belt.
167
205
  const category: Category = authority && authority.length > 0 ? "security" : RULE_CATEGORY[id] ?? "best-practice";
168
- return { id, tier, fixKind, category, title, remediation, authority, yamlBased: true };
206
+ return { id, tier, fixKind, category, title, remediation, authority, ...(lineage?.length ? { lineage } : {}), yamlBased: true };
169
207
  }
170
208
 
171
209
  const M = "merge-worthy" as const;
@@ -221,6 +259,10 @@ export const RULE_CATEGORY: Record<string, Category> = {
221
259
  NGX005: "security",
222
260
  NGX006: "best-practice",
223
261
  NGX007: "best-practice",
262
+ // TF023 — Terraform state committed to the repository. Core-owned for the
263
+ // same reason SEC/WRG/NGX are: it reads the discovered file list, not a
264
+ // parsed root module. See ./terraform-state.ts.
265
+ TF023: "security",
224
266
  // AGT — agent configuration (`chant audit --agents`). Core-owned like COR/EXT:
225
267
  // these run against the machine's own agent config, not against any one
226
268
  // lexicon's emitted output, so no lexicon ships them.
@@ -282,6 +324,21 @@ export const RULE_CATALOG: Record<string, RuleMeta> = {
282
324
  NGX006: meta("NGX006", R, G, "Server version disclosure", "Add `server_tokens off;` in the http block so nginx stops advertising its exact version in the Server header and error pages."),
283
325
  NGX007: meta("NGX007", R, G, "Access logging disabled at server scope", "Re-enable access_log at http/server scope (silencing a single noisy location is fine) so requests are recorded for incident investigation."),
284
326
 
327
+ // TF023 (#2110) — Terraform state, or the `.terraform/` working directory,
328
+ // committed to the repository. The one TF rule core owns: every other TF id
329
+ // is a post-synth check over a parsed root module (the terraform lexicon's
330
+ // `auditCatalog()`), while this one reads the discovered file list and never
331
+ // runs during `chant build`. Same shape as SEC/WRG/NGX above, and the same
332
+ // reason it lives here: `terraform-state.ts` needs no lexicon installed.
333
+ TF023: meta(
334
+ "TF023",
335
+ M,
336
+ G,
337
+ "Terraform state committed to the repository",
338
+ "Delete the state file (or `.terraform/`) from version control, add it to .gitignore, move the state to a remote backend, and rotate every credential the file held.",
339
+ [HASHICORP_STYLE_GITIGNORE],
340
+ ),
341
+
285
342
  // ── Agent configuration (`chant audit --agents`) ──────────────────
286
343
  AGT001: agentMeta(
287
344
  "AGT001",
@@ -337,6 +394,9 @@ export const RULE_CATALOG: Record<string, RuleMeta> = {
337
394
  ),
338
395
  };
339
396
 
397
+ // Prior art credits for the core static rules (SEC/WRG/NGX/AGT/EXT) — ./lineage.ts.
398
+ attachLineage(RULE_CATALOG, coreAuditLineage);
399
+
340
400
  /**
341
401
  * Build one catalog entry — the lexicon-facing constructor for
342
402
  * `LexiconPlugin.auditCatalog()` (#687), so a lexicon can declare its own rules'
@@ -351,10 +411,20 @@ export function auditRule(
351
411
  fixKind: FixKind,
352
412
  title: string,
353
413
  remediation: string,
354
- opts?: { authority?: Authority[]; category?: Category },
414
+ opts?: { authority?: Authority[]; category?: Category; lineage?: Lineage[] },
355
415
  ): RuleMeta {
356
416
  const category: Category = opts?.authority && opts.authority.length > 0 ? "security" : (opts?.category ?? "best-practice");
357
- return { id, tier, fixKind, category, title, remediation, authority: opts?.authority, yamlBased: true };
417
+ return {
418
+ id,
419
+ tier,
420
+ fixKind,
421
+ category,
422
+ title,
423
+ remediation,
424
+ authority: opts?.authority,
425
+ ...(opts?.lineage?.length ? { lineage: opts.lineage } : {}),
426
+ yamlBased: true,
427
+ };
358
428
  }
359
429
 
360
430
  /**
@@ -374,15 +444,18 @@ export async function resolveAuditCatalog(lexicons: string[]): Promise<Record<st
374
444
  lexicons.includes("forgejo") && !lexicons.includes("github") ? [...lexicons, "github"] : lexicons;
375
445
  if (needed.length === 0) return catalog;
376
446
  // Lazy import so importing this module doesn't pull in the plugin/config graph
377
- // (matches ./core.ts's `load` — see #408).
378
- const { loadPlugins } = await import("../cli/plugins");
379
- let plugins: Array<{ auditCatalog?(): Record<string, RuleMeta> }>;
380
- try {
381
- plugins = await loadPlugins(needed);
382
- } catch {
383
- return catalog; // a lexicon package isn't installed — fall back to the static core catalog.
384
- }
385
- for (const plugin of plugins) {
447
+ // (matches ./core.ts's `load` — see #408). Loaded one at a time (rather than
448
+ // the bulk `loadPlugins`, which aborts on the first failure) so one
449
+ // not-yet-installed lexicon (e.g. terraform, #2085) doesn't drop every other
450
+ // lexicon's contributed catalog back to the static core map.
451
+ const { loadPlugin } = await import("../cli/plugins");
452
+ for (const name of needed) {
453
+ let plugin: { auditCatalog?(): Record<string, RuleMeta> };
454
+ try {
455
+ plugin = await loadPlugin(name);
456
+ } catch {
457
+ continue; // a lexicon package isn't installed, its catalog just doesn't contribute.
458
+ }
386
459
  const contributed = plugin?.auditCatalog?.();
387
460
  if (contributed) Object.assign(catalog, contributed);
388
461
  }
@@ -394,6 +467,31 @@ export function ruleMeta(id: string): RuleMeta | undefined {
394
467
  return RULE_CATALOG[id];
395
468
  }
396
469
 
470
+ /**
471
+ * Resolve a rule id to its canonical form against `catalog` (chant #2113). An
472
+ * id that is itself a key of `catalog` passes through unchanged (this covers
473
+ * the common case without scanning every entry's `aliases`); otherwise every
474
+ * entry's `aliases` is searched for a match, and the id it belongs to is
475
+ * returned. An id neither a key nor anyone's alias passes through unchanged
476
+ * too, since this is a best-effort resolver, not a validator, so an unknown
477
+ * id is a caller's problem, not this function's.
478
+ *
479
+ * Exported so a `lint.rules`/preset key that names an alias resolves to the
480
+ * rule that actually runs (see `resolveConfiguredSeverity`,
481
+ * `../lint/config.ts`), and so #2111's HCL suppression code can key an
482
+ * inline `# chant-ignore <id>` off the same resolution once it lands — that
483
+ * suppression mechanism does not exist yet in this worktree (#2111 is a
484
+ * separate, parallel issue), so this function is exported now for it to call
485
+ * later rather than being wired into it here.
486
+ */
487
+ export function canonicalRuleId(id: string, catalog: Record<string, RuleMeta> = RULE_CATALOG): string {
488
+ if (id in catalog) return id;
489
+ for (const [canonicalId, meta] of Object.entries(catalog)) {
490
+ if (meta.aliases?.includes(id)) return canonicalId;
491
+ }
492
+ return id;
493
+ }
494
+
397
495
  /** Docs path for the audit rules reference (one anchor per rule id). */
398
496
  export const RULES_DOC_PATH = "/chant/lint-rules/audit-rules/";
399
497
 
@@ -208,6 +208,32 @@ describe("auditFiles", () => {
208
208
  expect(findings.map((f) => `${f.file}:${f.entity}`).sort()).toEqual(["a.yaml:one", "b.yaml:two"]);
209
209
  });
210
210
 
211
+ test("parse-to-graph with an async entities parser: auditFiles awaits it into ctx.entities (#2082)", async () => {
212
+ const entityCheck: PostSynthCheck = {
213
+ id: "ENT003",
214
+ description: "reads ctx.entities, not ctx.outputs",
215
+ check: (ctx) =>
216
+ [...ctx.entities.keys()].map((name) => ({ checkId: "ENT003", severity: "warning" as const, message: `saw ${name}`, entity: name })),
217
+ };
218
+ const findings = await auditFiles(
219
+ [
220
+ { path: "a.tf", content: "one", lexicon: "terraform" },
221
+ { path: "b.tf", content: "two", lexicon: "terraform" },
222
+ ],
223
+ {
224
+ checksProvider: async () => [entityCheck],
225
+ // The lexicon's parser is inherently async (a lazy-loaded wasm HCL
226
+ // parser, per #1567's terraform follow-up). The returned Promise
227
+ // must be awaited before the check sees ctx.entities.
228
+ entitiesProvider: async () => async (content) => {
229
+ await Promise.resolve();
230
+ return new Map([[content, { entityType: "T::X" } as never]]);
231
+ },
232
+ },
233
+ );
234
+ expect(findings.map((f) => `${f.file}:${f.entity}`).sort()).toEqual(["a.tf:one", "b.tf:two"]);
235
+ });
236
+
211
237
  test("parse-to-graph merge: the same entity name in two files keeps both — a duplicate check sees the collision cross-file", async () => {
212
238
  const dupCheck: PostSynthCheck = {
213
239
  id: "DUP001",