@intentius/chant 0.124.52 → 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 +15 -2
- 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 +215 -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/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 +34 -1
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/driver.js +66 -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 +6 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +4 -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 +41 -4
- package/dist/components/pr-run.d.ts.map +1 -1
- package/dist/components/pr-run.js +209 -39
- 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/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 +56 -1
- package/dist/pr-loop.d.ts.map +1 -1
- package/dist/pr-loop.js +51 -1
- 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 +51 -2
- 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 +14 -2
- 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 +229 -0
- package/src/components/cli-support.ts +70 -14
- 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 +89 -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 +42 -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 +516 -3
- package/src/components/pr-run.ts +231 -41
- 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/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 +43 -0
- package/src/pr-loop.ts +111 -2
- 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 +51 -2
- 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
|
@@ -25,6 +25,17 @@ import { formatError, formatWarning } from "../format";
|
|
|
25
25
|
import { adjacencyOf, walkBreadthFirst } from "../../graph-walk";
|
|
26
26
|
import type { CommandContext } from "../registry";
|
|
27
27
|
import { SEARCH_CONTRACT_VERSION, SEARCH_OUTPUT_SCHEMA_ID, type SearchErrorCode, type SearchFailure, type SearchHead } from "../../workspace/search-contract";
|
|
28
|
+
import { isNoLexiconDetected } from "../../detectLexicon";
|
|
29
|
+
import {
|
|
30
|
+
countJoins,
|
|
31
|
+
formatIndexRef,
|
|
32
|
+
indexOnlyGraph,
|
|
33
|
+
joinCell,
|
|
34
|
+
joinDeclaredToIndex,
|
|
35
|
+
parseIndexRef,
|
|
36
|
+
readIndexRef,
|
|
37
|
+
type IndexJoin,
|
|
38
|
+
} from "../../lifecycle/index-join";
|
|
28
39
|
|
|
29
40
|
/**
|
|
30
41
|
* `chant search <query> [--live --env <name>]` — answer an estate question with
|
|
@@ -38,11 +49,17 @@ import { SEARCH_CONTRACT_VERSION, SEARCH_OUTPUT_SCHEMA_ID, type SearchErrorCode,
|
|
|
38
49
|
* on a terraform resource, its type (kind:aws_instance, kind:aws_iam_)
|
|
39
50
|
* tag:<key>=<val> a Tags entry with Key=key and Value containing val
|
|
40
51
|
* attr:<name>=<val> attribute <name> equals/contains <val>
|
|
52
|
+
* id:<cloud id> physicalId or an engine cloudIds value is exactly <cloud id> (#4534)
|
|
41
53
|
* ->kind:X / ->attr:.. this node has an edge TO a node matching the right side
|
|
42
54
|
* <-kind:X / <-attr:.. this node has an edge FROM a node matching the right side
|
|
43
55
|
* ->*X, ->{n}X, ->{m,n}X the far end is any depth / n / m..n hops away (#4359)
|
|
44
56
|
* ->[via=a]X, ->[to=a]X only edges through consumer attr a / reading producer attr a
|
|
45
57
|
*
|
|
58
|
+
* `--index <ref>` (#4525) answers from an index version in the store instead
|
|
59
|
+
* of a live read: the declared rows joined to it through each lexicon's index
|
|
60
|
+
* match, each row with its verdict, or, with no project, the index alone.
|
|
61
|
+
* See ../../lifecycle/index-join.ts.
|
|
62
|
+
*
|
|
46
63
|
* The edge operators are the point of "edge-aware" search (#1139): a small
|
|
47
64
|
* model shouldn't hand-join instance→subnet→public across many results — one
|
|
48
65
|
* query does the traversal. `kind:Instance ->attr:MapPublicIpOnLaunch=true`
|
|
@@ -88,6 +105,10 @@ export async function runSearch(ctx: CommandContext): Promise<number> {
|
|
|
88
105
|
|
|
89
106
|
let ir: GraphIR;
|
|
90
107
|
let source: AnswerSource = { kind: "declared" };
|
|
108
|
+
// Each declared row's join verdict against an index version (#4525).
|
|
109
|
+
let joins: Record<string, IndexJoin> | undefined;
|
|
110
|
+
// The lexicons a capability term reads an index-only graph through.
|
|
111
|
+
let indexPlugins: readonly LexiconPlugin[] | undefined;
|
|
91
112
|
// Lexicons whose live read threw (#1263). "Nothing observed" and "could not
|
|
92
113
|
// observe" are different claims; this is what carries the second one.
|
|
93
114
|
const liveFailures: string[] = [];
|
|
@@ -113,7 +134,14 @@ export async function runSearch(ctx: CommandContext): Promise<number> {
|
|
|
113
134
|
let driftFailure = false;
|
|
114
135
|
// Why --check-snapshot had nothing to check against, for --json (#4367).
|
|
115
136
|
let driftUnavailable: string | undefined;
|
|
116
|
-
if (args.
|
|
137
|
+
if (args.index !== undefined) {
|
|
138
|
+
const answered = await indexAnswer(ctx, String(args.index), projectPath, resolve(args.src ?? config.sourceDir ?? "."), config);
|
|
139
|
+
if ("error" in answered) return refuse(answered.error);
|
|
140
|
+
ir = answered.ir;
|
|
141
|
+
source = answered.source;
|
|
142
|
+
joins = answered.joins;
|
|
143
|
+
indexPlugins = answered.plugins;
|
|
144
|
+
} else if (args.live || snapshotRef) {
|
|
117
145
|
// checkSearchArgs refused a live or snapshot read without one.
|
|
118
146
|
const environment = String(args.env);
|
|
119
147
|
// Membership via matchesDeclaredEnvironment (#1221): handles `{ name,
|
|
@@ -334,7 +362,7 @@ export async function runSearch(ctx: CommandContext): Promise<number> {
|
|
|
334
362
|
ir = enrichEffectiveTopology(ir);
|
|
335
363
|
// Capability terms (#4375) read the graph through the lexicons' mappings.
|
|
336
364
|
if (terms.some(usesCapability)) {
|
|
337
|
-
const refused = await bindCapabilities(ctx, projectPath, ir, terms);
|
|
365
|
+
const refused = await bindCapabilities(ctx, projectPath, ir, terms, indexPlugins);
|
|
338
366
|
if (refused) return refuse({ code: "query-invalid", ...refused });
|
|
339
367
|
}
|
|
340
368
|
// Resolve `kind:` terms against what is actually in this graph, before any
|
|
@@ -371,10 +399,10 @@ export async function runSearch(ctx: CommandContext): Promise<number> {
|
|
|
371
399
|
source.kind === "live" && !matches.some((n) => n.physicalId) && args.env
|
|
372
400
|
? (await hasSnapshot(String(args.env))) ? "yes" : undefined
|
|
373
401
|
: undefined;
|
|
374
|
-
const env = args.env && source.kind
|
|
375
|
-
const provenanceText = provenanceLine(matches, source, recorded, liveFailures, [...derivedUsed(terms, matches, ir), ...capabilitiesUsed(terms)]).replace(/^— /, "");
|
|
402
|
+
const env = args.env && (source.kind === "live" || source.kind === "snapshot") ? String(args.env) : undefined;
|
|
403
|
+
const provenanceText = provenanceLine(matches, source, recorded, liveFailures, [...derivedUsed(terms, matches, ir), ...capabilitiesUsed(terms)], joins).replace(/^— /, "");
|
|
376
404
|
const capNotes = capabilityNotes(terms, ir, source);
|
|
377
|
-
const plannedCreates = source.kind
|
|
405
|
+
const plannedCreates = (source.kind === "live" || source.kind === "snapshot") && liveFailures.length === 0 ? plannedCreateCount(matches) : 0;
|
|
378
406
|
const driftJson = drift
|
|
379
407
|
? searchDriftJson(drift, matches.length, driftAgainst, snapshotDepth)
|
|
380
408
|
: driftUnavailable !== undefined
|
|
@@ -402,6 +430,7 @@ export async function runSearch(ctx: CommandContext): Promise<number> {
|
|
|
402
430
|
...(capNotes.length > 0 ? { capabilities: capNotes } : {}),
|
|
403
431
|
...(args.explain ? { explain: explainData(terms, matches, ir, nodeById) } : {}),
|
|
404
432
|
...(driftJson ? { drift: driftJson } : {}),
|
|
433
|
+
...(joins ? { joins } : {}),
|
|
405
434
|
}),
|
|
406
435
|
};
|
|
407
436
|
console.log(JSON.stringify(payload));
|
|
@@ -411,6 +440,8 @@ export async function runSearch(ctx: CommandContext): Promise<number> {
|
|
|
411
440
|
}
|
|
412
441
|
if (matches.length === 0) {
|
|
413
442
|
console.log(countBy ? "(no matches) · 0 total" : "(no matches)");
|
|
443
|
+
// An index answer names the version it read, rows or not (#4525).
|
|
444
|
+
if (source.kind === "index") provenance(matches, source, undefined, [], [], joins);
|
|
414
445
|
availableAttrs(terms, ir);
|
|
415
446
|
if (args.explain) explain(terms, matches, ir, nodeById, query);
|
|
416
447
|
for (const n of liveNotes) console.error(formatWarning({ message: n }));
|
|
@@ -420,7 +451,7 @@ export async function runSearch(ctx: CommandContext): Promise<number> {
|
|
|
420
451
|
for (const line of formatCounts(countGroups(matches, countBy, hasManyTerraformRoots(ir)), countBy)) console.log(line);
|
|
421
452
|
} else {
|
|
422
453
|
for (const n of matches) {
|
|
423
|
-
console.log(formatRow(n, show));
|
|
454
|
+
console.log(formatRow(n, show, joins?.[n.id]));
|
|
424
455
|
}
|
|
425
456
|
}
|
|
426
457
|
const backed = source.kind === "declared" || matches.some((n) => n.physicalId);
|
|
@@ -430,7 +461,7 @@ export async function runSearch(ctx: CommandContext): Promise<number> {
|
|
|
430
461
|
source.kind === "live" && !matches.some((n) => n.physicalId) && args.env
|
|
431
462
|
? (await hasSnapshot(String(args.env))) ? "yes" : undefined
|
|
432
463
|
: undefined;
|
|
433
|
-
provenance(matches, source, recorded, liveFailures, [...derivedUsed(terms, matches, ir), ...capabilitiesUsed(terms)]);
|
|
464
|
+
provenance(matches, source, recorded, liveFailures, [...derivedUsed(terms, matches, ir), ...capabilitiesUsed(terms)], joins);
|
|
434
465
|
for (const c of capabilityNotes(terms, ir, source)) {
|
|
435
466
|
if (c.notEvaluated.length > 0) console.log(`— ${c.name} does not evaluate: ${c.notEvaluated.join("; ")}`);
|
|
436
467
|
}
|
|
@@ -481,7 +512,7 @@ export type SearchArgsCheck =
|
|
|
481
512
|
* `--snapshot`, or plain search's `--at`.
|
|
482
513
|
*/
|
|
483
514
|
export function checkSearchArgs(
|
|
484
|
-
args: { countBy?: string; checkLive?: boolean; checkSnapshot?: boolean; failOnDrift?: boolean; live?: boolean; env?: string },
|
|
515
|
+
args: { countBy?: string; checkLive?: boolean; checkSnapshot?: boolean; failOnDrift?: boolean; live?: boolean; env?: string; index?: string; ambient?: boolean },
|
|
485
516
|
query: string,
|
|
486
517
|
snapshot: { ref?: string; flag: string },
|
|
487
518
|
): SearchArgsCheck {
|
|
@@ -534,6 +565,22 @@ export function checkSearchArgs(
|
|
|
534
565
|
},
|
|
535
566
|
};
|
|
536
567
|
}
|
|
568
|
+
// An index version (#4525) is a third observation, so it excludes the other
|
|
569
|
+
// two, and a live read's own flags mean nothing against it.
|
|
570
|
+
if (args.index !== undefined) {
|
|
571
|
+
const other = args.live ? "--live" : snapshot.ref ? flag : args.ambient ? "--ambient" : undefined;
|
|
572
|
+
if (other) {
|
|
573
|
+
return {
|
|
574
|
+
error: {
|
|
575
|
+
code: "usage-invalid",
|
|
576
|
+
message: `chant search takes --index or ${other}, not both`,
|
|
577
|
+
hint: "--index answers from an index version in the store; --live reads the estate now; a snapshot replays a chant recording",
|
|
578
|
+
},
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
const ref = parseIndexRef(args.index);
|
|
582
|
+
if ("error" in ref) return { error: { code: "usage-invalid", message: ref.error, hint: ref.hint } };
|
|
583
|
+
}
|
|
537
584
|
if ((args.live || snapshot.ref) && !args.env) {
|
|
538
585
|
const needs = snapshot.ref ? flag : "--live";
|
|
539
586
|
return { error: { code: "usage-invalid", message: `chant search ${needs} needs an environment: ${needs} --env <name>` } };
|
|
@@ -559,6 +606,78 @@ const BUILD_ROOT_FAILED = {
|
|
|
559
606
|
hint: "fix the error above; `chant graph . --format ir` reports the same one",
|
|
560
607
|
} as const;
|
|
561
608
|
|
|
609
|
+
/** What `--index` answers over (#4525), or why it can't. */
|
|
610
|
+
type IndexAnswer =
|
|
611
|
+
| { ir: GraphIR; source: AnswerSource & { kind: "index" }; joins?: Record<string, IndexJoin>; plugins?: readonly LexiconPlugin[] }
|
|
612
|
+
| { error: { code: SearchErrorCode; message: string; hint?: string } };
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Read the index version `--index` names from the project's store and build
|
|
616
|
+
* the graph the query runs over (#4525). With a project: the declared canvas
|
|
617
|
+
* `--live` would use (per stack when the config declares stacks, so ids
|
|
618
|
+
* match), every node joined to the index through its lexicon's index match.
|
|
619
|
+
* With no project (no lexicon in a config or in source): the index alone.
|
|
620
|
+
* No cloud is read either way.
|
|
621
|
+
*/
|
|
622
|
+
async function indexAnswer(
|
|
623
|
+
ctx: CommandContext,
|
|
624
|
+
refText: string,
|
|
625
|
+
projectPath: string,
|
|
626
|
+
srcDir: string,
|
|
627
|
+
config: Awaited<ReturnType<typeof loadChantConfig>>["config"],
|
|
628
|
+
): Promise<IndexAnswer> {
|
|
629
|
+
const ref = parseIndexRef(refText);
|
|
630
|
+
if ("error" in ref) return { error: { code: "usage-invalid", message: ref.error, hint: ref.hint } };
|
|
631
|
+
const { resolveSnapshotStore } = await import("../../lifecycle/snapshot-store");
|
|
632
|
+
const store = await resolveSnapshotStore({ cwd: projectPath, config: config as unknown as { snapshots?: unknown } });
|
|
633
|
+
await store.fetch();
|
|
634
|
+
const read = await readIndexRef(store, ref);
|
|
635
|
+
if ("error" in read) return { error: { code: "index-unavailable", message: read.error, ...(read.hint ? { hint: read.hint } : {}) } };
|
|
636
|
+
const { doc } = read;
|
|
637
|
+
const { stamp } = doc;
|
|
638
|
+
const base = {
|
|
639
|
+
kind: "index" as const,
|
|
640
|
+
index: formatIndexRef(stamp.scopeKey, read.version),
|
|
641
|
+
scopeKey: stamp.scopeKey,
|
|
642
|
+
version: read.version.replace(/\.json$/, ""),
|
|
643
|
+
observedAt: stamp.observedAt,
|
|
644
|
+
...(stamp.completedAt ? { completedAt: stamp.completedAt } : {}),
|
|
645
|
+
digest: stamp.digest,
|
|
646
|
+
by: stamp.source.version ? `${stamp.source.name} ${stamp.source.version}` : stamp.source.name,
|
|
647
|
+
};
|
|
648
|
+
|
|
649
|
+
let lexicons: string[] | undefined;
|
|
650
|
+
try {
|
|
651
|
+
lexicons = await resolveProjectLexicons(projectPath);
|
|
652
|
+
} catch (err) {
|
|
653
|
+
if (!isNoLexiconDetected(err)) throw err;
|
|
654
|
+
}
|
|
655
|
+
if (!lexicons) {
|
|
656
|
+
// No project: the index is the graph. Its nodes' lexicons, where they are
|
|
657
|
+
// installed, still map capability terms onto it.
|
|
658
|
+
const named = [...new Set(doc.graph.nodes.filter((n) => !n.unmappedKind).map((n) => n.lexicon))].sort();
|
|
659
|
+
let plugins: LexiconPlugin[] = [];
|
|
660
|
+
try {
|
|
661
|
+
plugins = named.length > 0 ? await loadPlugins(named) : [];
|
|
662
|
+
} catch {
|
|
663
|
+
plugins = [];
|
|
664
|
+
}
|
|
665
|
+
return { ir: indexOnlyGraph(doc), source: { ...base, project: false }, plugins };
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
const plugins = ctx.plugins.length > 0 ? ctx.plugins : await loadPlugins(lexicons);
|
|
669
|
+
const stacks = (config.stacks ?? []).map((s) => ({ name: s.name, region: s.region, src: s.src }));
|
|
670
|
+
const declared =
|
|
671
|
+
stacks.length > 0
|
|
672
|
+
? await buildDeclaredPerStack(stacks, projectPath, (g, entities) => withLexiconEdges(g, plugins, entities))
|
|
673
|
+
: await declaredGraph(ctx, projectPath, srcDir, plugins);
|
|
674
|
+
if (!declared) return { error: BUILD_ROOT_FAILED };
|
|
675
|
+
const joined = joinDeclaredToIndex(declared, doc, plugins, {
|
|
676
|
+
regionOf: (id) => stacks.find((st) => id.startsWith(`${st.name}::`))?.region,
|
|
677
|
+
});
|
|
678
|
+
return { ir: joined.ir, source: { ...base, project: true }, joins: joined.joins };
|
|
679
|
+
}
|
|
680
|
+
|
|
562
681
|
/**
|
|
563
682
|
* The declared graph a search answers over (#4362, #4365, #4368): discovery,
|
|
564
683
|
* plus the build-root entities (a terraform root's blocks, a rendered
|
|
@@ -599,7 +718,7 @@ async function declaredGraph(
|
|
|
599
718
|
* they report on.
|
|
600
719
|
*/
|
|
601
720
|
export async function printCapabilities(
|
|
602
|
-
args: { json?: boolean; live?: boolean; env?: string; snapshot?: string; at?: string; countBy?: string; explain?: boolean; show?: string },
|
|
721
|
+
args: { json?: boolean; live?: boolean; env?: string; snapshot?: string; at?: string; index?: string; countBy?: string; explain?: boolean; show?: string },
|
|
603
722
|
query: string,
|
|
604
723
|
lexicons: string[],
|
|
605
724
|
): Promise<number> {
|
|
@@ -607,7 +726,7 @@ export async function printCapabilities(
|
|
|
607
726
|
const extra = [
|
|
608
727
|
// `args.path` is "." when no query was given.
|
|
609
728
|
...(query && query !== "." ? [`the query "${query}"`] : []),
|
|
610
|
-
...(["live", "env", "snapshot", "at", "countBy", "explain", "show"] as const)
|
|
729
|
+
...(["live", "env", "snapshot", "at", "index", "countBy", "explain", "show"] as const)
|
|
611
730
|
.filter((k) => args[k] !== undefined && args[k] !== false)
|
|
612
731
|
.map((k) => `--${k.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`)}`),
|
|
613
732
|
];
|
|
@@ -709,8 +828,9 @@ async function bindCapabilities(
|
|
|
709
828
|
projectPath: string,
|
|
710
829
|
ir: GraphIR,
|
|
711
830
|
terms: Term[],
|
|
831
|
+
given?: readonly LexiconPlugin[],
|
|
712
832
|
): Promise<{ message: string; hint?: string } | undefined> {
|
|
713
|
-
let plugins: readonly LexiconPlugin[] = ctx.plugins;
|
|
833
|
+
let plugins: readonly LexiconPlugin[] = given ?? ctx.plugins;
|
|
714
834
|
if (plugins.length === 0) {
|
|
715
835
|
try {
|
|
716
836
|
plugins = await loadPlugins(await resolveProjectLexicons(projectPath));
|
|
@@ -819,7 +939,24 @@ export type AnswerSource =
|
|
|
819
939
|
| { kind: "declared" }
|
|
820
940
|
| ({ kind: "live" } & ReadDepth)
|
|
821
941
|
/** `snapshot` is the ref asked for (`latest`), `commit` the snapshot commit it named (#4374). */
|
|
822
|
-
| { kind: "snapshot"; snapshot?: string; commit: string; timestamp: string }
|
|
942
|
+
| { kind: "snapshot"; snapshot?: string; commit: string; timestamp: string }
|
|
943
|
+
/**
|
|
944
|
+
* `--index <ref>` (#4525): the index version answered from and its stamp.
|
|
945
|
+
* `index` is the ref resolved (`<scope key>@<version>`); `by` the source
|
|
946
|
+
* that wrote it; `project` false when there was no project, so every row
|
|
947
|
+
* is an indexed node.
|
|
948
|
+
*/
|
|
949
|
+
| {
|
|
950
|
+
kind: "index";
|
|
951
|
+
index: string;
|
|
952
|
+
scopeKey: string;
|
|
953
|
+
version: string;
|
|
954
|
+
observedAt: string;
|
|
955
|
+
completedAt?: string;
|
|
956
|
+
digest: string;
|
|
957
|
+
by: string;
|
|
958
|
+
project: boolean;
|
|
959
|
+
};
|
|
823
960
|
|
|
824
961
|
|
|
825
962
|
|
|
@@ -936,7 +1073,9 @@ function provenanceLine(
|
|
|
936
1073
|
recorded?: string,
|
|
937
1074
|
liveFailures: string[] = [],
|
|
938
1075
|
derived: string[] = [],
|
|
1076
|
+
joins?: Record<string, IndexJoin>,
|
|
939
1077
|
): string {
|
|
1078
|
+
if (source.kind === "index") return indexProvenance(matches, source, joins);
|
|
940
1079
|
const line = provenanceBase(matches, source, recorded, liveFailures, derived);
|
|
941
1080
|
// The plan read fell back (#4384): say to what, on whichever line this is.
|
|
942
1081
|
return source.kind === "live" ? line + fellBackText(source) : line;
|
|
@@ -950,6 +1089,23 @@ function fellBackText(source: ReadDepth): string {
|
|
|
950
1089
|
return ` · the plan read fell back to ${to}`;
|
|
951
1090
|
}
|
|
952
1091
|
|
|
1092
|
+
/**
|
|
1093
|
+
* The provenance line of an `--index` answer (#4525): the version read and
|
|
1094
|
+
* when, then how the declared rows joined, every verdict counted, so a row
|
|
1095
|
+
* that did not bind is never read as one that did.
|
|
1096
|
+
*/
|
|
1097
|
+
function indexProvenance(matches: IRNode[], source: AnswerSource & { kind: "index" }, joins?: Record<string, IndexJoin>): string {
|
|
1098
|
+
const taken = `taken ${source.observedAt}`;
|
|
1099
|
+
if (!source.project) {
|
|
1100
|
+
return `— index only, no project · ${source.index} ${taken} by ${source.by} · ${matches.length} ${matches.length === 1 ? "row" : "rows"}`;
|
|
1101
|
+
}
|
|
1102
|
+
const counts = countJoins(joins ?? {}, matches.map((n) => n.id));
|
|
1103
|
+
const rest = (["absent", "not-observed", "no-binding", "ambiguous"] as const)
|
|
1104
|
+
.filter((v) => counts[v] > 0)
|
|
1105
|
+
.map((v) => `${v === "not-observed" ? "not observed" : v} ${counts[v]}`);
|
|
1106
|
+
return `— observed from index ${source.index} ${taken} · bound ${counts.bound}/${matches.length}${rest.length > 0 ? ` · ${rest.join(" · ")}` : ""}`;
|
|
1107
|
+
}
|
|
1108
|
+
|
|
953
1109
|
function provenanceBase(
|
|
954
1110
|
matches: IRNode[],
|
|
955
1111
|
source: AnswerSource,
|
|
@@ -963,6 +1119,7 @@ function provenanceBase(
|
|
|
963
1119
|
const from = derived.length > 0 ? ` · ${derived.join(", ")} derived from declared references` : "";
|
|
964
1120
|
return `— declared only · no observation · physical ids unavailable${from}`;
|
|
965
1121
|
}
|
|
1122
|
+
if (source.kind === "index") return indexProvenance(matches, source);
|
|
966
1123
|
const bound = matches.filter((n) => n.physicalId).length;
|
|
967
1124
|
const what = source.kind === "live" ? "live read" : "snapshot";
|
|
968
1125
|
if (liveFailures.length > 0) {
|
|
@@ -1031,8 +1188,9 @@ function provenance(
|
|
|
1031
1188
|
recorded?: string,
|
|
1032
1189
|
liveFailures: string[] = [],
|
|
1033
1190
|
derived: string[] = [],
|
|
1191
|
+
joins?: Record<string, IndexJoin>,
|
|
1034
1192
|
): void {
|
|
1035
|
-
console.log(provenanceLine(matches, source, recorded, liveFailures, derived));
|
|
1193
|
+
console.log(provenanceLine(matches, source, recorded, liveFailures, derived, joins));
|
|
1036
1194
|
}
|
|
1037
1195
|
|
|
1038
1196
|
/** Union `LiveObservation.resources` across lexicons into one name-keyed map. */
|
|
@@ -1321,7 +1479,7 @@ function describeTerm(t: Term): string {
|
|
|
1321
1479
|
function leafText(x: Term): string {
|
|
1322
1480
|
if (x.kind === "cap") return `cap:${x.a}`;
|
|
1323
1481
|
return x.kind === "kind" ? `kind:${x.a}` : x.kind === "attr" ? `attr:${x.a}${x.b !== undefined ? "=" + x.b : ""}`
|
|
1324
|
-
: x.kind === "tag" ? `tag:${x.a}${x.b !== undefined ? "=" + x.b : ""}` : `"${x.a}"`;
|
|
1482
|
+
: x.kind === "tag" ? `tag:${x.a}${x.b !== undefined ? "=" + x.b : ""}` : x.kind === "id" ? `id:${x.a}` : `"${x.a}"`;
|
|
1325
1483
|
}
|
|
1326
1484
|
|
|
1327
1485
|
/**
|
|
@@ -1380,6 +1538,8 @@ export interface SearchJson {
|
|
|
1380
1538
|
unobserved?: string;
|
|
1381
1539
|
show?: Record<string, unknown>;
|
|
1382
1540
|
paths: { term: string; dir: "out" | "in"; hops: PathHop[]; because?: { capability: string; id: string; hops: PathHop[] }[] }[];
|
|
1541
|
+
/** `--index` with a project (#4525): how the declared row joined to the index version. */
|
|
1542
|
+
join?: IndexJoin;
|
|
1383
1543
|
}[];
|
|
1384
1544
|
provenance?: string;
|
|
1385
1545
|
/** Present when every match is a planned create (#4372): how many. See the schema. */
|
|
@@ -1446,6 +1606,7 @@ function searchJson(
|
|
|
1446
1606
|
capabilities?: SearchJson["capabilities"];
|
|
1447
1607
|
explain?: ReturnType<typeof explainData>;
|
|
1448
1608
|
drift?: SearchDriftJson;
|
|
1609
|
+
joins?: Record<string, IndexJoin>;
|
|
1449
1610
|
} = {},
|
|
1450
1611
|
): SearchJson {
|
|
1451
1612
|
const show = extra.show ?? [];
|
|
@@ -1468,6 +1629,7 @@ function searchJson(
|
|
|
1468
1629
|
hops: p.hops,
|
|
1469
1630
|
...(p.because ? { because: p.because } : {}),
|
|
1470
1631
|
})),
|
|
1632
|
+
...(extra.joins?.[n.id] ? { join: extra.joins[n.id] } : {}),
|
|
1471
1633
|
};
|
|
1472
1634
|
}),
|
|
1473
1635
|
...(extra.provenance !== undefined ? { provenance: extra.provenance } : {}),
|
|
@@ -1496,7 +1658,7 @@ function termText(t: Term): string {
|
|
|
1496
1658
|
}
|
|
1497
1659
|
|
|
1498
1660
|
export interface Term {
|
|
1499
|
-
kind: "word" | "kind" | "tag" | "attr" | "edge" | "cap";
|
|
1661
|
+
kind: "word" | "kind" | "tag" | "attr" | "edge" | "cap" | "id";
|
|
1500
1662
|
/** `!term` — the node must NOT satisfy this (#1280). */
|
|
1501
1663
|
negated?: boolean;
|
|
1502
1664
|
a: string;
|
|
@@ -1602,25 +1764,64 @@ function displayKind(n: IRNode): string | undefined {
|
|
|
1602
1764
|
return terraformType(n) ?? n.kind;
|
|
1603
1765
|
}
|
|
1604
1766
|
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1767
|
+
/**
|
|
1768
|
+
* The leaf prefixes the grammar reads (`kind:`, `attr:`, `tag:`, `id:`, `cap:`),
|
|
1769
|
+
* each with its parser. A new prefix is one entry here, one `Term` kind, and
|
|
1770
|
+
* its case in {@link matchTerm}; the unknown-prefix refusal lists the
|
|
1771
|
+
* entries marked `listed`, in this order.
|
|
1772
|
+
*/
|
|
1773
|
+
interface LeafPrefix {
|
|
1774
|
+
prefix: string;
|
|
1775
|
+
/** Named in the unknown-prefix hint. */
|
|
1776
|
+
listed: boolean;
|
|
1777
|
+
/** `rest` is what follows the colon; `tok` the whole token, for messages. */
|
|
1778
|
+
parse(rest: string, tok: string): Term;
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1781
|
+
/** `name` or `name=value` after a prefix. */
|
|
1782
|
+
function keyValueLeaf(kind: "kind" | "tag" | "attr"): LeafPrefix["parse"] {
|
|
1783
|
+
return (rest) => {
|
|
1620
1784
|
const eq = rest.indexOf("=");
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1785
|
+
return eq >= 0 ? { kind, a: rest.slice(0, eq), b: rest.slice(eq + 1) } : { kind, a: rest };
|
|
1786
|
+
};
|
|
1787
|
+
}
|
|
1788
|
+
|
|
1789
|
+
const LEAF_PREFIXES: readonly LeafPrefix[] = [
|
|
1790
|
+
{ prefix: "kind", listed: true, parse: keyValueLeaf("kind") },
|
|
1791
|
+
{ prefix: "attr", listed: true, parse: keyValueLeaf("attr") },
|
|
1792
|
+
{ prefix: "tag", listed: true, parse: keyValueLeaf("tag") },
|
|
1793
|
+
{
|
|
1794
|
+
// `id:<cloud id>` (#4534, behold#906 Q3): the whole rest is the id, colons
|
|
1795
|
+
// and `=` included, since an ARN has both.
|
|
1796
|
+
prefix: "id",
|
|
1797
|
+
listed: true,
|
|
1798
|
+
parse: (rest, tok) => {
|
|
1799
|
+
if (rest === "") {
|
|
1800
|
+
throw new QueryError(`"${tok}" needs a cloud id`, "name the id exactly as the cloud prints it: id:i-0abc123, id:arn:aws:s3:::my-bucket");
|
|
1801
|
+
}
|
|
1802
|
+
return { kind: "id", a: rest };
|
|
1803
|
+
},
|
|
1804
|
+
},
|
|
1805
|
+
{
|
|
1806
|
+
prefix: "cap",
|
|
1807
|
+
listed: false,
|
|
1808
|
+
parse: (rest, tok) => {
|
|
1809
|
+
if (!parseCapabilityCall(rest)) {
|
|
1810
|
+
throw new QueryError(
|
|
1811
|
+
`"${tok}" is not a capability term`,
|
|
1812
|
+
"name a capability, with arguments in parentheses when it takes any: cap:internet-reachable, cap:open-ingress(22); chant search --capabilities lists them",
|
|
1813
|
+
);
|
|
1814
|
+
}
|
|
1815
|
+
return { kind: "cap", a: rest };
|
|
1816
|
+
},
|
|
1817
|
+
},
|
|
1818
|
+
];
|
|
1819
|
+
|
|
1820
|
+
function parseLeaf(tok: string): Term {
|
|
1821
|
+
// A prefix is matched case-insensitively, as it always was.
|
|
1822
|
+
const prefixed = /^([A-Za-z][A-Za-z0-9_]*):(.*)$/.exec(tok);
|
|
1823
|
+
const known = prefixed ? LEAF_PREFIXES.find((p) => p.prefix === prefixed[1].toLowerCase()) : undefined;
|
|
1824
|
+
if (prefixed && known) return known.parse(prefixed[2], tok);
|
|
1624
1825
|
// `name:value` with a prefix the grammar does not have. This parsed as a
|
|
1625
1826
|
// free-text word and matched nothing, which is the worst available outcome:
|
|
1626
1827
|
// an agent looking for SSH reachability wrote
|
|
@@ -1635,9 +1836,10 @@ function parseLeaf(tok: string): Term {
|
|
|
1635
1836
|
if (bad) {
|
|
1636
1837
|
const name = bad[1];
|
|
1637
1838
|
const value = tok.slice(name.length + 1);
|
|
1839
|
+
const prefixes = LEAF_PREFIXES.filter((p) => p.listed).map((p) => `${p.prefix}:`).join(", ");
|
|
1638
1840
|
throw new QueryError(
|
|
1639
1841
|
`"${tok}" is not a term — there is no "${name}:" prefix`,
|
|
1640
|
-
`for an attribute, say attr:${name}=${value || "<value>"}; the prefixes are
|
|
1842
|
+
`for an attribute, say attr:${name}=${value || "<value>"}; the prefixes are ${prefixes}, and ->/<- for edges`,
|
|
1641
1843
|
);
|
|
1642
1844
|
}
|
|
1643
1845
|
return { kind: "word", a: tok };
|
|
@@ -1825,9 +2027,15 @@ function matchTerm(n: IRNode, t: Term, ir?: GraphIR, byId?: Map<string, IRNode>)
|
|
|
1825
2027
|
const val = attrString((attrs as Record<string, unknown>)[t.a]);
|
|
1826
2028
|
return t.b === undefined ? t.a in attrs : val.toLowerCase().includes(t.b.toLowerCase());
|
|
1827
2029
|
}
|
|
2030
|
+
if (t.kind === "id") return hasCloudId(n, t.a);
|
|
1828
2031
|
if (t.kind === "tag") {
|
|
1829
2032
|
const tags = (attrs as Record<string, unknown>)["Tags"];
|
|
1830
|
-
if (!Array.isArray(tags))
|
|
2033
|
+
if (!Array.isArray(tags)) {
|
|
2034
|
+
// An indexed node keeps its tags as a map (#4521), not a Tags list.
|
|
2035
|
+
return Object.entries(n.tags ?? {}).some(
|
|
2036
|
+
([key, val]) => key.toLowerCase() === t.a.toLowerCase() && (t.b === undefined || String(val).toLowerCase().includes(t.b.toLowerCase())),
|
|
2037
|
+
);
|
|
2038
|
+
}
|
|
1831
2039
|
return tags.some((tag) => {
|
|
1832
2040
|
const key = attrString((tag as Record<string, unknown>)?.Key);
|
|
1833
2041
|
const val = attrString((tag as Record<string, unknown>)?.Value);
|
|
@@ -1844,6 +2052,18 @@ function matchTerm(n: IRNode, t: Term, ir?: GraphIR, byId?: Map<string, IRNode>)
|
|
|
1844
2052
|
return hay.includes(t.a.toLowerCase());
|
|
1845
2053
|
}
|
|
1846
2054
|
|
|
2055
|
+
/**
|
|
2056
|
+
* Whether a node carries `id` as one of its cloud ids (#4534): its observed
|
|
2057
|
+
* `physicalId`, or any value in its engine facts' `cloudIds` (an ARN, an
|
|
2058
|
+
* import id, a self-link). The match is exact, case included: a cloud id is
|
|
2059
|
+
* an identifier, and a substring of one names another object. A bare word
|
|
2060
|
+
* never reads either field.
|
|
2061
|
+
*/
|
|
2062
|
+
function hasCloudId(n: IRNode, id: string): boolean {
|
|
2063
|
+
if (n.physicalId === id) return true;
|
|
2064
|
+
return (n.facts?.cloudIds ?? []).some((c) => c.value === id);
|
|
2065
|
+
}
|
|
2066
|
+
|
|
1847
2067
|
/**
|
|
1848
2068
|
* One edge on the path a match was reached by (#4359), in walk order from the
|
|
1849
2069
|
* match outward. `from` and `to` keep the edge's own direction (`from` holds
|
|
@@ -1918,7 +2138,15 @@ function findPath(n: IRNode, t: Term, ir: GraphIR, byId: Map<string, IRNode>): P
|
|
|
1918
2138
|
return found ? found.hops : null;
|
|
1919
2139
|
}
|
|
1920
2140
|
|
|
2141
|
+
/**
|
|
2142
|
+
* A cloud-listed node's path-style id (behold#1025 Q2,
|
|
2143
|
+
* `<substrate>/<scopeId>/<location>/<listedType>/<nativeId>`), printed whole:
|
|
2144
|
+
* its listed type holds `::`, which is not a stack qualification.
|
|
2145
|
+
*/
|
|
2146
|
+
const INDEX_NODE_ID = /^(aws|azure|gcp|kubernetes)\/[^/]+\/[^/]+\/[^/]+\/./;
|
|
2147
|
+
|
|
1921
2148
|
function bareId(id: string): string {
|
|
2149
|
+
if (INDEX_NODE_ID.test(id)) return id;
|
|
1922
2150
|
return id.includes("::") ? id.slice(id.lastIndexOf("::") + 2) : id;
|
|
1923
2151
|
}
|
|
1924
2152
|
|
|
@@ -2044,16 +2272,21 @@ function formatHops(hops: PathHop[], start: string): string {
|
|
|
2044
2272
|
.join("; ");
|
|
2045
2273
|
}
|
|
2046
2274
|
|
|
2047
|
-
function formatRow(n: IRNode, show: string[]): string {
|
|
2275
|
+
function formatRow(n: IRNode, show: string[], join?: IndexJoin): string {
|
|
2048
2276
|
const attrs = (n.attrs ?? {}) as Record<string, unknown>;
|
|
2049
2277
|
// Display the bare logical id, not the `${stack}::` qualification (#1162).
|
|
2050
|
-
const displayId =
|
|
2278
|
+
const displayId = bareId(n.id);
|
|
2051
2279
|
// A terraform resource shows its type (#4366); its IR kind is `Terraform::Resource` for all of them.
|
|
2052
2280
|
const parts: string[] = [displayId, displayKind(n) ?? ""];
|
|
2053
2281
|
// Prefer the node-level live physicalId (set by the overlay), then attrs;
|
|
2054
2282
|
// skip source-mode AttrRef placeholders (objects).
|
|
2055
2283
|
const physical = (n as { physicalId?: unknown }).physicalId ?? attrs["physicalId"] ?? attrs["InstanceId"] ?? attrs["Id"];
|
|
2056
|
-
|
|
2284
|
+
// A row joined to an index (#4525) that did not bind says which verdict it
|
|
2285
|
+
// got where the physical id would go: a declared InstanceId is not one the
|
|
2286
|
+
// index confirmed.
|
|
2287
|
+
const cell = join ? joinCell(join) : undefined;
|
|
2288
|
+
if (cell) parts.push(cell);
|
|
2289
|
+
else if (physical != null && typeof physical !== "object") parts.push(String(physical));
|
|
2057
2290
|
// A row nobody could read says so where its physical id would go (#1263). A
|
|
2058
2291
|
// blank there reads as "declared, not provisioned", which the read never
|
|
2059
2292
|
// established; the reason is the tri-state's (#1089).
|
package/src/cli/main.test.ts
CHANGED
|
@@ -28,6 +28,12 @@ describe("parseArgs", () => {
|
|
|
28
28
|
expect(parseArgs(["import", "--from", "prod", "--skip-undeclarable"]).skipUndeclarable).toBe(true);
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
+
test("import --index takes a selection: --type, --name, repeatable --tag, --select, --all (#4524)", () => {
|
|
32
|
+
const args = parseArgs(["import", "--index", "i.json", "--type", "AWS::S3::Bucket,AWS::IAM::Role", "--tag", "team=a", "--tag", "env=prod", "--select", "ids.json", "--all"]);
|
|
33
|
+
expect(args).toMatchObject({ command: "import", index: "i.json", selectType: "AWS::S3::Bucket,AWS::IAM::Role", selectTags: ["team=a", "env=prod"], selectAddress: "ids.json", all: true });
|
|
34
|
+
expect(() => parseArgs(["import", "--index", "i.json", "--tag", "team"])).toThrow(/--tag needs key=value/);
|
|
35
|
+
});
|
|
36
|
+
|
|
31
37
|
test("--fold and --no-fold set the tri-state fold option (#1134)", () => {
|
|
32
38
|
expect(parseArgs(["build", "src"]).fold).toBeUndefined();
|
|
33
39
|
expect(parseArgs(["build", "src", "--fold"]).fold).toBe(true);
|
|
@@ -851,6 +857,7 @@ describe("workspace init and ls (#2534)", () => {
|
|
|
851
857
|
"workspace box",
|
|
852
858
|
"workspace build",
|
|
853
859
|
"workspace check",
|
|
860
|
+
"workspace drift",
|
|
854
861
|
"workspace evidence",
|
|
855
862
|
"workspace exit",
|
|
856
863
|
"workspace export",
|