@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
@@ -1,6 +1,7 @@
1
1
  import { describe, expect, test } from "vitest";
2
2
  import type { LedgerReadPort } from "./ledger-port";
3
- import { firstWord, formatQueryResult, loadQueryData, QUERY_SCHEMA_VERSION, QUERY_TABLES, QueryError, runQuery, SCHEMA_TABLE } from "./query";
3
+ import { NEXT_RELEASE } from "../release-floors";
4
+ import { firstWord, formatQueryResult, loadQueryData, QUERY_OWNERSHIP_COLUMNS_FLOOR, QUERY_SCHEMA_VERSION, QUERY_TABLES, QueryError, runQuery, SCHEMA_TABLE } from "./query";
4
5
  import { makeRelease } from "./release-store";
5
6
 
6
7
  /** A port over a map of `<dir>/<file>` to text, the shape `gitLedgerReadPort` reads. */
@@ -88,4 +89,71 @@ describe("chant query (#4297)", () => {
88
89
  await expect(runQuery("SELECT nope FROM runs", load)).rejects.toThrow(/does not run/);
89
90
  expect(firstWord("-- note\n /* c */ select 1")).toBe("select");
90
91
  });
92
+
93
+ describe("ownership columns on resources (#4534)", () => {
94
+ // A choudoufu live root read through the terraform lexicon, and a k8s
95
+ // root whose labels name the stack and env. Engine facts are the
96
+ // snapshot's `facts`; chant's marker is its `marker`.
97
+ const owned = port({
98
+ "prod/estate__terraform.json": JSON.stringify({
99
+ lexicon: "terraform",
100
+ environment: "prod",
101
+ commit: "d".repeat(40),
102
+ timestamp: "2026-10-26T00:00:00Z",
103
+ resources: {
104
+ "aws_s3_bucket.logs": { type: "aws_s3_bucket", status: "bound", physicalId: "acme-logs", ownership: "owned", marker: { stack: "acme", env: "aws_s3_bucket.logs" }, facts: { ownership: "bound", ownedBy: "marker" } },
105
+ "aws_sqs_queue.jobs": { type: "aws_sqs_queue", status: "unowned", ownership: "foreign", facts: { ownership: "unowned" } },
106
+ "aws_eip.pool": { type: "aws_eip", status: "bound", ownership: "owned", facts: { ownership: "bound", ownedBy: "record" } },
107
+ },
108
+ }),
109
+ "prod/shop__k8s.json": JSON.stringify({
110
+ lexicon: "k8s",
111
+ environment: "prod",
112
+ commit: "e".repeat(40),
113
+ timestamp: "2026-10-26T00:00:00Z",
114
+ resources: { web: { type: "K8s::Apps::Deployment", status: "Available", physicalId: "default/web", ownership: "owned", marker: { stack: "shop", env: "prod" } } },
115
+ }),
116
+ });
117
+
118
+ test("are listed in schema v1, after the existing columns", async () => {
119
+ const cols = QUERY_TABLES.resources.map(([c]) => c);
120
+ expect(cols.slice(0, 13)).toEqual(["member", "env", "stack", "lexicon", "name", "type", "physical_id", "status", "last_updated", "ownership", "attributes", "git_sha", "observed_at"]);
121
+ expect(cols.slice(13)).toEqual(["marker_stack", "marker_env", "engine_ownership", "engine_owned_by"]);
122
+ const load = await loadQueryData([]);
123
+ const r = await runQuery(`SELECT column_name, version FROM ${SCHEMA_TABLE} WHERE table_name = 'resources' AND column_name IN ('ownership', 'marker_stack', 'marker_env', 'engine_ownership', 'engine_owned_by') ORDER BY position`, load);
124
+ expect(r.rows.map((x) => x.column_name)).toEqual(["ownership", "marker_stack", "marker_env", "engine_ownership", "engine_owned_by"]);
125
+ expect(new Set(r.rows.map((x) => x.version))).toEqual(new Set([1]));
126
+ });
127
+
128
+ test("project the snapshot's marker and engine facts, NULL when unknown", async () => {
129
+ const load = await loadQueryData([{ member: null, port: owned }]);
130
+ const by = Object.fromEntries(load.data.resources.map((r) => [r.name, r]));
131
+ expect(by["aws_s3_bucket.logs"]).toMatchObject({ ownership: "owned", marker_stack: "acme", marker_env: "aws_s3_bucket.logs", engine_ownership: "bound", engine_owned_by: "marker" });
132
+ expect(by["aws_sqs_queue.jobs"]).toMatchObject({ ownership: "foreign", marker_stack: null, marker_env: null, engine_ownership: "unowned", engine_owned_by: null });
133
+ expect(by.web).toMatchObject({ lexicon: "k8s", ownership: "owned", marker_stack: "shop", marker_env: "prod", engine_ownership: null, engine_owned_by: null });
134
+ });
135
+
136
+ test("are NULL on a snapshot that predates them", async () => {
137
+ const load = await loadQueryData([{ member: null, port: ledger }]);
138
+ for (const r of load.data.resources) {
139
+ expect(r).toMatchObject({ marker_stack: null, marker_env: null, engine_ownership: null, engine_owned_by: null });
140
+ }
141
+ });
142
+
143
+ test("count by both verdicts without the graph peer", async () => {
144
+ const load = await loadQueryData([{ member: null, port: owned }]);
145
+ const r = await runQuery("SELECT lexicon, ownership, engine_ownership, count(*) AS n FROM resources GROUP BY 1, 2, 3 ORDER BY 1, 2, 3", load);
146
+ expect(r.rows).toEqual([
147
+ { lexicon: "k8s", ownership: "owned", engine_ownership: null, n: 1 },
148
+ { lexicon: "terraform", ownership: "foreign", engine_ownership: "unowned", n: 1 },
149
+ { lexicon: "terraform", ownership: "owned", engine_ownership: "bound", n: 2 },
150
+ ]);
151
+ const who = await runQuery("SELECT stack, name, marker_stack FROM resources WHERE physical_id = 'default/web'", load);
152
+ expect(who.rows).toEqual([{ stack: "shop", name: "web", marker_stack: "shop" }]);
153
+ });
154
+
155
+ test("carry their floor at the next release", () => {
156
+ expect(QUERY_OWNERSHIP_COLUMNS_FLOOR).toBe(NEXT_RELEASE);
157
+ });
158
+ });
91
159
  });
