@intentius/chant 0.124.51 → 0.124.54

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 (593) hide show
  1. package/dist/audit/discover.d.ts.map +1 -1
  2. package/dist/audit/discover.js +3 -1
  3. package/dist/behaviour.d.ts +1 -1
  4. package/dist/behaviour.d.ts.map +1 -1
  5. package/dist/capabilities/templates.d.ts +65 -0
  6. package/dist/capabilities/templates.d.ts.map +1 -0
  7. package/dist/capabilities/templates.js +193 -0
  8. package/dist/capabilities/templates.json +145 -0
  9. package/dist/change-set-graph.d.ts +35 -3
  10. package/dist/change-set-graph.d.ts.map +1 -1
  11. package/dist/change-set-graph.js +60 -9
  12. package/dist/change-set.d.ts +65 -7
  13. package/dist/change-set.d.ts.map +1 -1
  14. package/dist/change-set.js +23 -12
  15. package/dist/ci-identity.d.ts +7 -2
  16. package/dist/ci-identity.d.ts.map +1 -1
  17. package/dist/ci-identity.js +4 -1
  18. package/dist/cli/commands/import-index.d.ts +52 -0
  19. package/dist/cli/commands/import-index.d.ts.map +1 -0
  20. package/dist/cli/commands/import-index.js +226 -0
  21. package/dist/cli/commands/lint.d.ts.map +1 -1
  22. package/dist/cli/commands/lint.js +4 -2
  23. package/dist/cli/handlers/components.d.ts.map +1 -1
  24. package/dist/cli/handlers/components.js +11 -2
  25. package/dist/cli/handlers/fan-out.d.ts.map +1 -1
  26. package/dist/cli/handlers/fan-out.js +16 -3
  27. package/dist/cli/handlers/graph.d.ts.map +1 -1
  28. package/dist/cli/handlers/graph.js +22 -4
  29. package/dist/cli/handlers/index-cloud.d.ts +14 -0
  30. package/dist/cli/handlers/index-cloud.d.ts.map +1 -0
  31. package/dist/cli/handlers/index-cloud.js +22 -0
  32. package/dist/cli/handlers/index-diff.d.ts +18 -0
  33. package/dist/cli/handlers/index-diff.d.ts.map +1 -0
  34. package/dist/cli/handlers/index-diff.js +142 -0
  35. package/dist/cli/handlers/lifecycle-drift.d.ts +25 -0
  36. package/dist/cli/handlers/lifecycle-drift.d.ts.map +1 -0
  37. package/dist/cli/handlers/lifecycle-drift.js +64 -0
  38. package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
  39. package/dist/cli/handlers/lifecycle.js +188 -28
  40. package/dist/cli/handlers/misc.d.ts +9 -0
  41. package/dist/cli/handlers/misc.d.ts.map +1 -1
  42. package/dist/cli/handlers/misc.js +77 -0
  43. package/dist/cli/handlers/pr.d.ts.map +1 -1
  44. package/dist/cli/handlers/pr.js +17 -3
  45. package/dist/cli/handlers/promote.d.ts.map +1 -1
  46. package/dist/cli/handlers/promote.js +89 -15
  47. package/dist/cli/handlers/query.d.ts.map +1 -1
  48. package/dist/cli/handlers/query.js +28 -4
  49. package/dist/cli/handlers/scenario.d.ts.map +1 -1
  50. package/dist/cli/handlers/scenario.js +8 -7
  51. package/dist/cli/handlers/search.d.ts +34 -4
  52. package/dist/cli/handlers/search.d.ts.map +1 -1
  53. package/dist/cli/handlers/search.js +216 -36
  54. package/dist/cli/main.d.ts.map +1 -1
  55. package/dist/cli/main.js +55 -1
  56. package/dist/cli/mcp/lifecycle-tools.d.ts.map +1 -1
  57. package/dist/cli/mcp/lifecycle-tools.js +3 -2
  58. package/dist/cli/mcp/resource-handlers.d.ts.map +1 -1
  59. package/dist/cli/mcp/resource-handlers.js +4 -3
  60. package/dist/cli/mcp/workspace-tools.js +1 -1
  61. package/dist/cli/parse-args.d.ts.map +1 -1
  62. package/dist/cli/parse-args.js +55 -2
  63. package/dist/cli/registry.d.ts +19 -1
  64. package/dist/cli/registry.d.ts.map +1 -1
  65. package/dist/cloud-lister/aws.d.ts +35 -0
  66. package/dist/cloud-lister/aws.d.ts.map +1 -0
  67. package/dist/cloud-lister/aws.js +203 -0
  68. package/dist/cloud-lister/azure.d.ts +34 -0
  69. package/dist/cloud-lister/azure.d.ts.map +1 -0
  70. package/dist/cloud-lister/azure.js +129 -0
  71. package/dist/cloud-lister/common.d.ts +40 -0
  72. package/dist/cloud-lister/common.d.ts.map +1 -0
  73. package/dist/cloud-lister/common.js +83 -0
  74. package/dist/cloud-lister/credentials.d.ts +50 -0
  75. package/dist/cloud-lister/credentials.d.ts.map +1 -0
  76. package/dist/cloud-lister/credentials.js +86 -0
  77. package/dist/cloud-lister/fakes.d.ts +27 -0
  78. package/dist/cloud-lister/fakes.d.ts.map +1 -0
  79. package/dist/cloud-lister/fakes.js +50 -0
  80. package/dist/cloud-lister/gcp.d.ts +42 -0
  81. package/dist/cloud-lister/gcp.d.ts.map +1 -0
  82. package/dist/cloud-lister/gcp.js +143 -0
  83. package/dist/cloud-lister/guard.d.ts +49 -0
  84. package/dist/cloud-lister/guard.d.ts.map +1 -0
  85. package/dist/cloud-lister/guard.js +103 -0
  86. package/dist/cloud-lister/ids.d.ts +23 -0
  87. package/dist/cloud-lister/ids.d.ts.map +1 -0
  88. package/dist/cloud-lister/ids.js +42 -0
  89. package/dist/cloud-lister/index.d.ts +67 -0
  90. package/dist/cloud-lister/index.d.ts.map +1 -0
  91. package/dist/cloud-lister/index.js +102 -0
  92. package/dist/cloud-lister/kubernetes.d.ts +64 -0
  93. package/dist/cloud-lister/kubernetes.d.ts.map +1 -0
  94. package/dist/cloud-lister/kubernetes.js +276 -0
  95. package/dist/cloud-lister/markers.d.ts +31 -0
  96. package/dist/cloud-lister/markers.d.ts.map +1 -0
  97. package/dist/cloud-lister/markers.js +73 -0
  98. package/dist/cloud-lister/mask.d.ts +31 -0
  99. package/dist/cloud-lister/mask.d.ts.map +1 -0
  100. package/dist/cloud-lister/mask.js +74 -0
  101. package/dist/cloud-lister/sigv4.d.ts +29 -0
  102. package/dist/cloud-lister/sigv4.d.ts.map +1 -0
  103. package/dist/cloud-lister/sigv4.js +54 -0
  104. package/dist/cloud-lister/transport.d.ts +55 -0
  105. package/dist/cloud-lister/transport.d.ts.map +1 -0
  106. package/dist/cloud-lister/transport.js +86 -0
  107. package/dist/cloud-lister/types.d.ts +121 -0
  108. package/dist/cloud-lister/types.d.ts.map +1 -0
  109. package/dist/cloud-lister/types.js +24 -0
  110. package/dist/components/capability-plugin-loader.d.ts.map +1 -1
  111. package/dist/components/capability-plugin-loader.js +6 -0
  112. package/dist/components/capability-plugin.d.ts +9 -0
  113. package/dist/components/capability-plugin.d.ts.map +1 -1
  114. package/dist/components/capability.d.ts +224 -0
  115. package/dist/components/capability.d.ts.map +1 -1
  116. package/dist/components/cli-support.d.ts +21 -0
  117. package/dist/components/cli-support.d.ts.map +1 -1
  118. package/dist/components/cli-support.js +58 -14
  119. package/dist/components/covered-round.d.ts +173 -0
  120. package/dist/components/covered-round.d.ts.map +1 -0
  121. package/dist/components/covered-round.js +200 -0
  122. package/dist/components/declared-reads.d.ts +38 -0
  123. package/dist/components/declared-reads.d.ts.map +1 -0
  124. package/dist/components/declared-reads.js +131 -0
  125. package/dist/components/deploy-units.d.ts.map +1 -1
  126. package/dist/components/deploy-units.js +4 -0
  127. package/dist/components/driver.d.ts +42 -1
  128. package/dist/components/driver.d.ts.map +1 -1
  129. package/dist/components/driver.js +74 -3
  130. package/dist/components/fan-out-run.d.ts +23 -1
  131. package/dist/components/fan-out-run.d.ts.map +1 -1
  132. package/dist/components/fan-out-run.js +82 -14
  133. package/dist/components/fan-out-support.d.ts +6 -0
  134. package/dist/components/fan-out-support.d.ts.map +1 -1
  135. package/dist/components/fan-out-support.js +4 -1
  136. package/dist/components/fan-out.d.ts +28 -0
  137. package/dist/components/fan-out.d.ts.map +1 -1
  138. package/dist/components/groups.d.ts +229 -0
  139. package/dist/components/groups.d.ts.map +1 -0
  140. package/dist/components/groups.js +760 -0
  141. package/dist/components/index.d.ts +7 -2
  142. package/dist/components/index.d.ts.map +1 -1
  143. package/dist/components/index.js +5 -0
  144. package/dist/components/plan-shape-conformance.d.ts +48 -0
  145. package/dist/components/plan-shape-conformance.d.ts.map +1 -0
  146. package/dist/components/plan-shape-conformance.js +122 -0
  147. package/dist/components/pr-run.d.ts +62 -7
  148. package/dist/components/pr-run.d.ts.map +1 -1
  149. package/dist/components/pr-run.js +354 -53
  150. package/dist/components/promote-rounds.d.ts +9 -0
  151. package/dist/components/promote-rounds.d.ts.map +1 -1
  152. package/dist/components/promote-rounds.js +23 -2
  153. package/dist/components/promote.d.ts +17 -0
  154. package/dist/components/promote.d.ts.map +1 -1
  155. package/dist/components/promote.js +36 -6
  156. package/dist/components/release-gate.d.ts +23 -1
  157. package/dist/components/release-gate.d.ts.map +1 -1
  158. package/dist/components/release-gate.js +97 -33
  159. package/dist/components/run-groups.d.ts +58 -0
  160. package/dist/components/run-groups.d.ts.map +1 -0
  161. package/dist/components/run-groups.js +78 -0
  162. package/dist/components/starter-plugin.d.ts +1 -0
  163. package/dist/components/starter-plugin.d.ts.map +1 -1
  164. package/dist/components/starter-plugin.js +6 -1
  165. package/dist/components/verbs/index.d.ts +1 -0
  166. package/dist/components/verbs/index.d.ts.map +1 -1
  167. package/dist/components/verbs/index.js +1 -0
  168. package/dist/components/verbs/member-outputs.d.ts +187 -0
  169. package/dist/components/verbs/member-outputs.d.ts.map +1 -0
  170. package/dist/components/verbs/member-outputs.js +218 -0
  171. package/dist/components/wave-plan.d.ts +2 -0
  172. package/dist/components/wave-plan.d.ts.map +1 -1
  173. package/dist/components/wave-plan.js +4 -1
  174. package/dist/config.d.ts +60 -0
  175. package/dist/config.d.ts.map +1 -1
  176. package/dist/config.js +27 -0
  177. package/dist/deep-observation.d.ts +1 -13
  178. package/dist/deep-observation.d.ts.map +1 -1
  179. package/dist/deep-observation.js +5 -22
  180. package/dist/drift-record.d.ts +542 -0
  181. package/dist/drift-record.d.ts.map +1 -0
  182. package/dist/drift-record.js +886 -0
  183. package/dist/engine-facts.d.ts +144 -0
  184. package/dist/engine-facts.d.ts.map +1 -0
  185. package/dist/engine-facts.js +14 -0
  186. package/dist/graph-ir.d.ts +153 -2
  187. package/dist/graph-ir.d.ts.map +1 -1
  188. package/dist/graph-ir.js +224 -6
  189. package/dist/graph-refs.d.ts +145 -0
  190. package/dist/graph-refs.d.ts.map +1 -1
  191. package/dist/graph-refs.js +305 -0
  192. package/dist/graph-schema/fixtures/adopt.json +15 -0
  193. package/dist/graph-schema/fixtures/choudoufu.engine-graph.json +169 -0
  194. package/dist/graph-schema/fixtures/index.json +68 -0
  195. package/dist/graph-schema/fixtures/plunge.engine-graph.json +158 -0
  196. package/dist/graph-schema/fixtures.d.ts +23 -0
  197. package/dist/graph-schema/fixtures.d.ts.map +1 -0
  198. package/dist/graph-schema/fixtures.js +246 -0
  199. package/dist/graph-schema/generate.d.ts +15 -0
  200. package/dist/graph-schema/generate.d.ts.map +1 -0
  201. package/dist/graph-schema/generate.js +267 -0
  202. package/dist/graph-schema/graph.schema.json +1387 -0
  203. package/dist/health.schema.json +2 -1
  204. package/dist/identity.d.ts.map +1 -1
  205. package/dist/identity.js +2 -0
  206. package/dist/index.d.ts +1 -0
  207. package/dist/index.d.ts.map +1 -1
  208. package/dist/index.js +2 -0
  209. package/dist/instance-nodes.d.ts +159 -0
  210. package/dist/instance-nodes.d.ts.map +1 -0
  211. package/dist/instance-nodes.js +231 -0
  212. package/dist/lexicon.d.ts +72 -0
  213. package/dist/lexicon.d.ts.map +1 -1
  214. package/dist/lifecycle/adoption-file.d.ts +56 -0
  215. package/dist/lifecycle/adoption-file.d.ts.map +1 -0
  216. package/dist/lifecycle/adoption-file.js +123 -0
  217. package/dist/lifecycle/cloud-index.d.ts +186 -0
  218. package/dist/lifecycle/cloud-index.d.ts.map +1 -0
  219. package/dist/lifecycle/cloud-index.js +618 -0
  220. package/dist/lifecycle/derive-edges.d.ts +59 -0
  221. package/dist/lifecycle/derive-edges.d.ts.map +1 -0
  222. package/dist/lifecycle/derive-edges.js +126 -0
  223. package/dist/lifecycle/git.d.ts +10 -9
  224. package/dist/lifecycle/git.d.ts.map +1 -1
  225. package/dist/lifecycle/git.js +7 -1
  226. package/dist/lifecycle/identity-match.d.ts +133 -0
  227. package/dist/lifecycle/identity-match.d.ts.map +1 -0
  228. package/dist/lifecycle/identity-match.js +147 -0
  229. package/dist/lifecycle/index-diff.d.ts +224 -0
  230. package/dist/lifecycle/index-diff.d.ts.map +1 -0
  231. package/dist/lifecycle/index-diff.js +327 -0
  232. package/dist/lifecycle/index-document.d.ts +130 -0
  233. package/dist/lifecycle/index-document.d.ts.map +1 -0
  234. package/dist/lifecycle/index-document.js +189 -0
  235. package/dist/lifecycle/index-drift.d.ts +121 -0
  236. package/dist/lifecycle/index-drift.d.ts.map +1 -0
  237. package/dist/lifecycle/index-drift.js +178 -0
  238. package/dist/lifecycle/index-import.d.ts +168 -0
  239. package/dist/lifecycle/index-import.d.ts.map +1 -0
  240. package/dist/lifecycle/index-import.js +515 -0
  241. package/dist/lifecycle/index-join.d.ts +129 -0
  242. package/dist/lifecycle/index-join.d.ts.map +1 -0
  243. package/dist/lifecycle/index-join.js +248 -0
  244. package/dist/lifecycle/index.d.ts +4 -0
  245. package/dist/lifecycle/index.d.ts.map +1 -1
  246. package/dist/lifecycle/index.js +4 -0
  247. package/dist/lifecycle/observation-baseline.d.ts +61 -21
  248. package/dist/lifecycle/observation-baseline.d.ts.map +1 -1
  249. package/dist/lifecycle/observation-baseline.js +144 -19
  250. package/dist/lifecycle/observe.d.ts.map +1 -1
  251. package/dist/lifecycle/observe.js +6 -1
  252. package/dist/lifecycle/query.d.ts +45 -4
  253. package/dist/lifecycle/query.d.ts.map +1 -1
  254. package/dist/lifecycle/query.js +89 -7
  255. package/dist/lifecycle/replay.d.ts +10 -3
  256. package/dist/lifecycle/replay.d.ts.map +1 -1
  257. package/dist/lifecycle/replay.js +10 -6
  258. package/dist/lifecycle/scenario.d.ts +4 -3
  259. package/dist/lifecycle/scenario.d.ts.map +1 -1
  260. package/dist/lifecycle/snapshot-store-fake.d.ts +9 -0
  261. package/dist/lifecycle/snapshot-store-fake.d.ts.map +1 -0
  262. package/dist/lifecycle/snapshot-store-fake.js +21 -0
  263. package/dist/lifecycle/snapshot-store-s3.d.ts +102 -0
  264. package/dist/lifecycle/snapshot-store-s3.d.ts.map +1 -0
  265. package/dist/lifecycle/snapshot-store-s3.js +254 -0
  266. package/dist/lifecycle/snapshot-store.d.ts +170 -0
  267. package/dist/lifecycle/snapshot-store.d.ts.map +1 -0
  268. package/dist/lifecycle/snapshot-store.js +832 -0
  269. package/dist/lifecycle/snapshot.d.ts +11 -0
  270. package/dist/lifecycle/snapshot.d.ts.map +1 -1
  271. package/dist/lifecycle/snapshot.js +18 -5
  272. package/dist/lifecycle/type-listing.d.ts +148 -0
  273. package/dist/lifecycle/type-listing.d.ts.map +1 -0
  274. package/dist/lifecycle/type-listing.js +166 -0
  275. package/dist/lint/component-checks.d.ts +15 -1
  276. package/dist/lint/component-checks.d.ts.map +1 -1
  277. package/dist/lint/component-checks.js +1 -0
  278. package/dist/lint/presets/relaxed.json +2 -1
  279. package/dist/lint/presets/strict.json +2 -1
  280. package/dist/lint/rules/__fixtures__/comp/comp008/fail/dns.component.d.ts +4 -0
  281. package/dist/lint/rules/__fixtures__/comp/comp008/fail/dns.component.d.ts.map +1 -0
  282. package/dist/lint/rules/__fixtures__/comp/comp008/fail/dns.component.js +13 -0
  283. package/dist/lint/rules/__fixtures__/comp/comp008/pass/dns.component.d.ts +4 -0
  284. package/dist/lint/rules/__fixtures__/comp/comp008/pass/dns.component.d.ts.map +1 -0
  285. package/dist/lint/rules/__fixtures__/comp/comp008/pass/dns.component.js +8 -0
  286. package/dist/lint/rules/comp/comp008-applies-signal-only-root.d.ts +33 -0
  287. package/dist/lint/rules/comp/comp008-applies-signal-only-root.d.ts.map +1 -0
  288. package/dist/lint/rules/comp/comp008-applies-signal-only-root.js +123 -0
  289. package/dist/lint/rules/comp/index.d.ts +2 -1
  290. package/dist/lint/rules/comp/index.d.ts.map +1 -1
  291. package/dist/lint/rules/comp/index.js +4 -1
  292. package/dist/observation.d.ts +19 -2
  293. package/dist/observation.d.ts.map +1 -1
  294. package/dist/observation.js +18 -1
  295. package/dist/op/activities/activity-contracts.d.ts +1 -1
  296. package/dist/op/activities/activity-contracts.js +1 -1
  297. package/dist/op/activities/change-set.d.ts +6 -4
  298. package/dist/op/activities/change-set.d.ts.map +1 -1
  299. package/dist/op/activities/change-set.js +4 -2
  300. package/dist/op/activity-failure.d.ts +27 -0
  301. package/dist/op/activity-failure.d.ts.map +1 -1
  302. package/dist/op/activity-failure.js +31 -0
  303. package/dist/op/index.d.ts +2 -1
  304. package/dist/op/index.d.ts.map +1 -1
  305. package/dist/op/index.js +1 -1
  306. package/dist/op/local-executor.d.ts +5 -1
  307. package/dist/op/local-executor.d.ts.map +1 -1
  308. package/dist/op/local-executor.js +22 -8
  309. package/dist/pr-loop.d.ts +92 -3
  310. package/dist/pr-loop.d.ts.map +1 -1
  311. package/dist/pr-loop.js +62 -3
  312. package/dist/pulumi-urn.d.ts +101 -0
  313. package/dist/pulumi-urn.d.ts.map +1 -0
  314. package/dist/pulumi-urn.js +131 -0
  315. package/dist/release-floors.d.ts +23 -0
  316. package/dist/release-floors.d.ts.map +1 -0
  317. package/dist/release-floors.js +22 -0
  318. package/dist/sensitive-key.d.ts +23 -0
  319. package/dist/sensitive-key.d.ts.map +1 -0
  320. package/dist/sensitive-key.js +31 -0
  321. package/dist/wave-runtime.mjs +234 -234
  322. package/dist/workspace/adoption-report.d.ts +53 -0
  323. package/dist/workspace/adoption-report.d.ts.map +1 -0
  324. package/dist/workspace/adoption-report.js +76 -0
  325. package/dist/workspace/capabilities-contract.d.ts +7 -0
  326. package/dist/workspace/capabilities-contract.d.ts.map +1 -1
  327. package/dist/workspace/capabilities-contract.js +2 -1
  328. package/dist/workspace/capabilities.schema.json +98 -0
  329. package/dist/workspace/change-set.schema.json +42 -3
  330. package/dist/workspace/ci-cloud-identity.d.ts +13 -1
  331. package/dist/workspace/ci-cloud-identity.d.ts.map +1 -1
  332. package/dist/workspace/ci-cloud-identity.js +30 -1
  333. package/dist/workspace/compose-graph.d.ts +10 -1
  334. package/dist/workspace/compose-graph.d.ts.map +1 -1
  335. package/dist/workspace/compose-graph.js +6 -1
  336. package/dist/workspace/conformance/index.d.ts +1 -1
  337. package/dist/workspace/conformance/index.d.ts.map +1 -1
  338. package/dist/workspace/conformance/index.js +6 -1
  339. package/dist/workspace/drift-cli.d.ts +81 -0
  340. package/dist/workspace/drift-cli.d.ts.map +1 -0
  341. package/dist/workspace/drift-cli.js +317 -0
  342. package/dist/workspace/drift.schema.json +672 -0
  343. package/dist/workspace/graph-cli.d.ts +2 -0
  344. package/dist/workspace/graph-cli.d.ts.map +1 -1
  345. package/dist/workspace/graph-cli.js +3 -0
  346. package/dist/workspace/graph.schema.json +72 -0
  347. package/dist/workspace/init.d.ts +5 -1
  348. package/dist/workspace/init.d.ts.map +1 -1
  349. package/dist/workspace/init.js +55 -9
  350. package/dist/workspace/ledger.schema.json +1 -1
  351. package/dist/workspace/nested-graph.d.ts.map +1 -1
  352. package/dist/workspace/nested-graph.js +2 -0
  353. package/dist/workspace/pr-report.schema.json +76 -3
  354. package/dist/workspace/promote-waves.d.ts +112 -0
  355. package/dist/workspace/promote-waves.d.ts.map +1 -0
  356. package/dist/workspace/promote-waves.js +290 -0
  357. package/dist/workspace/promote.d.ts +84 -2
  358. package/dist/workspace/promote.d.ts.map +1 -1
  359. package/dist/workspace/promote.js +347 -61
  360. package/dist/workspace/reason-codes.d.ts +12 -0
  361. package/dist/workspace/reason-codes.d.ts.map +1 -1
  362. package/dist/workspace/reason-codes.js +14 -0
  363. package/dist/workspace/search-contract.d.ts +3 -3
  364. package/dist/workspace/search-contract.d.ts.map +1 -1
  365. package/dist/workspace/search-contract.js +2 -0
  366. package/dist/workspace/search.schema.json +103 -5
  367. package/package.json +14 -1
  368. package/src/__fixtures__/drift-record/README.md +58 -0
  369. package/src/__fixtures__/drift-record/choudoufu-cone.ndjson +4 -0
  370. package/src/__fixtures__/drift-record/choudoufu-resource.ndjson +3 -0
  371. package/src/__fixtures__/drift-record/component-status-ledger.json +65 -0
  372. package/src/__fixtures__/drift-record/component-status.json +91 -0
  373. package/src/__fixtures__/drift-record/deep-diff.json +259 -0
  374. package/src/__fixtures__/drift-record/lifecycle-diff-live.json +825 -0
  375. package/src/__fixtures__/drift-record/live-diff.json +125 -0
  376. package/src/audit/discover.e2e.test.ts +14 -0
  377. package/src/audit/discover.ts +3 -1
  378. package/src/behaviour.ts +1 -1
  379. package/src/capabilities/templates.json +145 -0
  380. package/src/capabilities/templates.test.ts +212 -0
  381. package/src/capabilities/templates.ts +204 -0
  382. package/src/change-set-bundle.test.ts +83 -0
  383. package/src/change-set-graph.ts +80 -9
  384. package/src/change-set.test.ts +24 -0
  385. package/src/change-set.ts +77 -14
  386. package/src/ci-identity-targets.test.ts +23 -0
  387. package/src/ci-identity.ts +10 -4
  388. package/src/cli/commands/import-index.test.ts +117 -0
  389. package/src/cli/commands/import-index.ts +265 -0
  390. package/src/cli/commands/lint.ts +4 -2
  391. package/src/cli/handlers/components.test.ts +9 -0
  392. package/src/cli/handlers/components.ts +12 -2
  393. package/src/cli/handlers/fan-out.ts +17 -3
  394. package/src/cli/handlers/graph.test.ts +42 -0
  395. package/src/cli/handlers/graph.ts +26 -4
  396. package/src/cli/handlers/index-cloud.ts +32 -0
  397. package/src/cli/handlers/index-diff.test.ts +68 -0
  398. package/src/cli/handlers/index-diff.ts +146 -0
  399. package/src/cli/handlers/ledger-root-member.test.ts +161 -0
  400. package/src/cli/handlers/lifecycle-drift.ts +68 -0
  401. package/src/cli/handlers/lifecycle.test.ts +33 -11
  402. package/src/cli/handlers/lifecycle.ts +205 -30
  403. package/src/cli/handlers/misc.ts +73 -0
  404. package/src/cli/handlers/pr-waves-blocked.test.ts +37 -2
  405. package/src/cli/handlers/pr.ts +16 -3
  406. package/src/cli/handlers/promote.test.ts +64 -0
  407. package/src/cli/handlers/promote.ts +81 -6
  408. package/src/cli/handlers/query.ts +27 -4
  409. package/src/cli/handlers/run-declared-reads-cli.test.ts +187 -0
  410. package/src/cli/handlers/run-groups-cli.test.ts +229 -0
  411. package/src/cli/handlers/scenario.test.ts +13 -0
  412. package/src/cli/handlers/scenario.ts +8 -7
  413. package/src/cli/handlers/search-index.test.ts +255 -0
  414. package/src/cli/handlers/search-json.test.ts +1 -1
  415. package/src/cli/handlers/search-ownership.test.ts +194 -0
  416. package/src/cli/handlers/search.ts +271 -38
  417. package/src/cli/main.test.ts +7 -0
  418. package/src/cli/main.ts +56 -1
  419. package/src/cli/mcp/lifecycle-tools.ts +3 -2
  420. package/src/cli/mcp/resource-handlers.ts +4 -3
  421. package/src/cli/mcp/workspace-tools.ts +1 -1
  422. package/src/cli/parse-args.ts +40 -2
  423. package/src/cli/registry.ts +19 -1
  424. package/src/cloud-lister/aws.test.ts +202 -0
  425. package/src/cloud-lister/aws.ts +226 -0
  426. package/src/cloud-lister/azure.test.ts +132 -0
  427. package/src/cloud-lister/azure.ts +142 -0
  428. package/src/cloud-lister/common.ts +115 -0
  429. package/src/cloud-lister/credentials.ts +110 -0
  430. package/src/cloud-lister/fakes.ts +66 -0
  431. package/src/cloud-lister/gcp.test.ts +121 -0
  432. package/src/cloud-lister/gcp.ts +159 -0
  433. package/src/cloud-lister/guard.test.ts +198 -0
  434. package/src/cloud-lister/guard.ts +111 -0
  435. package/src/cloud-lister/ids.ts +54 -0
  436. package/src/cloud-lister/index.ts +134 -0
  437. package/src/cloud-lister/kubernetes.test.ts +160 -0
  438. package/src/cloud-lister/kubernetes.ts +284 -0
  439. package/src/cloud-lister/markers.ts +74 -0
  440. package/src/cloud-lister/mask.ts +77 -0
  441. package/src/cloud-lister/shape.test.ts +81 -0
  442. package/src/cloud-lister/sigv4.ts +70 -0
  443. package/src/cloud-lister/transport.ts +118 -0
  444. package/src/cloud-lister/types.ts +135 -0
  445. package/src/components/capability-plugin-loader.ts +4 -0
  446. package/src/components/capability-plugin.ts +10 -0
  447. package/src/components/capability.ts +238 -0
  448. package/src/components/cli-support.ts +70 -14
  449. package/src/components/covered-round.test.ts +166 -0
  450. package/src/components/covered-round.ts +293 -0
  451. package/src/components/declared-reads.test.ts +103 -0
  452. package/src/components/declared-reads.ts +134 -0
  453. package/src/components/deploy-units.ts +4 -0
  454. package/src/components/driver.ts +101 -4
  455. package/src/components/fan-out-run.ts +95 -15
  456. package/src/components/fan-out-support.ts +10 -1
  457. package/src/components/fan-out.ts +30 -0
  458. package/src/components/groups.test.ts +320 -0
  459. package/src/components/groups.ts +880 -0
  460. package/src/components/index.ts +59 -0
  461. package/src/components/plan-shape-conformance.ts +130 -0
  462. package/src/components/pr-env-run-bundle.test.ts +2 -0
  463. package/src/components/pr-run.test.ts +728 -4
  464. package/src/components/pr-run.ts +395 -55
  465. package/src/components/promote-rounds.ts +25 -2
  466. package/src/components/promote.ts +55 -5
  467. package/src/components/registry.test.ts +1 -1
  468. package/src/components/release-gate.ts +115 -30
  469. package/src/components/release-groups.test.ts +362 -0
  470. package/src/components/run-groups.ts +113 -0
  471. package/src/components/starter-plugin.ts +6 -0
  472. package/src/components/verbs/index.ts +1 -0
  473. package/src/components/verbs/member-outputs.test.ts +205 -0
  474. package/src/components/verbs/member-outputs.ts +308 -0
  475. package/src/components/wave-plan.ts +5 -2
  476. package/src/config.ts +44 -0
  477. package/src/deep-observation.ts +5 -23
  478. package/src/drift-record.test.ts +596 -0
  479. package/src/drift-record.ts +1206 -0
  480. package/src/engine-facts.guard.test.ts +111 -0
  481. package/src/engine-facts.test.ts +178 -0
  482. package/src/engine-facts.ts +154 -0
  483. package/src/gated-waves-bundle.test.ts +2 -0
  484. package/src/graph-ir-live.test.ts +92 -0
  485. package/src/graph-ir.ts +317 -7
  486. package/src/graph-refs.ts +416 -0
  487. package/src/graph-schema/fixtures/adopt.json +15 -0
  488. package/src/graph-schema/fixtures/choudoufu.engine-graph.json +169 -0
  489. package/src/graph-schema/fixtures/index.json +68 -0
  490. package/src/graph-schema/fixtures/plunge.engine-graph.json +158 -0
  491. package/src/graph-schema/fixtures.ts +267 -0
  492. package/src/graph-schema/generate.ts +263 -0
  493. package/src/graph-schema/graph-schema.test.ts +153 -0
  494. package/src/graph-schema/graph.schema.json +1387 -0
  495. package/src/health.schema.json +2 -1
  496. package/src/identity.ts +2 -0
  497. package/src/index.ts +2 -0
  498. package/src/instance-nodes.ts +288 -0
  499. package/src/lexicon.ts +76 -0
  500. package/src/lifecycle/__fixtures__/index-diff/20261026T120000Z-aaaaaaaaaaaa.json +149 -0
  501. package/src/lifecycle/__fixtures__/index-diff/20261026T130000Z-bbbbbbbbbbbb.json +127 -0
  502. package/src/lifecycle/adoption-file.test.ts +100 -0
  503. package/src/lifecycle/adoption-file.ts +154 -0
  504. package/src/lifecycle/cloud-index.test.ts +517 -0
  505. package/src/lifecycle/cloud-index.ts +736 -0
  506. package/src/lifecycle/derive-edges.test.ts +193 -0
  507. package/src/lifecycle/derive-edges.ts +182 -0
  508. package/src/lifecycle/git.ts +10 -4
  509. package/src/lifecycle/identity-match.test.ts +308 -0
  510. package/src/lifecycle/identity-match.ts +257 -0
  511. package/src/lifecycle/index-diff.test.ts +198 -0
  512. package/src/lifecycle/index-diff.ts +476 -0
  513. package/src/lifecycle/index-document.test.ts +64 -0
  514. package/src/lifecycle/index-document.ts +299 -0
  515. package/src/lifecycle/index-drift.test.ts +191 -0
  516. package/src/lifecycle/index-drift.ts +304 -0
  517. package/src/lifecycle/index-import.test.ts +255 -0
  518. package/src/lifecycle/index-import.ts +634 -0
  519. package/src/lifecycle/index-join.test.ts +250 -0
  520. package/src/lifecycle/index-join.ts +304 -0
  521. package/src/lifecycle/index-store-load-bearing.test.ts +187 -0
  522. package/src/lifecycle/index.ts +4 -0
  523. package/src/lifecycle/member-ledger.test.ts +25 -7
  524. package/src/lifecycle/observation-baseline.test.ts +72 -1
  525. package/src/lifecycle/observation-baseline.ts +190 -27
  526. package/src/lifecycle/observe.ts +6 -1
  527. package/src/lifecycle/query.test.ts +69 -1
  528. package/src/lifecycle/query.ts +103 -10
  529. package/src/lifecycle/replay.test.ts +9 -5
  530. package/src/lifecycle/replay.ts +9 -5
  531. package/src/lifecycle/scenario.ts +4 -3
  532. package/src/lifecycle/snapshot-store-fake.ts +29 -0
  533. package/src/lifecycle/snapshot-store-s3.ts +316 -0
  534. package/src/lifecycle/snapshot-store.test.ts +385 -0
  535. package/src/lifecycle/snapshot-store.ts +981 -0
  536. package/src/lifecycle/snapshot.test.ts +13 -0
  537. package/src/lifecycle/snapshot.ts +23 -6
  538. package/src/lifecycle/type-listing.test.ts +166 -0
  539. package/src/lifecycle/type-listing.ts +309 -0
  540. package/src/lint/component-checks.ts +17 -1
  541. package/src/lint/config.test.ts +3 -0
  542. package/src/lint/presets/relaxed.json +2 -1
  543. package/src/lint/presets/strict.json +2 -1
  544. package/src/lint/rules/__fixtures__/comp/comp008/fail/dns.component.ts +15 -0
  545. package/src/lint/rules/__fixtures__/comp/comp008/pass/dns.component.ts +10 -0
  546. package/src/lint/rules/comp/comp.test.ts +2 -1
  547. package/src/lint/rules/comp/comp008-applies-signal-only-root.ts +121 -0
  548. package/src/lint/rules/comp/comp008.test.ts +77 -0
  549. package/src/lint/rules/comp/index.ts +4 -1
  550. package/src/observation-edges.test.ts +33 -0
  551. package/src/observation.ts +36 -1
  552. package/src/op/activities/activity-contracts.ts +1 -1
  553. package/src/op/activities/change-set.ts +8 -5
  554. package/src/op/activity-failure.ts +36 -0
  555. package/src/op/index.ts +2 -1
  556. package/src/op/local-executor.test.ts +80 -0
  557. package/src/op/local-executor.ts +27 -9
  558. package/src/pr-loop-bundle.test.ts +5 -2
  559. package/src/pr-loop.test.ts +57 -1
  560. package/src/pr-loop.ts +154 -6
  561. package/src/pulumi-urn.ts +151 -0
  562. package/src/release-floors.ts +22 -0
  563. package/src/sensitive-key.ts +34 -0
  564. package/src/workspace/adoption-report.test.ts +61 -0
  565. package/src/workspace/adoption-report.ts +103 -0
  566. package/src/workspace/capabilities-contract.test.ts +4 -0
  567. package/src/workspace/capabilities-contract.ts +9 -1
  568. package/src/workspace/capabilities.schema.json +98 -0
  569. package/src/workspace/change-set.schema.json +42 -3
  570. package/src/workspace/ci-cloud-identity.ts +31 -1
  571. package/src/workspace/compose-graph.test.ts +12 -0
  572. package/src/workspace/compose-graph.ts +12 -1
  573. package/src/workspace/conformance/conformance.e2e.test.ts +2 -1
  574. package/src/workspace/conformance/index.ts +6 -1
  575. package/src/workspace/drift-cli.test.ts +65 -0
  576. package/src/workspace/drift-cli.ts +365 -0
  577. package/src/workspace/drift.schema.json +672 -0
  578. package/src/workspace/graph-cli.ts +5 -0
  579. package/src/workspace/graph.schema.json +72 -0
  580. package/src/workspace/init.test.ts +38 -1
  581. package/src/workspace/init.ts +50 -8
  582. package/src/workspace/intent-gaps.test.ts +18 -2
  583. package/src/workspace/ledger.schema.json +1 -1
  584. package/src/workspace/nested-graph.ts +1 -0
  585. package/src/workspace/pr-report.schema.json +76 -3
  586. package/src/workspace/promote-waves.test.ts +296 -0
  587. package/src/workspace/promote-waves.ts +340 -0
  588. package/src/workspace/promote.test.ts +158 -4
  589. package/src/workspace/promote.ts +398 -57
  590. package/src/workspace/reason-codes.test.ts +4 -1
  591. package/src/workspace/reason-codes.ts +14 -0
  592. package/src/workspace/search-contract.ts +2 -0
  593. package/src/workspace/search.schema.json +103 -5
