@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.
- package/dist/audit/discover.d.ts.map +1 -1
- package/dist/audit/discover.js +3 -1
- package/dist/behaviour.d.ts +1 -1
- package/dist/behaviour.d.ts.map +1 -1
- package/dist/capabilities/templates.d.ts +65 -0
- package/dist/capabilities/templates.d.ts.map +1 -0
- package/dist/capabilities/templates.js +193 -0
- package/dist/capabilities/templates.json +145 -0
- package/dist/change-set-graph.d.ts +35 -3
- package/dist/change-set-graph.d.ts.map +1 -1
- package/dist/change-set-graph.js +60 -9
- package/dist/change-set.d.ts +65 -7
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +23 -12
- package/dist/ci-identity.d.ts +7 -2
- package/dist/ci-identity.d.ts.map +1 -1
- package/dist/ci-identity.js +4 -1
- package/dist/cli/commands/import-index.d.ts +52 -0
- package/dist/cli/commands/import-index.d.ts.map +1 -0
- package/dist/cli/commands/import-index.js +226 -0
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/lint.js +4 -2
- package/dist/cli/handlers/components.d.ts.map +1 -1
- package/dist/cli/handlers/components.js +11 -2
- package/dist/cli/handlers/fan-out.d.ts.map +1 -1
- package/dist/cli/handlers/fan-out.js +16 -3
- package/dist/cli/handlers/graph.d.ts.map +1 -1
- package/dist/cli/handlers/graph.js +22 -4
- package/dist/cli/handlers/index-cloud.d.ts +14 -0
- package/dist/cli/handlers/index-cloud.d.ts.map +1 -0
- package/dist/cli/handlers/index-cloud.js +22 -0
- package/dist/cli/handlers/index-diff.d.ts +18 -0
- package/dist/cli/handlers/index-diff.d.ts.map +1 -0
- package/dist/cli/handlers/index-diff.js +142 -0
- package/dist/cli/handlers/lifecycle-drift.d.ts +25 -0
- package/dist/cli/handlers/lifecycle-drift.d.ts.map +1 -0
- package/dist/cli/handlers/lifecycle-drift.js +64 -0
- package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
- package/dist/cli/handlers/lifecycle.js +188 -28
- package/dist/cli/handlers/misc.d.ts +9 -0
- package/dist/cli/handlers/misc.d.ts.map +1 -1
- package/dist/cli/handlers/misc.js +77 -0
- package/dist/cli/handlers/pr.d.ts.map +1 -1
- package/dist/cli/handlers/pr.js +17 -3
- package/dist/cli/handlers/promote.d.ts.map +1 -1
- package/dist/cli/handlers/promote.js +89 -15
- package/dist/cli/handlers/query.d.ts.map +1 -1
- package/dist/cli/handlers/query.js +28 -4
- package/dist/cli/handlers/scenario.d.ts.map +1 -1
- package/dist/cli/handlers/scenario.js +8 -7
- package/dist/cli/handlers/search.d.ts +34 -4
- package/dist/cli/handlers/search.d.ts.map +1 -1
- package/dist/cli/handlers/search.js +216 -36
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +55 -1
- package/dist/cli/mcp/lifecycle-tools.d.ts.map +1 -1
- package/dist/cli/mcp/lifecycle-tools.js +3 -2
- package/dist/cli/mcp/resource-handlers.d.ts.map +1 -1
- package/dist/cli/mcp/resource-handlers.js +4 -3
- package/dist/cli/mcp/workspace-tools.js +1 -1
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +55 -2
- package/dist/cli/registry.d.ts +19 -1
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/cloud-lister/aws.d.ts +35 -0
- package/dist/cloud-lister/aws.d.ts.map +1 -0
- package/dist/cloud-lister/aws.js +203 -0
- package/dist/cloud-lister/azure.d.ts +34 -0
- package/dist/cloud-lister/azure.d.ts.map +1 -0
- package/dist/cloud-lister/azure.js +129 -0
- package/dist/cloud-lister/common.d.ts +40 -0
- package/dist/cloud-lister/common.d.ts.map +1 -0
- package/dist/cloud-lister/common.js +83 -0
- package/dist/cloud-lister/credentials.d.ts +50 -0
- package/dist/cloud-lister/credentials.d.ts.map +1 -0
- package/dist/cloud-lister/credentials.js +86 -0
- package/dist/cloud-lister/fakes.d.ts +27 -0
- package/dist/cloud-lister/fakes.d.ts.map +1 -0
- package/dist/cloud-lister/fakes.js +50 -0
- package/dist/cloud-lister/gcp.d.ts +42 -0
- package/dist/cloud-lister/gcp.d.ts.map +1 -0
- package/dist/cloud-lister/gcp.js +143 -0
- package/dist/cloud-lister/guard.d.ts +49 -0
- package/dist/cloud-lister/guard.d.ts.map +1 -0
- package/dist/cloud-lister/guard.js +103 -0
- package/dist/cloud-lister/ids.d.ts +23 -0
- package/dist/cloud-lister/ids.d.ts.map +1 -0
- package/dist/cloud-lister/ids.js +42 -0
- package/dist/cloud-lister/index.d.ts +67 -0
- package/dist/cloud-lister/index.d.ts.map +1 -0
- package/dist/cloud-lister/index.js +102 -0
- package/dist/cloud-lister/kubernetes.d.ts +64 -0
- package/dist/cloud-lister/kubernetes.d.ts.map +1 -0
- package/dist/cloud-lister/kubernetes.js +276 -0
- package/dist/cloud-lister/markers.d.ts +31 -0
- package/dist/cloud-lister/markers.d.ts.map +1 -0
- package/dist/cloud-lister/markers.js +73 -0
- package/dist/cloud-lister/mask.d.ts +31 -0
- package/dist/cloud-lister/mask.d.ts.map +1 -0
- package/dist/cloud-lister/mask.js +74 -0
- package/dist/cloud-lister/sigv4.d.ts +29 -0
- package/dist/cloud-lister/sigv4.d.ts.map +1 -0
- package/dist/cloud-lister/sigv4.js +54 -0
- package/dist/cloud-lister/transport.d.ts +55 -0
- package/dist/cloud-lister/transport.d.ts.map +1 -0
- package/dist/cloud-lister/transport.js +86 -0
- package/dist/cloud-lister/types.d.ts +121 -0
- package/dist/cloud-lister/types.d.ts.map +1 -0
- package/dist/cloud-lister/types.js +24 -0
- package/dist/components/capability-plugin-loader.d.ts.map +1 -1
- package/dist/components/capability-plugin-loader.js +6 -0
- package/dist/components/capability-plugin.d.ts +9 -0
- package/dist/components/capability-plugin.d.ts.map +1 -1
- package/dist/components/capability.d.ts +224 -0
- package/dist/components/capability.d.ts.map +1 -1
- package/dist/components/cli-support.d.ts +21 -0
- package/dist/components/cli-support.d.ts.map +1 -1
- package/dist/components/cli-support.js +58 -14
- package/dist/components/covered-round.d.ts +173 -0
- package/dist/components/covered-round.d.ts.map +1 -0
- package/dist/components/covered-round.js +200 -0
- package/dist/components/declared-reads.d.ts +38 -0
- package/dist/components/declared-reads.d.ts.map +1 -0
- package/dist/components/declared-reads.js +131 -0
- package/dist/components/deploy-units.d.ts.map +1 -1
- package/dist/components/deploy-units.js +4 -0
- package/dist/components/driver.d.ts +42 -1
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/driver.js +74 -3
- package/dist/components/fan-out-run.d.ts +23 -1
- package/dist/components/fan-out-run.d.ts.map +1 -1
- package/dist/components/fan-out-run.js +82 -14
- package/dist/components/fan-out-support.d.ts +6 -0
- package/dist/components/fan-out-support.d.ts.map +1 -1
- package/dist/components/fan-out-support.js +4 -1
- package/dist/components/fan-out.d.ts +28 -0
- package/dist/components/fan-out.d.ts.map +1 -1
- package/dist/components/groups.d.ts +229 -0
- package/dist/components/groups.d.ts.map +1 -0
- package/dist/components/groups.js +760 -0
- package/dist/components/index.d.ts +7 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +5 -0
- package/dist/components/plan-shape-conformance.d.ts +48 -0
- package/dist/components/plan-shape-conformance.d.ts.map +1 -0
- package/dist/components/plan-shape-conformance.js +122 -0
- package/dist/components/pr-run.d.ts +62 -7
- package/dist/components/pr-run.d.ts.map +1 -1
- package/dist/components/pr-run.js +354 -53
- package/dist/components/promote-rounds.d.ts +9 -0
- package/dist/components/promote-rounds.d.ts.map +1 -1
- package/dist/components/promote-rounds.js +23 -2
- package/dist/components/promote.d.ts +17 -0
- package/dist/components/promote.d.ts.map +1 -1
- package/dist/components/promote.js +36 -6
- package/dist/components/release-gate.d.ts +23 -1
- package/dist/components/release-gate.d.ts.map +1 -1
- package/dist/components/release-gate.js +97 -33
- package/dist/components/run-groups.d.ts +58 -0
- package/dist/components/run-groups.d.ts.map +1 -0
- package/dist/components/run-groups.js +78 -0
- package/dist/components/starter-plugin.d.ts +1 -0
- package/dist/components/starter-plugin.d.ts.map +1 -1
- package/dist/components/starter-plugin.js +6 -1
- package/dist/components/verbs/index.d.ts +1 -0
- package/dist/components/verbs/index.d.ts.map +1 -1
- package/dist/components/verbs/index.js +1 -0
- package/dist/components/verbs/member-outputs.d.ts +187 -0
- package/dist/components/verbs/member-outputs.d.ts.map +1 -0
- package/dist/components/verbs/member-outputs.js +218 -0
- package/dist/components/wave-plan.d.ts +2 -0
- package/dist/components/wave-plan.d.ts.map +1 -1
- package/dist/components/wave-plan.js +4 -1
- package/dist/config.d.ts +60 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +27 -0
- package/dist/deep-observation.d.ts +1 -13
- package/dist/deep-observation.d.ts.map +1 -1
- package/dist/deep-observation.js +5 -22
- package/dist/drift-record.d.ts +542 -0
- package/dist/drift-record.d.ts.map +1 -0
- package/dist/drift-record.js +886 -0
- package/dist/engine-facts.d.ts +144 -0
- package/dist/engine-facts.d.ts.map +1 -0
- package/dist/engine-facts.js +14 -0
- package/dist/graph-ir.d.ts +153 -2
- package/dist/graph-ir.d.ts.map +1 -1
- package/dist/graph-ir.js +224 -6
- package/dist/graph-refs.d.ts +145 -0
- package/dist/graph-refs.d.ts.map +1 -1
- package/dist/graph-refs.js +305 -0
- package/dist/graph-schema/fixtures/adopt.json +15 -0
- package/dist/graph-schema/fixtures/choudoufu.engine-graph.json +169 -0
- package/dist/graph-schema/fixtures/index.json +68 -0
- package/dist/graph-schema/fixtures/plunge.engine-graph.json +158 -0
- package/dist/graph-schema/fixtures.d.ts +23 -0
- package/dist/graph-schema/fixtures.d.ts.map +1 -0
- package/dist/graph-schema/fixtures.js +246 -0
- package/dist/graph-schema/generate.d.ts +15 -0
- package/dist/graph-schema/generate.d.ts.map +1 -0
- package/dist/graph-schema/generate.js +267 -0
- package/dist/graph-schema/graph.schema.json +1387 -0
- package/dist/health.schema.json +2 -1
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/instance-nodes.d.ts +159 -0
- package/dist/instance-nodes.d.ts.map +1 -0
- package/dist/instance-nodes.js +231 -0
- package/dist/lexicon.d.ts +72 -0
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/adoption-file.d.ts +56 -0
- package/dist/lifecycle/adoption-file.d.ts.map +1 -0
- package/dist/lifecycle/adoption-file.js +123 -0
- package/dist/lifecycle/cloud-index.d.ts +186 -0
- package/dist/lifecycle/cloud-index.d.ts.map +1 -0
- package/dist/lifecycle/cloud-index.js +618 -0
- package/dist/lifecycle/derive-edges.d.ts +59 -0
- package/dist/lifecycle/derive-edges.d.ts.map +1 -0
- package/dist/lifecycle/derive-edges.js +126 -0
- package/dist/lifecycle/git.d.ts +10 -9
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lifecycle/git.js +7 -1
- package/dist/lifecycle/identity-match.d.ts +133 -0
- package/dist/lifecycle/identity-match.d.ts.map +1 -0
- package/dist/lifecycle/identity-match.js +147 -0
- package/dist/lifecycle/index-diff.d.ts +224 -0
- package/dist/lifecycle/index-diff.d.ts.map +1 -0
- package/dist/lifecycle/index-diff.js +327 -0
- package/dist/lifecycle/index-document.d.ts +130 -0
- package/dist/lifecycle/index-document.d.ts.map +1 -0
- package/dist/lifecycle/index-document.js +189 -0
- package/dist/lifecycle/index-drift.d.ts +121 -0
- package/dist/lifecycle/index-drift.d.ts.map +1 -0
- package/dist/lifecycle/index-drift.js +178 -0
- package/dist/lifecycle/index-import.d.ts +168 -0
- package/dist/lifecycle/index-import.d.ts.map +1 -0
- package/dist/lifecycle/index-import.js +515 -0
- package/dist/lifecycle/index-join.d.ts +129 -0
- package/dist/lifecycle/index-join.d.ts.map +1 -0
- package/dist/lifecycle/index-join.js +248 -0
- package/dist/lifecycle/index.d.ts +4 -0
- package/dist/lifecycle/index.d.ts.map +1 -1
- package/dist/lifecycle/index.js +4 -0
- package/dist/lifecycle/observation-baseline.d.ts +61 -21
- package/dist/lifecycle/observation-baseline.d.ts.map +1 -1
- package/dist/lifecycle/observation-baseline.js +144 -19
- package/dist/lifecycle/observe.d.ts.map +1 -1
- package/dist/lifecycle/observe.js +6 -1
- package/dist/lifecycle/query.d.ts +45 -4
- package/dist/lifecycle/query.d.ts.map +1 -1
- package/dist/lifecycle/query.js +89 -7
- package/dist/lifecycle/replay.d.ts +10 -3
- package/dist/lifecycle/replay.d.ts.map +1 -1
- package/dist/lifecycle/replay.js +10 -6
- package/dist/lifecycle/scenario.d.ts +4 -3
- package/dist/lifecycle/scenario.d.ts.map +1 -1
- package/dist/lifecycle/snapshot-store-fake.d.ts +9 -0
- package/dist/lifecycle/snapshot-store-fake.d.ts.map +1 -0
- package/dist/lifecycle/snapshot-store-fake.js +21 -0
- package/dist/lifecycle/snapshot-store-s3.d.ts +102 -0
- package/dist/lifecycle/snapshot-store-s3.d.ts.map +1 -0
- package/dist/lifecycle/snapshot-store-s3.js +254 -0
- package/dist/lifecycle/snapshot-store.d.ts +170 -0
- package/dist/lifecycle/snapshot-store.d.ts.map +1 -0
- package/dist/lifecycle/snapshot-store.js +832 -0
- package/dist/lifecycle/snapshot.d.ts +11 -0
- package/dist/lifecycle/snapshot.d.ts.map +1 -1
- package/dist/lifecycle/snapshot.js +18 -5
- package/dist/lifecycle/type-listing.d.ts +148 -0
- package/dist/lifecycle/type-listing.d.ts.map +1 -0
- package/dist/lifecycle/type-listing.js +166 -0
- package/dist/lint/component-checks.d.ts +15 -1
- package/dist/lint/component-checks.d.ts.map +1 -1
- package/dist/lint/component-checks.js +1 -0
- package/dist/lint/presets/relaxed.json +2 -1
- package/dist/lint/presets/strict.json +2 -1
- package/dist/lint/rules/__fixtures__/comp/comp008/fail/dns.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp008/fail/dns.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp008/fail/dns.component.js +13 -0
- package/dist/lint/rules/__fixtures__/comp/comp008/pass/dns.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp008/pass/dns.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp008/pass/dns.component.js +8 -0
- package/dist/lint/rules/comp/comp008-applies-signal-only-root.d.ts +33 -0
- package/dist/lint/rules/comp/comp008-applies-signal-only-root.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp008-applies-signal-only-root.js +123 -0
- package/dist/lint/rules/comp/index.d.ts +2 -1
- package/dist/lint/rules/comp/index.d.ts.map +1 -1
- package/dist/lint/rules/comp/index.js +4 -1
- package/dist/observation.d.ts +19 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +18 -1
- package/dist/op/activities/activity-contracts.d.ts +1 -1
- package/dist/op/activities/activity-contracts.js +1 -1
- package/dist/op/activities/change-set.d.ts +6 -4
- package/dist/op/activities/change-set.d.ts.map +1 -1
- package/dist/op/activities/change-set.js +4 -2
- package/dist/op/activity-failure.d.ts +27 -0
- package/dist/op/activity-failure.d.ts.map +1 -1
- package/dist/op/activity-failure.js +31 -0
- package/dist/op/index.d.ts +2 -1
- package/dist/op/index.d.ts.map +1 -1
- package/dist/op/index.js +1 -1
- package/dist/op/local-executor.d.ts +5 -1
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/local-executor.js +22 -8
- package/dist/pr-loop.d.ts +92 -3
- package/dist/pr-loop.d.ts.map +1 -1
- package/dist/pr-loop.js +62 -3
- package/dist/pulumi-urn.d.ts +101 -0
- package/dist/pulumi-urn.d.ts.map +1 -0
- package/dist/pulumi-urn.js +131 -0
- package/dist/release-floors.d.ts +23 -0
- package/dist/release-floors.d.ts.map +1 -0
- package/dist/release-floors.js +22 -0
- package/dist/sensitive-key.d.ts +23 -0
- package/dist/sensitive-key.d.ts.map +1 -0
- package/dist/sensitive-key.js +31 -0
- package/dist/wave-runtime.mjs +234 -234
- package/dist/workspace/adoption-report.d.ts +53 -0
- package/dist/workspace/adoption-report.d.ts.map +1 -0
- package/dist/workspace/adoption-report.js +76 -0
- package/dist/workspace/capabilities-contract.d.ts +7 -0
- package/dist/workspace/capabilities-contract.d.ts.map +1 -1
- package/dist/workspace/capabilities-contract.js +2 -1
- package/dist/workspace/capabilities.schema.json +98 -0
- package/dist/workspace/change-set.schema.json +42 -3
- package/dist/workspace/ci-cloud-identity.d.ts +13 -1
- package/dist/workspace/ci-cloud-identity.d.ts.map +1 -1
- package/dist/workspace/ci-cloud-identity.js +30 -1
- package/dist/workspace/compose-graph.d.ts +10 -1
- package/dist/workspace/compose-graph.d.ts.map +1 -1
- package/dist/workspace/compose-graph.js +6 -1
- package/dist/workspace/conformance/index.d.ts +1 -1
- package/dist/workspace/conformance/index.d.ts.map +1 -1
- package/dist/workspace/conformance/index.js +6 -1
- package/dist/workspace/drift-cli.d.ts +81 -0
- package/dist/workspace/drift-cli.d.ts.map +1 -0
- package/dist/workspace/drift-cli.js +317 -0
- package/dist/workspace/drift.schema.json +672 -0
- package/dist/workspace/graph-cli.d.ts +2 -0
- package/dist/workspace/graph-cli.d.ts.map +1 -1
- package/dist/workspace/graph-cli.js +3 -0
- package/dist/workspace/graph.schema.json +72 -0
- package/dist/workspace/init.d.ts +5 -1
- package/dist/workspace/init.d.ts.map +1 -1
- package/dist/workspace/init.js +55 -9
- package/dist/workspace/ledger.schema.json +1 -1
- package/dist/workspace/nested-graph.d.ts.map +1 -1
- package/dist/workspace/nested-graph.js +2 -0
- package/dist/workspace/pr-report.schema.json +76 -3
- package/dist/workspace/promote-waves.d.ts +112 -0
- package/dist/workspace/promote-waves.d.ts.map +1 -0
- package/dist/workspace/promote-waves.js +290 -0
- package/dist/workspace/promote.d.ts +84 -2
- package/dist/workspace/promote.d.ts.map +1 -1
- package/dist/workspace/promote.js +347 -61
- package/dist/workspace/reason-codes.d.ts +12 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +14 -0
- package/dist/workspace/search-contract.d.ts +3 -3
- package/dist/workspace/search-contract.d.ts.map +1 -1
- package/dist/workspace/search-contract.js +2 -0
- package/dist/workspace/search.schema.json +103 -5
- package/package.json +14 -1
- package/src/__fixtures__/drift-record/README.md +58 -0
- package/src/__fixtures__/drift-record/choudoufu-cone.ndjson +4 -0
- package/src/__fixtures__/drift-record/choudoufu-resource.ndjson +3 -0
- package/src/__fixtures__/drift-record/component-status-ledger.json +65 -0
- package/src/__fixtures__/drift-record/component-status.json +91 -0
- package/src/__fixtures__/drift-record/deep-diff.json +259 -0
- package/src/__fixtures__/drift-record/lifecycle-diff-live.json +825 -0
- package/src/__fixtures__/drift-record/live-diff.json +125 -0
- package/src/audit/discover.e2e.test.ts +14 -0
- package/src/audit/discover.ts +3 -1
- package/src/behaviour.ts +1 -1
- package/src/capabilities/templates.json +145 -0
- package/src/capabilities/templates.test.ts +212 -0
- package/src/capabilities/templates.ts +204 -0
- package/src/change-set-bundle.test.ts +83 -0
- package/src/change-set-graph.ts +80 -9
- package/src/change-set.test.ts +24 -0
- package/src/change-set.ts +77 -14
- package/src/ci-identity-targets.test.ts +23 -0
- package/src/ci-identity.ts +10 -4
- package/src/cli/commands/import-index.test.ts +117 -0
- package/src/cli/commands/import-index.ts +265 -0
- package/src/cli/commands/lint.ts +4 -2
- package/src/cli/handlers/components.test.ts +9 -0
- package/src/cli/handlers/components.ts +12 -2
- package/src/cli/handlers/fan-out.ts +17 -3
- package/src/cli/handlers/graph.test.ts +42 -0
- package/src/cli/handlers/graph.ts +26 -4
- package/src/cli/handlers/index-cloud.ts +32 -0
- package/src/cli/handlers/index-diff.test.ts +68 -0
- package/src/cli/handlers/index-diff.ts +146 -0
- package/src/cli/handlers/ledger-root-member.test.ts +161 -0
- package/src/cli/handlers/lifecycle-drift.ts +68 -0
- package/src/cli/handlers/lifecycle.test.ts +33 -11
- package/src/cli/handlers/lifecycle.ts +205 -30
- package/src/cli/handlers/misc.ts +73 -0
- package/src/cli/handlers/pr-waves-blocked.test.ts +37 -2
- package/src/cli/handlers/pr.ts +16 -3
- package/src/cli/handlers/promote.test.ts +64 -0
- package/src/cli/handlers/promote.ts +81 -6
- package/src/cli/handlers/query.ts +27 -4
- package/src/cli/handlers/run-declared-reads-cli.test.ts +187 -0
- package/src/cli/handlers/run-groups-cli.test.ts +229 -0
- package/src/cli/handlers/scenario.test.ts +13 -0
- package/src/cli/handlers/scenario.ts +8 -7
- package/src/cli/handlers/search-index.test.ts +255 -0
- package/src/cli/handlers/search-json.test.ts +1 -1
- package/src/cli/handlers/search-ownership.test.ts +194 -0
- package/src/cli/handlers/search.ts +271 -38
- package/src/cli/main.test.ts +7 -0
- package/src/cli/main.ts +56 -1
- package/src/cli/mcp/lifecycle-tools.ts +3 -2
- package/src/cli/mcp/resource-handlers.ts +4 -3
- package/src/cli/mcp/workspace-tools.ts +1 -1
- package/src/cli/parse-args.ts +40 -2
- package/src/cli/registry.ts +19 -1
- package/src/cloud-lister/aws.test.ts +202 -0
- package/src/cloud-lister/aws.ts +226 -0
- package/src/cloud-lister/azure.test.ts +132 -0
- package/src/cloud-lister/azure.ts +142 -0
- package/src/cloud-lister/common.ts +115 -0
- package/src/cloud-lister/credentials.ts +110 -0
- package/src/cloud-lister/fakes.ts +66 -0
- package/src/cloud-lister/gcp.test.ts +121 -0
- package/src/cloud-lister/gcp.ts +159 -0
- package/src/cloud-lister/guard.test.ts +198 -0
- package/src/cloud-lister/guard.ts +111 -0
- package/src/cloud-lister/ids.ts +54 -0
- package/src/cloud-lister/index.ts +134 -0
- package/src/cloud-lister/kubernetes.test.ts +160 -0
- package/src/cloud-lister/kubernetes.ts +284 -0
- package/src/cloud-lister/markers.ts +74 -0
- package/src/cloud-lister/mask.ts +77 -0
- package/src/cloud-lister/shape.test.ts +81 -0
- package/src/cloud-lister/sigv4.ts +70 -0
- package/src/cloud-lister/transport.ts +118 -0
- package/src/cloud-lister/types.ts +135 -0
- package/src/components/capability-plugin-loader.ts +4 -0
- package/src/components/capability-plugin.ts +10 -0
- package/src/components/capability.ts +238 -0
- package/src/components/cli-support.ts +70 -14
- package/src/components/covered-round.test.ts +166 -0
- package/src/components/covered-round.ts +293 -0
- package/src/components/declared-reads.test.ts +103 -0
- package/src/components/declared-reads.ts +134 -0
- package/src/components/deploy-units.ts +4 -0
- package/src/components/driver.ts +101 -4
- package/src/components/fan-out-run.ts +95 -15
- package/src/components/fan-out-support.ts +10 -1
- package/src/components/fan-out.ts +30 -0
- package/src/components/groups.test.ts +320 -0
- package/src/components/groups.ts +880 -0
- package/src/components/index.ts +59 -0
- package/src/components/plan-shape-conformance.ts +130 -0
- package/src/components/pr-env-run-bundle.test.ts +2 -0
- package/src/components/pr-run.test.ts +728 -4
- package/src/components/pr-run.ts +395 -55
- package/src/components/promote-rounds.ts +25 -2
- package/src/components/promote.ts +55 -5
- package/src/components/registry.test.ts +1 -1
- package/src/components/release-gate.ts +115 -30
- package/src/components/release-groups.test.ts +362 -0
- package/src/components/run-groups.ts +113 -0
- package/src/components/starter-plugin.ts +6 -0
- package/src/components/verbs/index.ts +1 -0
- package/src/components/verbs/member-outputs.test.ts +205 -0
- package/src/components/verbs/member-outputs.ts +308 -0
- package/src/components/wave-plan.ts +5 -2
- package/src/config.ts +44 -0
- package/src/deep-observation.ts +5 -23
- package/src/drift-record.test.ts +596 -0
- package/src/drift-record.ts +1206 -0
- package/src/engine-facts.guard.test.ts +111 -0
- package/src/engine-facts.test.ts +178 -0
- package/src/engine-facts.ts +154 -0
- package/src/gated-waves-bundle.test.ts +2 -0
- package/src/graph-ir-live.test.ts +92 -0
- package/src/graph-ir.ts +317 -7
- package/src/graph-refs.ts +416 -0
- package/src/graph-schema/fixtures/adopt.json +15 -0
- package/src/graph-schema/fixtures/choudoufu.engine-graph.json +169 -0
- package/src/graph-schema/fixtures/index.json +68 -0
- package/src/graph-schema/fixtures/plunge.engine-graph.json +158 -0
- package/src/graph-schema/fixtures.ts +267 -0
- package/src/graph-schema/generate.ts +263 -0
- package/src/graph-schema/graph-schema.test.ts +153 -0
- package/src/graph-schema/graph.schema.json +1387 -0
- package/src/health.schema.json +2 -1
- package/src/identity.ts +2 -0
- package/src/index.ts +2 -0
- package/src/instance-nodes.ts +288 -0
- package/src/lexicon.ts +76 -0
- package/src/lifecycle/__fixtures__/index-diff/20261026T120000Z-aaaaaaaaaaaa.json +149 -0
- package/src/lifecycle/__fixtures__/index-diff/20261026T130000Z-bbbbbbbbbbbb.json +127 -0
- package/src/lifecycle/adoption-file.test.ts +100 -0
- package/src/lifecycle/adoption-file.ts +154 -0
- package/src/lifecycle/cloud-index.test.ts +517 -0
- package/src/lifecycle/cloud-index.ts +736 -0
- package/src/lifecycle/derive-edges.test.ts +193 -0
- package/src/lifecycle/derive-edges.ts +182 -0
- package/src/lifecycle/git.ts +10 -4
- package/src/lifecycle/identity-match.test.ts +308 -0
- package/src/lifecycle/identity-match.ts +257 -0
- package/src/lifecycle/index-diff.test.ts +198 -0
- package/src/lifecycle/index-diff.ts +476 -0
- package/src/lifecycle/index-document.test.ts +64 -0
- package/src/lifecycle/index-document.ts +299 -0
- package/src/lifecycle/index-drift.test.ts +191 -0
- package/src/lifecycle/index-drift.ts +304 -0
- package/src/lifecycle/index-import.test.ts +255 -0
- package/src/lifecycle/index-import.ts +634 -0
- package/src/lifecycle/index-join.test.ts +250 -0
- package/src/lifecycle/index-join.ts +304 -0
- package/src/lifecycle/index-store-load-bearing.test.ts +187 -0
- package/src/lifecycle/index.ts +4 -0
- package/src/lifecycle/member-ledger.test.ts +25 -7
- package/src/lifecycle/observation-baseline.test.ts +72 -1
- package/src/lifecycle/observation-baseline.ts +190 -27
- package/src/lifecycle/observe.ts +6 -1
- package/src/lifecycle/query.test.ts +69 -1
- package/src/lifecycle/query.ts +103 -10
- package/src/lifecycle/replay.test.ts +9 -5
- package/src/lifecycle/replay.ts +9 -5
- package/src/lifecycle/scenario.ts +4 -3
- package/src/lifecycle/snapshot-store-fake.ts +29 -0
- package/src/lifecycle/snapshot-store-s3.ts +316 -0
- package/src/lifecycle/snapshot-store.test.ts +385 -0
- package/src/lifecycle/snapshot-store.ts +981 -0
- package/src/lifecycle/snapshot.test.ts +13 -0
- package/src/lifecycle/snapshot.ts +23 -6
- package/src/lifecycle/type-listing.test.ts +166 -0
- package/src/lifecycle/type-listing.ts +309 -0
- package/src/lint/component-checks.ts +17 -1
- package/src/lint/config.test.ts +3 -0
- package/src/lint/presets/relaxed.json +2 -1
- package/src/lint/presets/strict.json +2 -1
- package/src/lint/rules/__fixtures__/comp/comp008/fail/dns.component.ts +15 -0
- package/src/lint/rules/__fixtures__/comp/comp008/pass/dns.component.ts +10 -0
- package/src/lint/rules/comp/comp.test.ts +2 -1
- package/src/lint/rules/comp/comp008-applies-signal-only-root.ts +121 -0
- package/src/lint/rules/comp/comp008.test.ts +77 -0
- package/src/lint/rules/comp/index.ts +4 -1
- package/src/observation-edges.test.ts +33 -0
- package/src/observation.ts +36 -1
- package/src/op/activities/activity-contracts.ts +1 -1
- package/src/op/activities/change-set.ts +8 -5
- package/src/op/activity-failure.ts +36 -0
- package/src/op/index.ts +2 -1
- package/src/op/local-executor.test.ts +80 -0
- package/src/op/local-executor.ts +27 -9
- package/src/pr-loop-bundle.test.ts +5 -2
- package/src/pr-loop.test.ts +57 -1
- package/src/pr-loop.ts +154 -6
- package/src/pulumi-urn.ts +151 -0
- package/src/release-floors.ts +22 -0
- package/src/sensitive-key.ts +34 -0
- package/src/workspace/adoption-report.test.ts +61 -0
- package/src/workspace/adoption-report.ts +103 -0
- package/src/workspace/capabilities-contract.test.ts +4 -0
- package/src/workspace/capabilities-contract.ts +9 -1
- package/src/workspace/capabilities.schema.json +98 -0
- package/src/workspace/change-set.schema.json +42 -3
- package/src/workspace/ci-cloud-identity.ts +31 -1
- package/src/workspace/compose-graph.test.ts +12 -0
- package/src/workspace/compose-graph.ts +12 -1
- package/src/workspace/conformance/conformance.e2e.test.ts +2 -1
- package/src/workspace/conformance/index.ts +6 -1
- package/src/workspace/drift-cli.test.ts +65 -0
- package/src/workspace/drift-cli.ts +365 -0
- package/src/workspace/drift.schema.json +672 -0
- package/src/workspace/graph-cli.ts +5 -0
- package/src/workspace/graph.schema.json +72 -0
- package/src/workspace/init.test.ts +38 -1
- package/src/workspace/init.ts +50 -8
- package/src/workspace/intent-gaps.test.ts +18 -2
- package/src/workspace/ledger.schema.json +1 -1
- package/src/workspace/nested-graph.ts +1 -0
- package/src/workspace/pr-report.schema.json +76 -3
- package/src/workspace/promote-waves.test.ts +296 -0
- package/src/workspace/promote-waves.ts +340 -0
- package/src/workspace/promote.test.ts +158 -4
- package/src/workspace/promote.ts +398 -57
- package/src/workspace/reason-codes.test.ts +4 -1
- package/src/workspace/reason-codes.ts +14 -0
- package/src/workspace/search-contract.ts +2 -0
- 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 {
|
|
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
|
});
|
package/src/lifecycle/query.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `chant query "<sql>"` (#4297): one read-only SQL statement over
|
|
3
|
-
*
|
|
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
|
-
/**
|
|
51
|
-
|
|
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
|
-
/**
|
|
55
|
-
|
|
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({
|
|
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
|
|
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("./
|
|
8
|
-
|
|
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
|
|
package/src/lifecycle/replay.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* answer most questions but never all of them.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import {
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
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
|
+
}
|