@@ -1,12 +1,14 @@
1
1
  /**
2
- * `chant query "<sql>"` (#4297): one read-only SQL statement over what
3
- * `chant/lifecycle` holds, run in this process with no server.
2
+ * `chant query "<sql>"` (#4297): one read-only SQL statement over the
3
+ * snapshots and the Ops records, run in this process with no server.
4
4
  *
5
5
  * The rows come from the ledgers chant already writes:
6
6
  *
7
7
  * - the snapshots, `<env>/<lexicon>.json` and `<env>/<stack>__<lexicon>.json`
8
8
  * (`./git.ts` `snapshotStorageKey`), each lexicon's `describeResources`
9
- * read, so the inventory works for every lexicon;
9
+ * read, so the inventory works for every lexicon. They are read through the
10
+ * index store (./snapshot-store.ts, #4519) when the ledger names one, so
11
+ * the tables are the same whichever store holds them;
10
12
  * - the Op run ledgers, `<env>/runs__<op>.jsonl` (`./run-ledger.ts`);
11
13
  * - the gate ledgers, `_gates/<op>.jsonl` (`./gate-ledger.ts`);
12
14
  * - the deploy records, `<env>/releases.jsonl` (`./release-read.ts`);
@@ -34,6 +36,7 @@ import { parseReleaseLedger, releaseLedgerLines } from "./release-read";
34
36
  import { CUTS_FILE, parseCuts, parseRelease, RELEASES_DIR, verifyReleaseDigest } from "./release-store";
35
37
  import { opOfRunLedgerFile, parseRunLedger } from "./run-ledger";
36
38
  import type { LifecycleSnapshot } from "./types";
39
+ import { NEXT_RELEASE } from "../release-floors";
37
40
 
38
41
  /** The version of the table schema below. */