@@ -0,0 +1,142 @@
1
+ /**
2
+ * `chant index diff <a> [<b>] [--store <spec>] [--json]` (#4533): what
3
+ * changed between two versions of one index scope.
4
+ *
5
+ * `<a>` is `<scopeKey>/<version>`, or `<scopeKey>` alone. `<b>` is
6
+ * `<scopeKey>/<version>`, or a version name in `<a>`'s scope. With no `<b>`,
7
+ * the version before `<a>` is diffed against `<a>`, and a scope alone diffs
8
+ * its last two versions.
9
+ *
10
+ * Versions are read through #4519's store API, from the store `chant index`
11
+ * writes to (#4532's {@link planIndexStore}: `--store <spec>`, else the
12
+ * project's store, else the per-user one), so a git-ref, local or s3 store
13
+ * diffs the same way. Nothing is built, no lexicon is loaded and no cloud is
14
+ * queried. The computation is ../../lifecycle/index-diff.ts.
15
+ */
16
+ import { homedir } from "node:os";
17
+ import { chantUserStoreDir, IndexUsageError, planIndexStore } from "../../lifecycle/cloud-index.js";
18
+ import { diffIndexVersionRefs, IndexScopeMismatch, NotAnIndexVersion, parseIndexVersionRef } from "../../lifecycle/index-diff.js";
19
+ import { createSnapshotStore, resolveSnapshotStore, snapshotStoreConfig } from "../../lifecycle/snapshot-store.js";
20
+ export const INDEX_DIFF_USAGE = `chant index diff <a> [<b>] [--store <spec>] [--json]
21
+
22
+ What changed between two versions of one index scope: nodes added and
23
+ removed, properties changed, edges added and removed. A node is removed only
24
+ where the later read listed its type and location; elsewhere it is not
25
+ observed. Two versions of different scopes are refused.
26
+
27
+ <a> <scopeKey>/<version>, or <scopeKey> for its latest version
28
+ <b> <scopeKey>/<version>, or a version name in <a>'s scope.
29
+ Absent: the version before <a> against <a> (a scope alone:
30
+ its last two versions)
31
+ --store <spec> the store to read, as chant index takes it (local,
32
+ local:<dir>, git-ref, git-ref:<ref>, s3,
33
+ s3://<bucket>[/<prefix>]). Default: the project's store,
34
+ else chant's per-user store
35
+ --json the diff as JSON
36
+ `;
37
+ async function openReadStore(plan, cwd) {
38
+ switch (plan.kind) {
39
+ case "user":
40
+ return createSnapshotStore({ store: "local", dir: plan.dir }, { cwd });
41
+ case "project":
42
+ return resolveSnapshotStore({ cwd: plan.projectDir });
43
+ case "spec":
44
+ return createSnapshotStore(snapshotStoreConfig(plan.configured, plan.env), { cwd, env: plan.env });
45
+ }
46
+ }
47
+ const show = (v) => (v === undefined ? "(absent)" : JSON.stringify(v));
48
+ /** The diff as text, one line per change. */
49
+ export function renderIndexDiff(d) {
50
+ const lines = [];
51
+ lines.push(`Index diff: ${d.scopeKey}`);
52
+ lines.push(` from ${d.from.version ?? d.from.digest.slice(0, 12)} (observed ${d.from.observedAt})`);
53
+ lines.push(` to ${d.to.version ?? d.to.digest.slice(0, 12)} (observed ${d.to.observedAt})`);
54
+ if (d.unchanged) {
55
+ lines.push("", "Same digest: nothing changed.");
56
+ return `${lines.join("\n")}\n`;
57
+ }
58
+ const c = d.counts;
59
+ lines.push("", `${c.added} added, ${c.removed} removed, ${c.changed} changed (${c.properties} properties), ${c.notObserved} not observed; edges ${c.edgesAdded} added, ${c.edgesRemoved} removed, ${c.edgesNotObserved} not observed`);
60
+ for (const n of d.nodes.added)
61
+ lines.push(` + ${n.key}`);
62
+ for (const n of d.nodes.removed)
63
+ lines.push(` - ${n.key}`);
64
+ for (const n of d.nodes.changed) {
65
+ lines.push(` ~ ${n.key}`);
66
+ for (const p of n.properties)
67
+ lines.push(` ${p.path}: ${show(p.before)} -> ${show(p.after)}`);
68
+ }
69
+ for (const n of d.nodes.notObserved)
70
+ lines.push(` ? ${n.key} (not observed in the ${n.side} read: ${n.verdict}${n.detail ? `, ${n.detail}` : ""})`);
71
+ for (const e of d.edges.added)
72
+ lines.push(` + edge ${e.from} -> ${e.to}${e.viaAttr ? ` via ${e.viaAttr}` : ""}`);
73
+ for (const e of d.edges.removed)
74
+ lines.push(` - edge ${e.from} -> ${e.to}${e.viaAttr ? ` via ${e.viaAttr}` : ""}`);
75
+ for (const e of d.edges.notObserved)
76
+ lines.push(` ? edge ${e.from} -> ${e.to} (${e.unobservedEnd} not observed in the ${e.side} read: ${e.verdict})`);
77
+ for (const v of d.coverage)
78
+ lines.push(` coverage ${v.listedType} @ ${v.location}: ${v.before ?? "(none)"} -> ${v.after ?? "(none)"}`);
79
+ return `${lines.join("\n")}\n`;
80
+ }
81
+ /** `chant index diff`'s argv (the words after `diff`). Exit 0 on a diff, 1 on a refusal, 2 on a usage error. */
82
+ export async function runIndexDiff(argv, o = {}) {
83
+ const out = o.stdout ?? ((s) => void process.stdout.write(s));
84
+ const err = o.stderr ?? ((s) => void process.stderr.write(s));
85
+ const cwd = o.cwd ?? process.cwd();
86
+ const env = o.env ?? process.env;
87
+ if (argv.includes("-h") || argv.includes("--help")) {
88
+ out(INDEX_DIFF_USAGE);
89
+ return 0;
90
+ }
91
+ const refs = [];
92
+ let store;
93
+ let json = false;
94
+ for (let i = 0; i < argv.length; i++) {
95
+ const a = argv[i];
96
+ if (a === "--json")
97
+ json = true;
98
+ else if (a === "--store") {
99
+ store = argv[++i];
100
+ if (!store || store.startsWith("-")) {
101
+ err(`chant index diff: --store needs a store spec\n\n${INDEX_DIFF_USAGE}`);
102
+ return 2;
103
+ }
104
+ }
105
+ else if (a.startsWith("--store="))
106
+ store = a.slice("--store=".length);
107
+ else if (a.startsWith("-")) {
108
+ err(`chant index diff: unknown flag ${a}\n\n${INDEX_DIFF_USAGE}`);
109
+ return 2;
110
+ }
111
+ else
112
+ refs.push(a);
113
+ }
114
+ if (refs.length < 1 || refs.length > 2) {
115
+ err(`chant index diff: name one or two index versions\n\n${INDEX_DIFF_USAGE}`);
116
+ return 2;
117
+ }
118
+ let d;
119
+ try {
120
+ const from = parseIndexVersionRef(refs[0]);
121
+ const to = refs[1] ? parseIndexVersionRef(refs[1], from.scopeKey) : undefined;
122
+ const plan = planIndexStore({ store, cwd, env, defaultStoreDir: () => chantUserStoreDir(env, o.home ?? homedir()), command: "chant index diff" });
123
+ const s = await (o.openStore ?? openReadStore)(plan, cwd);
124
+ await s.fetch();
125
+ d = await diffIndexVersionRefs(s, from, to);
126
+ }
127
+ catch (e) {
128
+ if (e instanceof IndexUsageError) {
129
+ err(`${e.message}\n`);
130
+ return 2;
131
+ }
132
+ if (e instanceof IndexScopeMismatch || e instanceof NotAnIndexVersion) {
133
+ if (json)
134
+ out(`${JSON.stringify({ error: e.code, message: e.message, ...(e instanceof IndexScopeMismatch ? { fromScopeKey: e.fromScopeKey, toScopeKey: e.toScopeKey } : {}) }, null, 2)}\n`);
135
+ err(`chant index diff: ${e.message}\n`);
136
+ return 1;
137
+ }
138
+ throw e;
139
+ }
140
+ out(json ? `${JSON.stringify(d, null, 2)}\n` : renderIndexDiff(d));
141
+ return 0;
142
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * `chant lifecycle drift [--member <name>] [--read <read>] [--resource <addr>]`
3
+ * (behold#995): the project's drift, as each lexicon's own engine reads it,
4
+ * printed as the drift-record NDJSON stream (`../../drift-record.ts`).
5
+ *
6
+ * This is the member half of `chant workspace drift`. A `terraform` or
7
+ * `choudoufu` member has no chant config of its own, so the workspace writes
8
+ * it a reader project (`../../workspace/kind-readers.ts`) and runs this
9
+ * command there, under the member's own toolchain, the way `workspace graph`
10
+ * runs `chant graph`. Every lexicon with a `readDrift` is asked; the lines
11
+ * are printed in the order they came, one JSON object per line. chant core
12
+ * never imports a lexicon to read drift.
13
+ *
14
+ * `--member` names the workspace member the records are for; it defaults to
15
+ * the project directory's name. A lexicon that refuses the read (a read its
16
+ * engine has not got, or one resource on an engine that cannot read one on
17
+ * its own) makes the command print `{"refused": {code, message}}` as its
18
+ * only stdout line and exit 3, so the workspace command can name the
19
+ * refusal. No lexicon with a drift read is the refusal `no-drift-read`.
20
+ */
21
+ import type { CommandContext } from "../registry.js";
22
+ /** The exit status of a refused read. */
23
+ export declare const DRIFT_REFUSED_EXIT = 3;
24
+ export declare function runLifecycleDrift(ctx: CommandContext): Promise<number>;
25
+ //# sourceMappingURL=lifecycle-drift.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle-drift.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/lifecycle-drift.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,yCAAyC;AACzC,eAAO,MAAM,kBAAkB,IAAI,CAAC;AASpC,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA8B5E"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * `chant lifecycle drift [--member <name>] [--read <read>] [--resource <addr>]`
3
+ * (behold#995): the project's drift, as each lexicon's own engine reads it,
4
+ * printed as the drift-record NDJSON stream (`../../drift-record.ts`).
5
+ *
6
+ * This is the member half of `chant workspace drift`. A `terraform` or
7
+ * `choudoufu` member has no chant config of its own, so the workspace writes
8
+ * it a reader project (`../../workspace/kind-readers.ts`) and runs this
9
+ * command there, under the member's own toolchain, the way `workspace graph`
10
+ * runs `chant graph`. Every lexicon with a `readDrift` is asked; the lines
11
+ * are printed in the order they came, one JSON object per line. chant core
12
+ * never imports a lexicon to read drift.
13
+ *
14
+ * `--member` names the workspace member the records are for; it defaults to
15
+ * the project directory's name. A lexicon that refuses the read (a read its
16
+ * engine has not got, or one resource on an engine that cannot read one on
17
+ * its own) makes the command print `{"refused": {code, message}}` as its
18
+ * only stdout line and exit 3, so the workspace command can name the
19
+ * refusal. No lexicon with a drift read is the refusal `no-drift-read`.
20
+ */
21
+ import { basename, resolve } from "node:path";
22
+ import { loadChantConfig } from "../../config.js";
23
+ import { DRIFT_READS, encodeDriftLine } from "../../drift-record.js";
24
+ import { formatError } from "../format.js";
25
+ /** The exit status of a refused read. */
26
+ export const DRIFT_REFUSED_EXIT = 3;
27
+ const USAGE = "chant lifecycle drift [--member <name>] [--read <state|plan|refresh|live-read|ownership>] [--resource <addr>]";
28
+ function refuse(code, message) {
29
+ console.log(JSON.stringify({ refused: { code, message } }));
30
+ return DRIFT_REFUSED_EXIT;
31
+ }
32
+ export async function runLifecycleDrift(ctx) {
33
+ const { args, plugins } = ctx;
34
+ const read = args.driftRead;
35
+ if (read !== undefined && !DRIFT_READS.includes(read)) {
36
+ console.error(formatError({ message: `--read ${read} is not a drift read; the reads are ${DRIFT_READS.join(", ")}`, hint: USAGE }));
37
+ return 1;
38
+ }
39
+ const projectRoot = resolve(".");
40
+ const { config } = await loadChantConfig(projectRoot);
41
+ const member = args.members?.[0] ?? basename(projectRoot);
42
+ const readers = plugins.filter((p) => typeof p.readDrift === "function");
43
+ if (readers.length === 0) {
44
+ return refuse("no-drift-read", `no lexicon this project declares (${plugins.map((p) => p.name).join(", ") || "none"}) has a drift read`);
45
+ }
46
+ const observedAt = new Date().toISOString();
47
+ const lines = [];
48
+ for (const plugin of readers) {
49
+ const answer = await plugin.readDrift({
50
+ member,
51
+ projectRoot,
52
+ config: config,
53
+ ...(read !== undefined ? { read: read } : {}),
54
+ ...(args.resource !== undefined ? { resource: args.resource } : {}),
55
+ observedAt,
56
+ });
57
+ if ("refused" in answer)
58
+ return refuse(answer.refused.code, `${plugin.name}: ${answer.refused.message}`);
59
+ lines.push(...answer.lines);
60
+ }
61
+ for (const line of lines)
62
+ process.stdout.write(encodeDriftLine(line));
63
+ return 0;
64
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/lifecycle.ts"],"names":[],"mappings":"AA+CA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAKlD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,GAAG,MAAM,CAE9E;AAED;;cAEc;AACd,UAAU,WAAW;IACnB;iDAC6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;0CACsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb;;;6DAGyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,GAAG,WAAW,EAAE,CAMxF;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAyH/E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA4C3E;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA8B/E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA+L3E;AA+sBD;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAyR3E;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA2L/E;AAsBD;;GAEG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAiB1E;AAgBD;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAmE7E;AAiCD;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAM9E;AAkBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA8D/E"}
1
+ {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/lifecycle.ts"],"names":[],"mappings":"AAkDA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAKlD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAKhD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,GAAG,MAAM,CAE9E;AAED;;cAEc;AACd,UAAU,WAAW;IACnB;iDAC6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;0CACsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb;;;6DAGyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,GAAG,WAAW,EAAE,CAMxF;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA8H/E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA6C3E;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA8B/E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA8Q3E;AA8xBD;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA2R3E;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA2L/E;AAsBD;;GAEG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAoB1E;AAgBD;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAmE7E;AAiCD;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAM9E;AAkBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA8D/E"}
@@ -1,15 +1,19 @@
1
1
  import { lexiconNames } from "../../lexicon-module.js";
2
- import { resolve } from "node:path";
2
+ import { basename, resolve } from "node:path";
3
3
  import { commandBuildParams } from "../build-params-cli.js";
4
4
  import { build } from "../../build.js";
5
5
  import { takeSnapshot } from "../../lifecycle/snapshot.js";
6
- import { readSnapshot, readSnapshotAt, readEnvironmentSnapshots, listSnapshots, fetchLifecycle, pushLifecycle, snapshotStorageKey, StaleLifecycleBranchError } from "../../lifecycle/git.js";
6
+ import { snapshotStorageKey, StaleLifecycleBranchError } from "../../lifecycle/git.js";
7
+ import { readEnvironmentSnapshotsFrom, resolveSnapshotStore } from "../../lifecycle/snapshot-store.js";
7
8
  import { deepDiffForLexicon } from "../../lifecycle/deep-observe.js";
8
9
  import { countUnclaimed, countPending, countPropertyDrift, countHeld, suspiciousHeld } from "../../lifecycle/deep-diff.js";
9
10
  import { describePathOrigin, getPathProvenance, getProvenance } from "../../provenance.js";
10
11
  import { resolveDeepDrift, resolveDriftedField } from "../../fold-provenance.js";
11
- import { acceptDeviations, baselineForLexicon, emptyBaseline, readObservationBaseline, writeObservationBaseline, OBSERVATION_BASELINE_FILE, } from "../../lifecycle/observation-baseline.js";
12
+ import { acceptDeviations, baselineForLexicon, emptyBaseline, readObservationBaseline, saveObservationBaseline, } from "../../lifecycle/observation-baseline.js";
12
13
  import { computeBuildDigest, declaredDefinitions, diffDigests } from "../../lifecycle/digest.js";
14
+ import { diffDeclaredAgainstIndex, indexDriftDocument } from "../../lifecycle/index-drift.js";
15
+ import { joinCell, parseIndexRef, readIndexRef } from "../../lifecycle/index-join.js";
16
+ import { CHANT_VERSION } from "../../chant-version.js";
13
17
  import { diffLive, diffLiveArtifacts, diffSnapshots, missingRow } from "../../lifecycle/live-diff.js";
14
18
  import { buildChangeSet, renderChangeSet, renderChangeSetMarkdown, gitlabMrReport, unobservedPlanNotice } from "../../lifecycle/change-set.js";
15
19
  import { mergeReceiptEntries, observedValueResolver, planReceipts, readReceiptValue } from "../../lifecycle/receipt-plan.js";
@@ -100,6 +104,7 @@ export async function runLifecycleSnapshot(ctx) {
100
104
  // from its own scoped root — so its logical ids match what it deploys — and
101
105
  // snapshots against its own live stack name (#932).
102
106
  const targets = resolveStackTargets(args, config);
107
+ const store = await resolveSnapshotStore({ cwd: projectPath, config });
103
108
  let anySnapshotSaved = false;
104
109
  let anyHardError = false;
105
110
  // #1166 — same self-sufficiency as `chant graph --live`: a snapshot is
@@ -139,6 +144,7 @@ export async function runLifecycleSnapshot(ctx) {
139
144
  deep: args.deep,
140
145
  ambient: args.ambient,
141
146
  ambientKinds: projectKinds,
147
+ store,
142
148
  });
143
149
  }
144
150
  catch (err) {
@@ -163,7 +169,10 @@ export async function runLifecycleSnapshot(ctx) {
163
169
  const counts = result.snapshots
164
170
  .map((s) => `${s.lexicon}(${Object.keys(s.resources).length})`)
165
171
  .join(" ");
166
- console.error(formatSuccess(`${prefix}Snapshot saved to chant/lifecycle (${counts})`));
172
+ // `none` keeps nothing, and says so: the observation still ran (#4519).
173
+ console.error(result.store && !result.store.written
174
+ ? formatWarning({ message: `${prefix}Snapshot observed, not kept: the store is ${result.store.where} (${counts})` })
175
+ : formatSuccess(`${prefix}Snapshot saved to ${store.where} (${counts})`));
167
176
  }
168
177
  if (result.errors.length > 0)
169
178
  anyHardError = true;
@@ -185,9 +194,10 @@ export async function runLifecycleShow(ctx) {
185
194
  return 1;
186
195
  }
187
196
  // Fetch from remote first
188
- await fetchLifecycle();
197
+ const store = await resolveSnapshotStore();
198
+ await store.fetch();
189
199
  if (lexiconFilter) {
190
- const content = await readSnapshot(environment, lexiconFilter);
200
+ const content = await store.readLatest(environment, lexiconFilter);
191
201
  if (!content) {
192
202
  console.error(formatError({ message: `No snapshot found for ${environment}/${lexiconFilter}` }));
193
203
  return 1;
@@ -196,7 +206,7 @@ export async function runLifecycleShow(ctx) {
196
206
  printSnapshotTable(snapshot);
197
207
  }
198
208
  else {
199
- const snapshots = await readEnvironmentSnapshots(environment);
209
+ const snapshots = await readEnvironmentSnapshotsFrom(store, environment);
200
210
  if (snapshots.size === 0) {
201
211
  console.error(formatError({ message: `No snapshots found for environment "${environment}"` }));
202
212
  return 1;
@@ -277,6 +287,21 @@ export async function runLifecycleDiff(ctx) {
277
287
  json: !!args.json,
278
288
  });
279
289
  }
290
+ // `--index <ref>` (#4526): the observed side is an index version in the
291
+ // store, not a live read and not a snapshot.
292
+ const indexMode = args.index !== undefined;
293
+ if (indexMode && (args.live || (args.betweenA && args.betweenB))) {
294
+ console.error(formatError({
295
+ message: `chant lifecycle diff takes --index or ${args.live ? "--live" : "--between"}, not both`,
296
+ hint: "--index compares source with an index version in the store; --live reads the estate now; --between compares two snapshots",
297
+ }));
298
+ return 1;
299
+ }
300
+ const indexRef = indexMode ? parseIndexRef(String(args.index)) : undefined;
301
+ if (indexRef && "error" in indexRef) {
302
+ console.error(formatError({ message: indexRef.error, hint: indexRef.hint }));
303
+ return 1;
304
+ }
280
305
  // Filter serializers to target lexicon before building
281
306
  const targetSerializers = lexiconFilter
282
307
  ? plugins.filter((p) => p.name === lexiconFilter).map((p) => p.serializer)
@@ -288,7 +313,18 @@ export async function runLifecycleDiff(ctx) {
288
313
  const declaredParams = await commandBuildParams(config.buildParams, args);
289
314
  if (!declaredParams)
290
315
  return 1;
291
- await fetchLifecycle();
316
+ const store = await resolveSnapshotStore({ config });
317
+ await store.fetch();
318
+ let indexRead;
319
+ if (indexRef && !("error" in indexRef)) {
320
+ const read = await readIndexRef(store, indexRef);
321
+ if ("error" in read) {
322
+ console.error(formatError({ message: read.error, ...(read.hint ? { hint: read.hint } : {}) }));
323
+ return 1;
324
+ }
325
+ indexRead = read;
326
+ }
327
+ const indexResults = [];
292
328
  // One target per stack (single-stack projects: exactly one), each built from
293
329
  // its own scoped root and diffed against its own live stack name (#932).
294
330
  const targets = resolveStackTargets(args, config);
@@ -302,7 +338,7 @@ export async function runLifecycleDiff(ctx) {
302
338
  // Accepted-deviation baseline (#1014). Read once for the whole run — it is
303
339
  // env-keyed, not stack-keyed, and every deep pass subtracts from the same
304
340
  // committed set. Absent is the normal state (nothing accepted yet).
305
- const baseline = args.live ? await readObservationBaseline(environment) : null;
341
+ const baseline = args.live || indexRead ? await readObservationBaseline(environment, { config }) : null;
306
342
  const accepted = {};
307
343
  // Effect receipts across every target's build (#1833) — `--update-baseline`
308
344
  // refuses to accept drift on them (the effect step is their only writer),
@@ -312,7 +348,7 @@ export async function runLifecycleDiff(ctx) {
312
348
  // Floci), so `--live` is self-sufficient even when the ambient shell never
313
349
  // exported e.g. AWS_ENDPOINT_URL. Ambient always wins when it's already set.
314
350
  // Scoped to just the live reads below — restored in `finally`.
315
- const liveLexicons = args.live ? plugins.filter((p) => p.describeResources || p.listArtifacts) : [];
351
+ const liveLexicons = args.live && !indexRead ? plugins.filter((p) => p.describeResources || p.listArtifacts) : [];
316
352
  const endpointResult = applyLiveEndpoint(config.environments, environment, liveLexicons);
317
353
  if (endpointResult.notice)
318
354
  console.error(formatWarning({ message: endpointResult.notice }));
@@ -377,6 +413,7 @@ export async function runLifecycleDiff(ctx) {
377
413
  plugins,
378
414
  buildResult,
379
415
  json,
416
+ store,
380
417
  stack: target.stack,
381
418
  region: target.region,
382
419
  componentStacks,
@@ -402,15 +439,69 @@ export async function runLifecycleDiff(ctx) {
402
439
  combinedLexiconsJson = r.byLexicon;
403
440
  }
404
441
  }
442
+ else if (indexRead) {
443
+ const r = runLifecycleDiffIndex({
444
+ read: indexRead,
445
+ lexicons: lexiconFilter ? [lexiconFilter] : builtLexicons,
446
+ plugins,
447
+ buildResult,
448
+ baseline,
449
+ member: basename(projectRoot),
450
+ stack: target.stack,
451
+ region: target.region,
452
+ json,
453
+ projectRoot,
454
+ });
455
+ indexResults.push(r);
456
+ for (const [lexicon, part] of Object.entries(r.byLexicon)) {
457
+ if (args.updateBaseline)
458
+ (accepted[lexicon] ?? (accepted[lexicon] = [])).push(...deviationsToAccept(part.deep));
459
+ }
460
+ if (args.updateBaseline) {
461
+ for (const name of collectEffectReceipts(buildResult.entities).keys())
462
+ receiptEntities.add(name);
463
+ }
464
+ }
405
465
  else {
406
- await runLifecycleDiffDigest({ environment, lexicons, buildResult, stack: target.stack });
466
+ await runLifecycleDiffDigest({ environment, lexicons, buildResult, stack: target.stack, store });
407
467
  }
408
468
  }
409
469
  // `--update-baseline` (#1014): record what the deep pass just reported as
410
470
  // accepted, so it stops re-alerting. Runs before the summary lines so the
411
471
  // "no drift" verdict below still describes the run that produced it.
412
- if (args.live && args.updateBaseline) {
413
- await recordAcceptedBaseline(environment, baseline, accepted, json, receiptEntities);
472
+ if ((args.live || indexRead) && args.updateBaseline) {
473
+ await recordAcceptedBaseline(environment, baseline, accepted, json, receiptEntities, config);
474
+ }
475
+ if (indexRead) {
476
+ // Drift records, drift document v1 (#4526).
477
+ if (json)
478
+ console.log(JSON.stringify(indexDriftDocument(indexResults, CHANT_VERSION)));
479
+ else {
480
+ const sum = (k) => indexResults.reduce((n, r) => n + r.counts[k], 0);
481
+ const ref = indexResults[0]?.ref;
482
+ const declaredCount = sum("declared");
483
+ const drift = sum("properties") + sum("pending");
484
+ const notObserved = sum("notObserved");
485
+ if (anyBuildError) {
486
+ // the build error is already printed
487
+ }
488
+ else if (declaredCount === 0) {
489
+ console.error(formatWarning({ message: "No declared entities to compare with the index" }));
490
+ }
491
+ else if (drift === 0) {
492
+ console.error(notObserved > 0
493
+ ? formatWarning({
494
+ message: `No drift detected against index ${ref} across ${sum("bound")} bound entity(ies), but ${notObserved} declared entity(ies) are not observed by it: that part of the estate is unknown, not clean`,
495
+ })
496
+ : formatSuccess(`No drift detected against index ${ref} across ${declaredCount} declared entity(ies)`));
497
+ }
498
+ else {
499
+ console.error(formatWarning({
500
+ message: `Drift against index ${ref}: ${sum("properties")} property difference(s) on ${sum("drifted")} entity(ies), ${sum("pending")} declared entity(ies) absent from it, ${notObserved} not observed`,
501
+ }));
502
+ }
503
+ }
504
+ return anyBuildError ? 1 : 0;
414
505
  }
415
506
  if (args.live) {
416
507
  if (json) {
@@ -451,7 +542,7 @@ export async function runLifecycleDiff(ctx) {
451
542
  * count and the storage path, and a failed push says so rather than leaving
452
543
  * the operator believing the team's baseline moved.
453
544
  */
454
- async function recordAcceptedBaseline(environment, existing, accepted, json, receipts) {
545
+ async function recordAcceptedBaseline(environment, existing, accepted, json, receipts, config) {
455
546
  const total = Object.values(accepted).reduce((n, d) => n + d.length, 0);
456
547
  if (total === 0) {
457
548
  if (!json) {
@@ -469,11 +560,15 @@ async function recordAcceptedBaseline(environment, existing, accepted, json, rec
469
560
  for (const [lexicon, deviations] of Object.entries(accepted)) {
470
561
  next = acceptDeviations(next, lexicon, deviations, { receipts });
471
562
  }
472
- await writeObservationBaseline(next);
473
- const pushed = await pushLifecycle();
563
+ // A file under .chant/observation-baseline/ by default (#4519): commit it
564
+ // with the change that needed it, so the acceptance is reviewed.
565
+ const saved = await saveObservationBaseline(next, config ? { config } : undefined);
474
566
  if (!json) {
475
- console.error(formatSuccess(`--update-baseline: accepted ${total} deviation(s) into ${environment}/${OBSERVATION_BASELINE_FILE} on chant/lifecycle` +
476
- (pushed ? " (pushed)" : " (local only — no remote configured or push refused)")));
567
+ const note = saved.published === "pushed" ? " (pushed)"
568
+ : saved.published === "file" ? " (commit it to keep it)"
569
+ : saved.published === "none" ? " (the baseline store is none: nothing kept)"
570
+ : " (local only — no remote configured or push refused)";
571
+ console.error(formatSuccess(`--update-baseline: accepted ${total} deviation(s) into ${saved.where}${note}`));
477
572
  }
478
573
  }
479
574
  catch (err) {
@@ -489,8 +584,9 @@ async function recordAcceptedBaseline(environment, existing, accepted, json, rec
489
584
  * two-way delta per lexicon.
490
585
  */
491
586
  async function runLifecycleDiffBetween(args) {
492
- await fetchLifecycle();
493
587
  const { config } = await loadChantConfig(resolve("."));
588
+ const store = await resolveSnapshotStore({ config });
589
+ await store.fetch();
494
590
  const lexicons = args.lexiconFilter ? [args.lexiconFilter] : lexiconNames(config.lexicons ?? []);
495
591
  if (lexicons.length === 0) {
496
592
  console.error(formatError({ message: "No lexicons to diff — pass a lexicon or declare `lexicons` in chant.config." }));
@@ -508,8 +604,8 @@ async function runLifecycleDiffBetween(args) {
508
604
  };
509
605
  const byLexicon = {};
510
606
  for (const lexicon of lexicons) {
511
- const prev = parseResources(await readSnapshotAt(args.environment, lexicon, args.refA));
512
- const next = parseResources(await readSnapshotAt(args.environment, lexicon, args.refB));
607
+ const prev = parseResources(await store.readAt(args.environment, lexicon, args.refA));
608
+ const next = parseResources(await store.readAt(args.environment, lexicon, args.refB));
513
609
  if (prev === null && next === null) {
514
610
  if (!args.json)
515
611
  console.error(formatWarning({ message: `${lexicon}: not captured at either ref — skipping` }));
@@ -542,7 +638,7 @@ async function runLifecycleDiffDigest(args) {
542
638
  if (args.stack)
543
639
  console.log(`\n${formatBold(`■ stack ${args.stack}`)}`);
544
640
  for (const lexicon of args.lexicons) {
545
- const content = await readSnapshot(args.environment, snapshotStorageKey(lexicon, args.stack));
641
+ const content = await args.store.readLatest(args.environment, snapshotStorageKey(lexicon, args.stack));
546
642
  let previousDigest = undefined;
547
643
  if (content) {
548
644
  const snapshot = JSON.parse(content);
@@ -672,7 +768,7 @@ async function runLifecycleDiffLive(args) {
672
768
  : rawOutput.primary;
673
769
  // Read previous snapshot once; both flows pull what they need.
674
770
  let prevSnapshot;
675
- const content = await readSnapshot(args.environment, snapshotStorageKey(lexiconName, args.stack));
771
+ const content = await args.store.readLatest(args.environment, snapshotStorageKey(lexiconName, args.stack));
676
772
  if (content)
677
773
  prevSnapshot = JSON.parse(content);
678
774
  let lexiconChecked = false;
@@ -790,6 +886,65 @@ async function runLifecycleDiffLive(args) {
790
886
  }
791
887
  return { byLexicon, totalDrift, totalUnobserved, totalLexiconsChecked, toAccept };
792
888
  }
889
+ /**
890
+ * `chant lifecycle diff <env> --index <ref>` for one stack (#4526): every
891
+ * declared entity joined to the index version, the bound ones deep-diffed
892
+ * against their indexed trees, the rest reported with their join verdict.
893
+ * Reads nothing but the store. See ../../lifecycle/index-drift.ts.
894
+ */
895
+ function runLifecycleDiffIndex(args) {
896
+ const entities = new Map();
897
+ for (const lexicon of args.lexicons)
898
+ entities.set(lexicon, new Map());
899
+ for (const [name, entity] of args.buildResult.entities) {
900
+ const forLexicon = entities.get(entity.lexicon);
901
+ if (!forLexicon || !isObservableDeclarable(entity))
902
+ continue;
903
+ const pathOrigins = getPathProvenance(entity);
904
+ forLexicon.set(name, {
905
+ entityType: entity.entityType,
906
+ props: (entity.props != null ? entity.props : {}),
907
+ ...(pathOrigins ? { pathOrigins } : {}),
908
+ });
909
+ }
910
+ const result = diffDeclaredAgainstIndex({
911
+ doc: args.read.doc,
912
+ version: args.read.version,
913
+ entities,
914
+ lexicons: args.plugins,
915
+ baseline: args.baseline,
916
+ member: args.member,
917
+ ...(args.stack ? { stack: args.stack } : {}),
918
+ ...(args.region ? { region: args.region } : {}),
919
+ chant: CHANT_VERSION,
920
+ });
921
+ if (args.json)
922
+ return result;
923
+ const { stamp } = args.read.doc;
924
+ const by = stamp.source.version ? `${stamp.source.name} ${stamp.source.version}` : stamp.source.name;
925
+ if (args.stack)
926
+ console.log(`\n${formatBold(`■ stack ${args.stack}`)}`);
927
+ console.log(`index ${result.ref}, read ${stamp.observedAt} by ${by}`);
928
+ const provenanceOf = (name) => {
929
+ const entity = args.buildResult.entities.get(name);
930
+ return entity ? getProvenance(entity) : undefined;
931
+ };
932
+ for (const [lexicon, part] of Object.entries(result.byLexicon)) {
933
+ const rows = Object.entries(part.joins).sort(([a], [b]) => a.localeCompare(b));
934
+ const bound = rows.filter(([, j]) => j.verdict === "bound").length;
935
+ console.log(formatBold(`\n${lexicon}: ${bound}/${rows.length} declared entity(ies) bound to the index`));
936
+ const unbound = rows.filter(([, j]) => j.verdict !== "bound");
937
+ if (unbound.length > 0) {
938
+ console.log(formatBold("\nNOT COMPARED (the join did not bind; never diffed):"));
939
+ for (const [name, j] of unbound) {
940
+ const detail = "detail" in j ? `: ${j.detail}` : j.verdict === "absent" ? ": the index listed its type and location and does not hold it" : "";
941
+ console.log(` ? ${name} ${joinCell(j) ?? ""}${detail}`);
942
+ }
943
+ }
944
+ renderDeepDiff(lexicon, part.deep, provenanceOf, args.projectRoot);
945
+ }
946
+ return result;
947
+ }
793
948
  /**
794
949
  * Everything a deep diff reported this run, as deviations to record accepted.
795
950
  * `--update-baseline` accepts what was *reported*, never what was already
@@ -1068,7 +1223,8 @@ export async function runLifecyclePlan(ctx) {
1068
1223
  console.error(formatError({ message: "Build failed — fix errors before planning" }));
1069
1224
  return 1;
1070
1225
  }
1071
- await fetchLifecycle();
1226
+ const store = await resolveSnapshotStore({ config });
1227
+ await store.fetch();
1072
1228
  const lexicons = lexiconFilter ? [lexiconFilter] : Array.from(buildResult.manifest.lexicons);
1073
1229
  // Multi-stack component projects deploy one CFN stack per component, so the
1074
1230
  // single-stack-per-env observe below would see nothing live and plan every
@@ -1219,7 +1375,8 @@ export async function runLifecyclePlan(ctx) {
1219
1375
  receiptReadings.set(receiptName, { observed: true, present: false, lexicon: lexiconName });
1220
1376
  }
1221
1377
  }
1222
- const content = await readSnapshot(environment, lexiconName);
1378
+ // Evidence only (#4519): the change set never makes a decision from it.
1379
+ const content = await store.readLatest(environment, lexiconName);
1223
1380
  const observedThen = content ? JSON.parse(content).resources : undefined;
1224
1381
  const cs = buildChangeSet(environment, {
1225
1382
  declared,
@@ -1500,15 +1657,18 @@ async function promptProdTeardown(environment) {
1500
1657
  */
1501
1658
  export async function runLifecycleLog(ctx) {
1502
1659
  const environment = ctx.args.extraPositional;
1503
- await fetchLifecycle();
1504
- const entries = await listSnapshots({ environment });
1660
+ const store = await resolveSnapshotStore();
1661
+ await store.fetch();
1662
+ const entries = await store.list({ ...(environment ? { environment } : {}) });
1505
1663
  if (entries.length === 0) {
1506
1664
  console.error(formatError({ message: "No state snapshots found" }));
1507
1665
  return 1;
1508
1666
  }
1667
+ // A git store's version is a commit; s3's an object version, local's a time.
1668
+ const isCommit = (v) => /^[0-9a-f]{40}$/.test(v);
1509
1669
  for (const entry of entries) {
1510
1670
  const date = entry.date.split("T")[0];
1511
- console.log(`${entry.commit.slice(0, 7)} ${date} ${entry.message}`);
1671
+ console.log(`${isCommit(entry.version) ? entry.version.slice(0, 7) : entry.version} ${date} ${entry.key ?? entry.message}`);
1512
1672
  }
1513
1673
  return 0;
1514
1674
  }
@@ -1,7 +1,16 @@
1
+ import type { IndexImportSelection } from "../../lifecycle/index-import.js";
1
2
  import type { CommandContext } from "../registry.js";
2
3
  export declare function runAudit(ctx: CommandContext): Promise<number>;
3
4
  export declare function runList(ctx: CommandContext): Promise<number>;
4
5
  export declare function runDescribe(ctx: CommandContext): Promise<number>;
6
+ /**
7
+ * The selection for `chant import --index` (#4524). `--type` and `--name`
8
+ * take comma-separated lists, `--tag key=value` repeats, `--select` is a JSON
9
+ * file of node ids (a list of ids, of `{ id }` or `{ node }` objects, or an
10
+ * object holding `nodes` or `results`) or a comma-separated list of ids, and
11
+ * `--all` takes every node.
12
+ */
13
+ export declare function indexSelectionFromArgs(args: CommandContext["args"]): IndexImportSelection | Error;
5
14
  export declare function runImport(ctx: CommandContext): Promise<number>;
6
15
  export declare function runUpdate(ctx: CommandContext): Promise<number>;
7
16
  export declare function runDoctor(ctx: CommandContext): Promise<number>;
@@ -1 +1 @@
1
- {"version":3,"file":"misc.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/misc.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AA8ClD,wBAAsB,QAAQ,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAqGnE;AAED,wBAAsB,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAuClE;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA8CtE;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAqJpE;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAKpE;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBpE"}
1
+ {"version":3,"file":"misc.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/misc.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAQzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AA8ClD,wBAAsB,QAAQ,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAqGnE;AAED,wBAAsB,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAuClE;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA8CtE;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,cAAc,CAAC,MAAM,CAAC,GAAG,oBAAoB,GAAG,KAAK,CAwCjG;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA2KpE;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAKpE;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBpE"}