39
42
  export const QUERY_SCHEMA_VERSION = 1;
@@ -47,12 +50,28 @@ type ColumnType = "TEXT" | "INTEGER";
47
50
  * for a project outside a workspace.
48
51
  */
49
52
  export const QUERY_TABLES = {
50
- /** One row per resource in each environment's newest snapshot. `attributes` is JSON. */
51
- resources: [["member", "TEXT"], ["env", "TEXT"], ["stack", "TEXT"], ["lexicon", "TEXT"], ["name", "TEXT"], ["type", "TEXT"], ["physical_id", "TEXT"], ["status", "TEXT"], ["last_updated", "TEXT"], ["ownership", "TEXT"], ["attributes", "TEXT"], ["git_sha", "TEXT"], ["observed_at", "TEXT"]],
53
+ /**
54
+ * One row per resource in each environment's newest snapshot. `attributes`
55
+ * is JSON. `ownership` is chant's marker verdict; `marker_stack` and
56
+ * `marker_env` (#4534) are the stack and env that marker names, read off
57
+ * the resource. `engine_ownership` and `engine_owned_by` (#4534) are an
58
+ * ownership engine's verdict and what bound the node (choudoufu, plunge;
59
+ * the snapshot's `facts.ownership` and `facts.ownedBy`), shown beside
60
+ * chant's and never in place of it. NULL means unknown.
61
+ */
62
+ resources: [["member", "TEXT"], ["env", "TEXT"], ["stack", "TEXT"], ["lexicon", "TEXT"], ["name", "TEXT"], ["type", "TEXT"], ["physical_id", "TEXT"], ["status", "TEXT"], ["last_updated", "TEXT"], ["ownership", "TEXT"], ["attributes", "TEXT"], ["git_sha", "TEXT"], ["observed_at", "TEXT"], ["marker_stack", "TEXT"], ["marker_env", "TEXT"], ["engine_ownership", "TEXT"], ["engine_owned_by", "TEXT"]],
52
63
  /** One row per snapshot file: what was observed, when, and how many resources it holds. */
53
64
  snapshots: [["member", "TEXT"], ["env", "TEXT"], ["stack", "TEXT"], ["lexicon", "TEXT"], ["git_sha", "TEXT"], ["observed_at", "TEXT"], ["depth", "TEXT"], ["resources", "INTEGER"], ["unobserved", "INTEGER"]],
54
- /** One row per Op run record. `labels` and `outcomes` are JSON. */
55
- runs: [["member", "TEXT"], ["id", "TEXT"], ["op", "TEXT"], ["env", "TEXT"], ["started", "TEXT"], ["ended", "TEXT"], ["status", "TEXT"], ["git_sha", "TEXT"], ["forge", "TEXT"], ["run_url", "TEXT"], ["failure_code", "TEXT"], ["failure_reason", "TEXT"], ["failed_phase", "TEXT"], ["gate", "TEXT"], ["steward", "TEXT"], ["labels", "TEXT"], ["outcomes", "TEXT"]],
65
+ /**
66
+ * One row per Op run record. `labels` and `outcomes` are JSON. `root_member`
67
+ * (#4482) is the workspace member whose directory holds the terraform root
68
+ * a TerraformApplyOp run applied, read off its `TerraformRootPath` outcome.
69
+ * NULL means unknown (#4508): any other run, outside a workspace, or a run
70
+ * whose Init step failed before it resolved the root's directory, since the
71
+ * Op names its root only by key and Init is what resolves it. A run whose
72
+ * `terraform init` itself failed still names it (#4512).
73
+ */
74
+ runs: [["member", "TEXT"], ["id", "TEXT"], ["op", "TEXT"], ["env", "TEXT"], ["started", "TEXT"], ["ended", "TEXT"], ["status", "TEXT"], ["git_sha", "TEXT"], ["forge", "TEXT"], ["run_url", "TEXT"], ["failure_code", "TEXT"], ["failure_reason", "TEXT"], ["failed_phase", "TEXT"], ["gate", "TEXT"], ["steward", "TEXT"], ["labels", "TEXT"], ["outcomes", "TEXT"], ["root_member", "TEXT"]],
56
75
  /** One row per gate ledger line: `kind` is `pending` or `resolution`. `signed` is 1 for a sealed approval. */
57
76
  gates: [["member", "TEXT"], ["op", "TEXT"], ["gate", "TEXT"], ["kind", "TEXT"], ["timestamp", "TEXT"], ["resolved_by", "TEXT"], ["relayed_by", "TEXT"], ["approver_kind", "TEXT"], ["plan_digest", "TEXT"], ["environment", "TEXT"], ["release_digest", "TEXT"], ["git_sha", "TEXT"], ["run_id", "TEXT"], ["url", "TEXT"], ["note", "TEXT"], ["expires_at", "TEXT"], ["origin", "TEXT"], ["empty", "INTEGER"], ["signed", "INTEGER"]],
58
77
  /** One row per deploy record in `<env>/releases.jsonl`. `promoted_from`, `restores` and `redeploys` are JSON. */
@@ -63,6 +82,22 @@ export const QUERY_TABLES = {
63
82
  cuts: [["member", "TEXT"], ["release_digest", "TEXT"], ["label", "TEXT"], ["actor", "TEXT"], ["timestamp", "TEXT"], ["run_id", "TEXT"], ["forge", "TEXT"], ["channel", "TEXT"], ["signed", "INTEGER"], ["composed_base", "TEXT"]],
64
83
  } as const satisfies Record<string, ReadonlyArray<readonly [string, ColumnType]>>;
65
84
 
85
+ /**
86
+ * The first chant that writes `root_member` on a `runs` row, in `chant query`
87
+ * and in `chant ledger runs --json` (#4482, #4500). A contract field added
88
+ * within version 1: a reader treats a row from an older chant as lacking it.
89
+ */
90
+ export const LEDGER_ROOT_MEMBER_FLOOR = NEXT_RELEASE;
91
+
92
+ /**
93
+ * The first chant that writes `marker_stack`, `marker_env`,
94
+ * `engine_ownership` and `engine_owned_by` on a `resources` row, in
95
+ * `chant query` and in `chant ledger resources --json` (#4534). Columns added
96
+ * within version 1: a reader treats a row from an older chant as lacking
97
+ * them, which reads as unknown.
98
+ */
99
+ export const QUERY_OWNERSHIP_COLUMNS_FLOOR = NEXT_RELEASE;
100
+
66
101
  export type QueryTable = keyof typeof QUERY_TABLES;
67
102
 
68
103
  /** The table that describes the others: one row per column, with the schema version. */
@@ -78,6 +113,17 @@ export type QueryData = Record<QueryTable, QueryRow[]>;
78
113
  export interface QueryLedger {
79
114
  member: string | null;
80
115
  port: LedgerReadPort;
116
+ /**
117
+ * The snapshot family of the index store (#4519, `snapshotReadPort`). Given,
118
+ * the `resources` and `snapshots` rows come from it and snapshot files on
119
+ * `port` are skipped. Absent, they come from `port`, as before the store.
120
+ */
121
+ snapshots?: LedgerReadPort;
122
+ /**
123
+ * The member whose directory holds a workspace-relative path, or null
124
+ * (#4482). Given in a workspace; without it `root_member` is NULL.
125
+ */
126
+ ownerOfPath?: (path: string) => string | null;
81
127
  }
82
128
 
83
129
  export interface QueryLoad {
@@ -119,7 +165,25 @@ function snapshotRows(member: string | null, env: string, file: string, s: Lifec
119
165
  const resources = Object.entries(s.resources);
120
166
  data.snapshots.push({ member, env, stack, lexicon: s.lexicon, ...at, depth: s.depth ?? "identity", resources: resources.length, unobserved: Object.keys(s.unobserved ?? {}).length });
121
167
  for (const [name, r] of resources) {
122
- data.resources.push({ member, env, stack, lexicon: s.lexicon, name, type: str(r?.type), physical_id: str(r?.physicalId), status: str(r?.status), last_updated: str(r?.lastUpdated), ownership: str(r?.ownership), attributes: json(r?.attributes), ...at });
168
+ data.resources.push({
169
+ member,
170
+ env,
171
+ stack,
172
+ lexicon: s.lexicon,
173
+ name,
174
+ type: str(r?.type),
175
+ physical_id: str(r?.physicalId),
176
+ status: str(r?.status),
177
+ last_updated: str(r?.lastUpdated),
178
+ ownership: str(r?.ownership),
179
+ attributes: json(r?.attributes),
180
+ ...at,
181
+ // Read as data from the snapshot (#4534): a projection for people, never a decision.
182
+ marker_stack: str(r?.marker?.stack),
183
+ marker_env: str(r?.marker?.env),
184
+ engine_ownership: str(r?.facts?.ownership),
185
+ engine_owned_by: str(r?.facts?.ownedBy),
186
+ });
123
187
  }
124
188
  }
125
189
 
@@ -150,6 +214,19 @@ function gateRow(member: string | null, r: GateResolutionRecord | PendingGateRec
150
214
  };
151
215
  }
152
216
 
217
+ /**
218
+ * The member a run's `TerraformRootPath` outcome falls in (#4482): the
219
+ * workspace-relative directory of the root a TerraformApplyOp's Init step
220
+ * resolved. A local `chant run` records under the member that declares the
221
+ * Op, so this is what names the member whose root it applied when the two
222
+ * differ, as for a choudoufu member applied from a chant one.
223
+ */
224
+ function rootMemberOf(outcomes: Record<string, unknown> | undefined, ownerOfPath: ((path: string) => string | null) | undefined): string | null {
225
+ const path = outcomes?.TerraformRootPath;
226
+ if (typeof path !== "string" || !ownerOfPath) return null;
227
+ return ownerOfPath(path);
228
+ }
229
+
153
230
  /**
154
231
  * Read every table's rows from the ledgers, in the order given. A ledger
155
232
  * whose branch is absent reads as no rows. A line or file that is not its
@@ -159,11 +236,27 @@ function gateRow(member: string | null, r: GateResolutionRecord | PendingGateRec
159
236
  export async function loadQueryData(ledgers: readonly QueryLedger[]): Promise<QueryLoad> {
160
237
  const data = empty<QueryRow[]>(() => []) as QueryData;
161
238
  const malformed = empty(() => 0);
162
- for (const { member, port } of ledgers) {
239
+ for (const { member, port, ownerOfPath, snapshots } of ledgers) {
240
+ if (snapshots) {
241
+ for (const env of (await snapshots.trees()).filter((t) => !t.startsWith("_")).sort()) {
242
+ for (const file of (await snapshots.list(env)).sort()) {
243
+ if (!file.endsWith(".json")) continue;
244
+ const text = await snapshots.read(env, file);
245
+ let parsed: unknown;
246
+ try {
247
+ parsed = text === null ? null : JSON.parse(text);
248
+ } catch {
249
+ parsed = null;
250
+ }
251
+ if (isSnapshot(parsed)) snapshotRows(member, env, file, parsed, data);
252
+ }
253
+ }
254
+ }
163
255
  const trees = (await port.trees()).sort();
164
256
  for (const env of trees.filter((t) => !t.startsWith("_"))) {
165
257
  for (const file of (await port.list(env)).sort()) {
166
258
  if (file.endsWith(".json")) {
259
+ if (snapshots) continue;
167
260
  const text = await port.read(env, file);
168
261
  let parsed: unknown;
169
262
  try {
@@ -189,7 +282,7 @@ export async function loadQueryData(ledgers: readonly QueryLedger[]): Promise<Qu
189
282
  const { records, malformed: bad } = parseRunLedger(text);
190
283
  malformed.runs += bad;
191
284
  for (const r of records) {
192
- data.runs.push({ member, id: r.id, op: r.op, env: r.env, started: r.started, ended: r.ended, status: r.status, git_sha: str(r.gitSha), forge: str(r.runOrigin?.forge), run_url: str(r.runOrigin?.url), failure_code: str(r.failure?.code), failure_reason: str(r.failure?.reason), failed_phase: str(r.failure?.phase), gate: str(r.gate?.name), steward: str(r.steward), labels: json(r.labels ?? {}), outcomes: json(r.outcomes ?? {}) });
285
+ data.runs.push({ member, id: r.id, op: r.op, env: r.env, started: r.started, ended: r.ended, status: r.status, git_sha: str(r.gitSha), forge: str(r.runOrigin?.forge), run_url: str(r.runOrigin?.url), failure_code: str(r.failure?.code), failure_reason: str(r.failure?.reason), failed_phase: str(r.failure?.phase), gate: str(r.gate?.name), steward: str(r.steward), labels: json(r.labels ?? {}), outcomes: json(r.outcomes ?? {}), root_member: rootMemberOf(r.outcomes, ownerOfPath) });
193
286
  }
194
287
  }
195
288
  }
@@ -1,12 +1,16 @@
1
1
  import { describe, it, expect, vi, beforeEach } from "vitest";
2
2
  import type { LifecycleSnapshot } from "./types";
3
3
 
4
- // `replaySnapshots` reads the orphan branch through this one function, so the
5
- // stored set is the whole input surface.
4
+ // `replaySnapshots` reads the index store (#4519) through this one function,
5
+ // so the stored set is the whole input surface.
6
6
  const stored = new Map<string, string>();
7
- vi.mock("./git", () => ({
8
- readEnvironmentSnapshots: async (): Promise<Map<string, string>> => stored,
9
- }));
7
+ vi.mock("./snapshot-store", async () => {
8
+ const { fakeSnapshotStore } = await import("./snapshot-store-fake");
9
+ return {
10
+ resolveSnapshotStore: async () => fakeSnapshotStore({ keys: async () => [...stored.keys()] }),
11
+ readEnvironmentSnapshotsFrom: async (): Promise<Map<string, string>> => stored,
12
+ };
13
+ });
10
14
 
11
15
  const { replaySnapshots } = await import("./replay");
12
16
 
@@ -14,7 +14,7 @@
14
14
  * answer most questions but never all of them.
15
15
  */
16
16
 
17
- import { readEnvironmentSnapshots } from "./git";
17
+ import { readEnvironmentSnapshotsFrom, resolveSnapshotStore, type SnapshotStore } from "./snapshot-store";
18
18
  import { unqualifiedKey } from "./identity";
19
19
  import type { LiveObservation } from "../graph-ir";
20
20
  import type { LifecycleSnapshot, ObservationDepth } from "./types";
@@ -29,7 +29,7 @@ import type { LifecycleSnapshot, ObservationDepth } from "./types";
29
29
  * is shared. Nothing downstream needs to know which source it got.
30
30
  *
31
31
  * `latest` is the only ref for now. A specific commit is the natural extension
32
- * and the storage already supports it (`readSnapshotAt`), but "answer from what
32
+ * and the store already supports it (`SnapshotStore.readAt`), but "answer from what
33
33
  * is recorded" is the question worth settling first.
34
34
  */
35
35
  /**
@@ -40,9 +40,10 @@ import type { LifecycleSnapshot, ObservationDepth } from "./types";
40
40
  * failure here means the caller says the plain version of the message, never
41
41
  * that the command fails.
42
42
  */
43
- export async function hasSnapshot(environment: string): Promise<boolean> {
43
+ export async function hasSnapshot(environment: string, opts?: { store?: SnapshotStore }): Promise<boolean> {
44
44
  try {
45
- return (await readEnvironmentSnapshots(environment)).size > 0;
45
+ const store = opts?.store ?? (await resolveSnapshotStore());
46
+ return (await store.keys(environment)).length > 0;
46
47
  } catch {
47
48
  return false;
48
49
  }
@@ -52,6 +53,8 @@ export async function replaySnapshots(
52
53
  environment: string,
53
54
  ref: string,
54
55
  scopedStacks: Set<string>,
56
+ /** The index store to read (#4519). Default: the project's. */
57
+ opts?: { store?: SnapshotStore },
55
58
  ): Promise<
56
59
  | { observations: LiveObservation[]; commit: string; timestamp: string; depth: ObservationDepth }
57
60
  | { error: string; hint?: string }
@@ -62,7 +65,8 @@ export async function replaySnapshots(
62
65
  hint: "a specific snapshot commit is not wired up yet",
63
66
  };
64
67
  }
65
- const stored = await readEnvironmentSnapshots(environment);
68
+ const store = opts?.store ?? (await resolveSnapshotStore());
69
+ const stored = await readEnvironmentSnapshotsFrom(store, environment);
66
70
  if (stored.size === 0) {
67
71
  return {
68
72
  error: `No snapshots found for environment "${environment}"`,
@@ -48,9 +48,10 @@ export interface ScenarioGivenFile {
48
48
 
49
49
  /**
50
50
  * `given: snapshot("prod")` — the last snapshot recorded for that environment
51
- * on the `chant/lifecycle` orphan branch (one file per lexicon, read via
52
- * `readSnapshot`/`readEnvironmentSnapshots`, ../lifecycle/git.ts), replayed
53
- * exactly as `chant lifecycle plan` reads its own prior snapshot.
51
+ * in the project's index store (one file per lexicon, read through
52
+ * ./snapshot-store.ts, #4519), replayed exactly as `chant lifecycle plan`
53
+ * reads its own prior snapshot. With no store (`none`) a scenario names a
54
+ * checked-in fixture instead.
54
55
  */
55
56
  export interface ScenarioGivenEnv {
56
57
  readonly kind: "env";
@@ -0,0 +1,29 @@
1
+ /**
2
+ * A {@link SnapshotStore} made of the methods a test supplies, every other
3
+ * method reading as empty (#4519). It imports nothing at runtime, so a
4
+ * `vi.mock` factory can load it while the modules the real store needs are
5
+ * themselves mocked.
6
+ */
7
+ import type { SnapshotStore } from "./snapshot-store";
8
+
9
+ export function fakeSnapshotStore(parts: Partial<SnapshotStore> = {}): SnapshotStore {
10
+ return {
11
+ kind: "git-ref",
12
+ where: "the test store",
13
+ writable: true,
14
+ write: async () => ({ written: true }),
15
+ readLatest: async () => null,
16
+ readAt: async () => null,
17
+ list: async () => [],
18
+ keys: async () => [],
19
+ environments: async () => [],
20
+ writeIndex: async () => ({ written: false, reason: "the test store keeps no index" }),
21
+ listIndex: async () => [],
22
+ readIndexAt: async () => null,
23
+ readIndexLatest: async () => null,
24
+ readIndexScope: async () => null,
25
+ fetch: async () => {},
26
+ publish: async () => ({ status: "local" }),
27
+ ...parts,
28
+ };
29
+ }