@intentius/chant 0.102.0 → 0.104.1
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/core.d.ts +2 -0
- package/dist/audit/core.d.ts.map +1 -1
- package/dist/audit/discover.d.ts.map +1 -1
- package/dist/change-set.d.ts +232 -0
- package/dist/change-set.d.ts.map +1 -0
- package/dist/cli/commands/audit.d.ts +7 -0
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/change-set.d.ts +11 -0
- package/dist/cli/handlers/change-set.d.ts.map +1 -0
- package/dist/cli/handlers/fan-out.d.ts +33 -0
- package/dist/cli/handlers/fan-out.d.ts.map +1 -1
- package/dist/cli/handlers/operator.d.ts +7 -0
- package/dist/cli/handlers/operator.d.ts.map +1 -1
- package/dist/cli/handlers/pr.d.ts +31 -0
- package/dist/cli/handlers/pr.d.ts.map +1 -0
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/mcp/op-tools.d.ts.map +1 -1
- package/dist/cli/mcp/workspace-tools.d.ts +3 -2
- package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +63 -1
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/components/auto-release.d.ts +16 -0
- package/dist/components/auto-release.d.ts.map +1 -1
- package/dist/components/capability.d.ts +53 -0
- package/dist/components/capability.d.ts.map +1 -1
- package/dist/components/changed-files.d.ts +31 -0
- package/dist/components/changed-files.d.ts.map +1 -0
- package/dist/components/cli-support.d.ts +9 -1
- package/dist/components/cli-support.d.ts.map +1 -1
- package/dist/components/component.d.ts +24 -0
- package/dist/components/component.d.ts.map +1 -1
- package/dist/components/deploy-units.d.ts.map +1 -1
- package/dist/components/driver.d.ts +13 -0
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/fan-out-output.d.ts +6 -0
- package/dist/components/fan-out-output.d.ts.map +1 -1
- package/dist/components/fan-out-record.d.ts +41 -0
- package/dist/components/fan-out-record.d.ts.map +1 -0
- package/dist/components/fan-out-run.d.ts +65 -0
- package/dist/components/fan-out-run.d.ts.map +1 -1
- package/dist/components/fan-out-support.d.ts +2 -0
- package/dist/components/fan-out-support.d.ts.map +1 -1
- package/dist/components/fan-out.d.ts +6 -0
- package/dist/components/fan-out.d.ts.map +1 -1
- package/dist/components/gated-wave-pipeline.d.ts +50 -0
- package/dist/components/gated-wave-pipeline.d.ts.map +1 -0
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/layers.d.ts +25 -0
- package/dist/components/layers.d.ts.map +1 -0
- package/dist/components/pr-pipeline.d.ts +61 -0
- package/dist/components/pr-pipeline.d.ts.map +1 -0
- package/dist/components/pr-run.d.ts +119 -0
- package/dist/components/pr-run.d.ts.map +1 -0
- package/dist/components/promote.d.ts.map +1 -1
- package/dist/components/verbs/shell.d.ts.map +1 -1
- package/dist/components/wave-plan.d.ts +49 -0
- package/dist/components/wave-plan.d.ts.map +1 -0
- package/dist/gated-waves.d.ts +147 -0
- package/dist/gated-waves.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/lexicon.d.ts +48 -0
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.d.ts +7 -0
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/git.d.ts +46 -1
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lint/post-synth.d.ts +18 -0
- package/dist/lint/post-synth.d.ts.map +1 -1
- package/dist/op/activities/activity-contracts.d.ts +126 -0
- package/dist/op/activities/activity-contracts.d.ts.map +1 -1
- package/dist/op/activities/change-set.d.ts +62 -0
- package/dist/op/activities/change-set.d.ts.map +1 -0
- package/dist/op/activities/decide.d.ts +2 -0
- package/dist/op/activities/decide.d.ts.map +1 -1
- package/dist/op/activities/factory.d.ts +137 -0
- package/dist/op/activities/factory.d.ts.map +1 -0
- package/dist/op/activities/index.d.ts +4 -0
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/activity-contract.d.ts.map +1 -1
- package/dist/op/builders.d.ts +11 -0
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/decide-backend.d.ts +5 -1
- package/dist/op/decide-backend.d.ts.map +1 -1
- package/dist/op/decide-read-inputs.d.ts +4 -2
- package/dist/op/decide-read-inputs.d.ts.map +1 -1
- package/dist/op/factory.d.ts +83 -0
- package/dist/op/factory.d.ts.map +1 -0
- package/dist/op/index.d.ts +4 -1
- package/dist/op/index.d.ts.map +1 -1
- package/dist/op/op-ir.d.ts +2 -0
- package/dist/op/op-ir.d.ts.map +1 -1
- package/dist/op/op-verb-class.d.ts.map +1 -1
- package/dist/op/types.d.ts +8 -0
- package/dist/op/types.d.ts.map +1 -1
- package/dist/op/work-lease-run.d.ts.map +1 -1
- package/dist/plan-summary.d.ts +207 -0
- package/dist/plan-summary.d.ts.map +1 -0
- package/dist/pr-forge.d.ts +105 -0
- package/dist/pr-forge.d.ts.map +1 -0
- package/dist/pr-loop.d.ts +178 -0
- package/dist/pr-loop.d.ts.map +1 -0
- package/dist/telemetry-attribution.d.ts +31 -0
- package/dist/telemetry-attribution.d.ts.map +1 -1
- package/dist/terraform/hcl2json.d.ts +45 -0
- package/dist/terraform/hcl2json.d.ts.map +1 -0
- package/dist/terraform/parse.d.ts +4 -40
- package/dist/terraform/parse.d.ts.map +1 -1
- package/dist/vendor/js-yaml-load.d.ts +56 -0
- package/dist/vendor/js-yaml-load.d.ts.map +1 -0
- package/dist/workspace/box-cli.d.ts +12 -0
- package/dist/workspace/box-cli.d.ts.map +1 -0
- package/dist/workspace/box-factory.d.ts +27 -3
- package/dist/workspace/box-factory.d.ts.map +1 -1
- package/dist/workspace/box-listing.d.ts +85 -0
- package/dist/workspace/box-listing.d.ts.map +1 -0
- package/dist/workspace/box-publish.d.ts +147 -0
- package/dist/workspace/box-publish.d.ts.map +1 -0
- package/dist/workspace/broker-protocol.d.ts +190 -0
- package/dist/workspace/broker-protocol.d.ts.map +1 -0
- package/dist/workspace/checks.d.ts.map +1 -1
- package/dist/workspace/composites.d.ts +2 -2
- package/dist/workspace/composites.d.ts.map +1 -1
- package/dist/workspace/conformance/__fixtures__/reference-broker.d.ts +17 -0
- package/dist/workspace/conformance/__fixtures__/reference-broker.d.ts.map +1 -0
- package/dist/workspace/conformance/broker.d.ts +202 -0
- package/dist/workspace/conformance/broker.d.ts.map +1 -0
- package/dist/workspace/conformance/index.d.ts +2 -1
- package/dist/workspace/conformance/index.d.ts.map +1 -1
- package/dist/workspace/conformance/vitest.d.ts +9 -2
- package/dist/workspace/conformance/vitest.d.ts.map +1 -1
- package/dist/workspace/conformance/writer.d.ts +108 -14
- package/dist/workspace/conformance/writer.d.ts.map +1 -1
- package/dist/workspace/decide.d.ts +126 -12
- package/dist/workspace/decide.d.ts.map +1 -1
- package/dist/workspace/decision-points.schema.json +11 -4
- package/dist/workspace/declaration.d.ts +65 -0
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.schema.json +153 -4
- package/dist/workspace/environments.d.ts +36 -10
- package/dist/workspace/environments.d.ts.map +1 -1
- package/dist/workspace/factory-rules.d.ts +180 -0
- package/dist/workspace/factory-rules.d.ts.map +1 -0
- package/dist/workspace/init.d.ts +21 -0
- package/dist/workspace/init.d.ts.map +1 -1
- package/dist/workspace/intent-cli.d.ts +1 -1
- package/dist/workspace/intent-cli.d.ts.map +1 -1
- package/dist/workspace/intent-record.d.ts +28 -1
- package/dist/workspace/intent-record.d.ts.map +1 -1
- package/dist/workspace/intent.d.ts +102 -5
- package/dist/workspace/intent.d.ts.map +1 -1
- package/dist/workspace/json-edit.d.ts +24 -0
- package/dist/workspace/json-edit.d.ts.map +1 -0
- package/dist/workspace/jsonc.d.ts +11 -0
- package/dist/workspace/jsonc.d.ts.map +1 -1
- package/dist/workspace/kinds.d.ts +48 -0
- package/dist/workspace/kinds.d.ts.map +1 -1
- package/dist/workspace/lexicon-symbols.d.ts +29 -0
- package/dist/workspace/lexicon-symbols.d.ts.map +1 -0
- package/dist/workspace/lineage-upgrade.d.ts +31 -2
- package/dist/workspace/lineage-upgrade.d.ts.map +1 -1
- package/dist/workspace/point-answer.schema.json +42 -2
- package/dist/workspace/points-cli.d.ts +10 -3
- package/dist/workspace/points-cli.d.ts.map +1 -1
- package/dist/workspace/points.d.ts +66 -5
- package/dist/workspace/points.d.ts.map +1 -1
- package/dist/workspace/reason-codes.d.ts +33 -4
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/record-sessions.d.ts +5 -7
- package/dist/workspace/record-sessions.d.ts.map +1 -1
- package/dist/workspace/records-cli.d.ts +7 -0
- package/dist/workspace/records-cli.d.ts.map +1 -1
- package/dist/workspace/records-close.d.ts +7 -3
- package/dist/workspace/records-close.d.ts.map +1 -1
- package/dist/workspace/records-write.d.ts +66 -6
- package/dist/workspace/records-write.d.ts.map +1 -1
- package/dist/workspace/records.d.ts +28 -9
- package/dist/workspace/records.d.ts.map +1 -1
- package/dist/workspace/runs-cli.d.ts +138 -6
- package/dist/workspace/runs-cli.d.ts.map +1 -1
- package/dist/workspace/runs.d.ts +132 -11
- package/dist/workspace/runs.d.ts.map +1 -1
- package/dist/workspace/session-kinds.d.ts +1 -1
- package/dist/workspace/session-kinds.d.ts.map +1 -1
- package/dist/workspace/squash.d.ts +80 -0
- package/dist/workspace/squash.d.ts.map +1 -0
- package/dist/workspace/status-gates.d.ts +2 -0
- package/dist/workspace/status-gates.d.ts.map +1 -1
- package/dist/workspace/status.d.ts +54 -0
- package/dist/workspace/status.d.ts.map +1 -1
- package/dist/workspace/symbols.d.ts +16 -5
- package/dist/workspace/symbols.d.ts.map +1 -1
- package/dist/workspace/trust/run-commits.d.ts +46 -0
- package/dist/workspace/trust/run-commits.d.ts.map +1 -0
- package/dist/workspace/trust/run-statement.d.ts +128 -0
- package/dist/workspace/trust/run-statement.d.ts.map +1 -0
- package/dist/workspace/trust/seal.d.ts +6 -1
- package/dist/workspace/trust/seal.d.ts.map +1 -1
- package/dist/workspace/trust/verify-cli.d.ts +1 -1
- package/dist/workspace/trust/verify.d.ts +16 -2
- package/dist/workspace/trust/verify.d.ts.map +1 -1
- package/dist/workspace/wip-cli.d.ts +21 -0
- package/dist/workspace/wip-cli.d.ts.map +1 -0
- package/dist/workspace/wip.d.ts +268 -0
- package/dist/workspace/wip.d.ts.map +1 -0
- package/dist/workspace/work-cli.d.ts.map +1 -1
- package/dist/workspace/work-evidence.d.ts +1 -1
- package/dist/workspace/work-evidence.d.ts.map +1 -1
- package/dist/workspace/work-size.d.ts +55 -0
- package/dist/workspace/work-size.d.ts.map +1 -0
- package/dist/workspace/workspace-kinds.schema.json +122 -0
- package/dist/workspace/write-lock-cli.d.ts +60 -0
- package/dist/workspace/write-lock-cli.d.ts.map +1 -0
- package/dist/workspace/write-lock.d.ts +152 -0
- package/dist/workspace/write-lock.d.ts.map +1 -0
- package/dist/workspace/write-scope.d.ts +6 -2
- package/dist/workspace/write-scope.d.ts.map +1 -1
- package/dist/yaml.d.ts +1 -1
- package/dist/yaml.d.ts.map +1 -1
- package/package.json +6 -1
- package/src/__fixtures__/change-set/lifecycle-plan.floci.json +59 -0
- package/src/__fixtures__/change-set/lifecycle-v1.ts.txt +4 -0
- package/src/__fixtures__/change-set/lifecycle-v2.ts.txt +4 -0
- package/src/__fixtures__/change-set/lifecycle.change-set.golden.json +95 -0
- package/src/__fixtures__/change-set/warden.change-set.golden.json +106 -0
- package/src/__fixtures__/change-set/warden.plan.json +44 -0
- package/src/__fixtures__/plan-summary/normalization-vectors.json +1593 -0
- package/src/__fixtures__/pr-loop/pr-apply-applied.note.golden.md +31 -0
- package/src/__fixtures__/pr-loop/pr-apply-refused.note.golden.md +31 -0
- package/src/__fixtures__/pr-loop/pr-plan.golden.json +127 -0
- package/src/__fixtures__/pr-loop/pr-plan.note.golden.md +37 -0
- package/src/audit/core.test.ts +15 -0
- package/src/audit/core.ts +8 -2
- package/src/audit/discover.test.ts +11 -0
- package/src/audit/discover.ts +7 -2
- package/src/change-set-bundle.test.ts +57 -0
- package/src/change-set.test.ts +215 -0
- package/src/change-set.ts +445 -0
- package/src/cli/commands/audit-opt-in.test.ts +54 -0
- package/src/cli/commands/audit.ts +29 -2
- package/src/cli/commands/build.test.ts +19 -0
- package/src/cli/commands/build.ts +3 -2
- package/src/cli/handlers/build.ts +13 -1
- package/src/cli/handlers/change-set.test.ts +56 -0
- package/src/cli/handlers/change-set.ts +44 -0
- package/src/cli/handlers/fan-out.test.ts +221 -2
- package/src/cli/handlers/fan-out.ts +165 -75
- package/src/cli/handlers/graph.ts +3 -0
- package/src/cli/handlers/operator.test.ts +21 -0
- package/src/cli/handlers/operator.ts +34 -3
- package/src/cli/handlers/pr.ts +373 -0
- package/src/cli/handlers/run.ts +1 -0
- package/src/cli/main.test.ts +20 -0
- package/src/cli/main.ts +185 -23
- package/src/cli/mcp/never-over-mcp.test.ts +101 -0
- package/src/cli/mcp/op-tools.ts +24 -2
- package/src/cli/mcp/workspace-tools.test.ts +1 -1
- package/src/cli/mcp/workspace-tools.ts +34 -6
- package/src/cli/registry.ts +63 -1
- package/src/components/auto-release.ts +1 -1
- package/src/components/capability.ts +55 -0
- package/src/components/changed-files.ts +66 -0
- package/src/components/cli-support.ts +28 -5
- package/src/components/component.schema.json +17 -0
- package/src/components/component.ts +25 -0
- package/src/components/deploy-units.ts +3 -0
- package/src/components/driver.test.ts +52 -0
- package/src/components/driver.ts +31 -13
- package/src/components/fan-out-output.ts +42 -1
- package/src/components/fan-out-record.ts +69 -0
- package/src/components/fan-out-run.test.ts +17 -0
- package/src/components/fan-out-run.ts +304 -1
- package/src/components/fan-out-support.ts +3 -0
- package/src/components/fan-out-waves.test.ts +375 -0
- package/src/components/fan-out.ts +18 -17
- package/src/components/gated-wave-pipeline.ts +82 -0
- package/src/components/index.ts +1 -0
- package/src/components/layers.ts +30 -0
- package/src/components/pr-pipeline.ts +91 -0
- package/src/components/pr-run.test.ts +205 -0
- package/src/components/pr-run.ts +280 -0
- package/src/components/promote.ts +5 -0
- package/src/components/verbs/shell.test.ts +11 -0
- package/src/components/verbs/shell.ts +7 -3
- package/src/components/wave-plan.ts +124 -0
- package/src/discovery/sandbox/bundle.ts +1 -1
- package/src/gated-waves-bundle.test.ts +62 -0
- package/src/gated-waves.test.ts +118 -0
- package/src/gated-waves.ts +240 -0
- package/src/index.ts +1 -0
- package/src/lexicon.ts +51 -0
- package/src/lifecycle/gate-ledger.ts +7 -0
- package/src/lifecycle/git.ts +102 -16
- package/src/lint/post-synth.test.ts +19 -0
- package/src/lint/post-synth.ts +19 -1
- package/src/meta/declared-imports.test.ts +1 -1
- package/src/op/activities/activity-contracts.ts +84 -0
- package/src/op/activities/change-set.ts +114 -0
- package/src/op/activities/decide.ts +3 -0
- package/src/op/activities/factory.ts +675 -0
- package/src/op/activities/index.ts +6 -0
- package/src/op/activity-contract.test.ts +21 -1
- package/src/op/activity-contract.ts +19 -9
- package/src/op/builders.ts +23 -0
- package/src/op/decide-backend.ts +5 -1
- package/src/op/decide-read-inputs.ts +33 -5
- package/src/op/factory.e2e.test.ts +232 -0
- package/src/op/factory.ts +118 -0
- package/src/op/index.ts +9 -1
- package/src/op/op-ir.test.ts +9 -0
- package/src/op/op-ir.ts +4 -0
- package/src/op/op-verb-class.ts +3 -0
- package/src/op/types.ts +8 -0
- package/src/op/work-lease-run.ts +3 -0
- package/src/plan-summary.test.ts +263 -0
- package/src/plan-summary.ts +845 -0
- package/src/pr-forge.test.ts +237 -0
- package/src/pr-forge.ts +332 -0
- package/src/pr-loop-bundle.test.ts +46 -0
- package/src/pr-loop.test.ts +171 -0
- package/src/pr-loop.ts +324 -0
- package/src/telemetry-attribution.test.ts +23 -1
- package/src/telemetry-attribution.ts +51 -0
- package/src/terraform/hcl2json.test.ts +21 -0
- package/src/terraform/hcl2json.ts +81 -0
- package/src/terraform/parse.ts +11 -74
- package/src/vendor/js-yaml-load.test.ts +115 -0
- package/src/vendor/js-yaml-load.ts +1939 -0
- package/src/workspace/__fixtures__/studio-template-84c8b21.json +1 -1
- package/src/workspace/app-kind.test.ts +196 -0
- package/src/workspace/box-cli.ts +113 -0
- package/src/workspace/box-factory.test.ts +4 -1
- package/src/workspace/box-factory.ts +37 -4
- package/src/workspace/box-listing-write.schema.json +204 -0
- package/src/workspace/box-listing.test.ts +234 -0
- package/src/workspace/box-listing.ts +324 -0
- package/src/workspace/box-publish.schema.json +498 -0
- package/src/workspace/box-publish.test.ts +204 -0
- package/src/workspace/box-publish.ts +420 -0
- package/src/workspace/box-ship.test.ts +96 -0
- package/src/workspace/broker-protocol.schema.json +186 -0
- package/src/workspace/broker-protocol.test.ts +122 -0
- package/src/workspace/broker-protocol.ts +317 -0
- package/src/workspace/builder-tiers.test.ts +146 -0
- package/src/workspace/change-set.schema.json +460 -0
- package/src/workspace/chant-migrations.e2e.test.ts +17 -5
- package/src/workspace/checks/boxes.test.ts +3 -0
- package/src/workspace/checks.ts +10 -3
- package/src/workspace/component-environments.test.ts +105 -0
- package/src/workspace/composites.schema.json +23 -4
- package/src/workspace/composites.test.ts +8 -8
- package/src/workspace/composites.ts +13 -2
- package/src/workspace/conformance/__fixture__/decisions/decision.schema.json +2 -2
- package/src/workspace/conformance/__fixtures__/reference-broker.ts +207 -0
- package/src/workspace/conformance/__writer_fixture__/answers/answer.kind.mjs +7 -2
- package/src/workspace/conformance/__writer_fixture__/answers/answer.schema.json +42 -2
- package/src/workspace/conformance/__writer_fixture__/contracts/contract.kind.mjs +37 -0
- package/src/workspace/conformance/__writer_fixture__/contracts/contract.schema.json +213 -0
- package/src/workspace/conformance/__writer_fixture__/decisions/points.json +96 -0
- package/src/workspace/conformance/__writer_fixture__/drivers/driver.kind.mjs +15 -0
- package/src/workspace/conformance/__writer_fixture__/drivers/driver.schema.json +38 -0
- package/src/workspace/conformance/__writer_fixture__/sessions/session.kind.mjs +14 -8
- package/src/workspace/conformance/__writer_fixture__/sessions/session.schema.json +187 -6
- package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +25 -0
- package/src/workspace/conformance/broker.test.ts +122 -0
- package/src/workspace/conformance/broker.ts +792 -0
- package/src/workspace/conformance/conformance.e2e.test.ts +2 -1
- package/src/workspace/conformance/index.mjs +22 -1
- package/src/workspace/conformance/index.ts +5 -1
- package/src/workspace/conformance/vitest.ts +33 -1
- package/src/workspace/conformance/writer-conformance.e2e.test.ts +49 -3
- package/src/workspace/conformance/writer.test.ts +32 -2
- package/src/workspace/conformance/writer.ts +339 -28
- package/src/workspace/decide.test.ts +208 -4
- package/src/workspace/decide.ts +427 -73
- package/src/workspace/decision-points.schema.json +11 -4
- package/src/workspace/declaration.schema.json +153 -4
- package/src/workspace/declaration.ts +141 -0
- package/src/workspace/environments.ts +66 -14
- package/src/workspace/factory-rules.test.ts +62 -0
- package/src/workspace/factory-rules.ts +218 -0
- package/src/workspace/graph-cli.ts +2 -2
- package/src/workspace/graph.schema.json +67 -0
- package/src/workspace/identity.test.ts +23 -0
- package/src/workspace/init.ts +82 -2
- package/src/workspace/intent-cli.ts +26 -9
- package/src/workspace/intent-patch-id.test.ts +162 -0
- package/src/workspace/intent-record.schema.json +130 -3
- package/src/workspace/intent-record.ts +74 -28
- package/src/workspace/intent-reviews.test.ts +76 -0
- package/src/workspace/intent-squash.test.ts +213 -0
- package/src/workspace/intent-why.test.ts +5 -5
- package/src/workspace/intent.schema.json +234 -4
- package/src/workspace/intent.ts +260 -66
- package/src/workspace/json-edit.test.ts +121 -0
- package/src/workspace/json-edit.ts +142 -0
- package/src/workspace/jsonc.ts +20 -0
- package/src/workspace/kinds.ts +157 -2
- package/src/workspace/lexicon-symbols.test.ts +148 -0
- package/src/workspace/lexicon-symbols.ts +125 -0
- package/src/workspace/lineage-upgrade.test.ts +63 -0
- package/src/workspace/lineage-upgrade.ts +146 -5
- package/src/workspace/plan-summary.schema.json +155 -0
- package/src/workspace/point-answer.schema.json +42 -2
- package/src/workspace/points-cli.ts +42 -16
- package/src/workspace/points-write.schema.json +162 -4
- package/src/workspace/points.schema.json +157 -2
- package/src/workspace/points.test.ts +13 -1
- package/src/workspace/points.ts +118 -12
- package/src/workspace/pr-report.schema.json +95 -0
- package/src/workspace/profiles.test.ts +159 -0
- package/src/workspace/read-contract.test.ts +2 -2
- package/src/workspace/reason-codes.test.ts +13 -1
- package/src/workspace/reason-codes.ts +38 -4
- package/src/workspace/record-sessions.ts +9 -8
- package/src/workspace/records-amend.schema.json +78 -0
- package/src/workspace/records-cli.ts +20 -6
- package/src/workspace/records-close.schema.json +78 -0
- package/src/workspace/records-close.ts +31 -7
- package/src/workspace/records-concurrent.e2e.test.ts +135 -0
- package/src/workspace/records-concurrent.test.ts +145 -0
- package/src/workspace/records-formats.test.ts +46 -10
- package/src/workspace/records-new.schema.json +7 -0
- package/src/workspace/records-review.schema.json +78 -0
- package/src/workspace/records-sessions-write.test.ts +69 -0
- package/src/workspace/records-sessions.test.ts +22 -0
- package/src/workspace/records-write.ts +192 -25
- package/src/workspace/records.schema.json +16 -0
- package/src/workspace/records.ts +50 -9
- package/src/workspace/reference-kinds/app/package.json +10 -0
- package/src/workspace/reference-kinds/app/workspace-kinds.json +45 -0
- package/src/workspace/run-statement.schema.json +622 -0
- package/src/workspace/runs-cli.ts +343 -14
- package/src/workspace/runs-statement.test.ts +239 -0
- package/src/workspace/runs-write.schema.json +416 -5
- package/src/workspace/runs.schema.json +451 -4
- package/src/workspace/runs.test.ts +39 -0
- package/src/workspace/runs.ts +296 -35
- package/src/workspace/session-kinds.ts +3 -3
- package/src/workspace/squash.ts +198 -0
- package/src/workspace/status-contract.test.ts +5 -2
- package/src/workspace/status-gates.ts +3 -1
- package/src/workspace/status.schema.json +126 -3
- package/src/workspace/status.ts +90 -1
- package/src/workspace/symbols.ts +20 -9
- package/src/workspace/trust/run-commits.ts +115 -0
- package/src/workspace/trust/run-statement.ts +226 -0
- package/src/workspace/trust/seal.ts +8 -2
- package/src/workspace/trust/verify-cli.ts +6 -5
- package/src/workspace/trust/verify.ts +39 -6
- package/src/workspace/wip-cli.ts +97 -0
- package/src/workspace/wip-write.schema.json +504 -0
- package/src/workspace/wip.schema.json +334 -0
- package/src/workspace/wip.test.ts +294 -0
- package/src/workspace/wip.ts +753 -0
- package/src/workspace/work-cli.ts +3 -0
- package/src/workspace/work-evidence.schema.json +3 -0
- package/src/workspace/work-size.test.ts +77 -0
- package/src/workspace/work-size.ts +93 -0
- package/src/workspace/workspace-kinds.schema.json +122 -0
- package/src/workspace/write-lock-cli.ts +131 -0
- package/src/workspace/write-lock.schema.json +172 -0
- package/src/workspace/write-lock.test.ts +189 -0
- package/src/workspace/write-lock.ts +474 -0
- package/src/workspace/write-scope.test.ts +16 -1
- package/src/workspace/write-scope.ts +33 -11
- package/src/yaml.ts +31 -21
package/src/op/op-ir.ts
CHANGED
|
@@ -199,6 +199,8 @@ export interface OpIR {
|
|
|
199
199
|
workLease?: OpWorkLease;
|
|
200
200
|
/** `OpConfig.changesCheckout` (#2748), present only when true. */
|
|
201
201
|
changesCheckout?: true;
|
|
202
|
+
/** `OpConfig.neverOverMcp`, present only when true. */
|
|
203
|
+
neverOverMcp?: true;
|
|
202
204
|
phases: OpIRPhase[];
|
|
203
205
|
onFailure: OpIRPhase[];
|
|
204
206
|
/** Every activity profile referenced by a step in this Op, keyed by profile name — from the registry passed to {@link buildOpIR}, empty when none was. */
|
|
@@ -365,6 +367,7 @@ export function buildOpIR(
|
|
|
365
367
|
...(config.schedule ? { schedule: config.schedule } : {}),
|
|
366
368
|
...(config.workLease ? { workLease: config.workLease } : {}),
|
|
367
369
|
...(config.changesCheckout ? { changesCheckout: true as const } : {}),
|
|
370
|
+
...(config.neverOverMcp ? { neverOverMcp: true as const } : {}),
|
|
368
371
|
phases: config.phases.map((p) => irPhase(p, contractRegistry)),
|
|
369
372
|
onFailure: (config.onFailure ?? []).map((p) => irPhase(p, contractRegistry)),
|
|
370
373
|
activityProfiles: sortedEntries(profiles),
|
|
@@ -446,5 +449,6 @@ export function opConfigFromIR(ir: OpIR): OpConfig {
|
|
|
446
449
|
...(ir.schedule ? { schedule: ir.schedule } : {}),
|
|
447
450
|
...(ir.workLease ? { workLease: ir.workLease } : {}),
|
|
448
451
|
...(ir.changesCheckout ? { changesCheckout: true } : {}),
|
|
452
|
+
...(ir.neverOverMcp ? { neverOverMcp: true } : {}),
|
|
449
453
|
};
|
|
450
454
|
}
|
package/src/op/op-verb-class.ts
CHANGED
|
@@ -35,6 +35,9 @@ export type OpVerbClass = "read-only" | "mutating" | "destructive";
|
|
|
35
35
|
const READ_ONLY_ACTIVITY_FNS: ReadonlySet<string> = new Set([
|
|
36
36
|
"lifecycleSnapshot",
|
|
37
37
|
"lifecycleDiff",
|
|
38
|
+
"composeChangeSet",
|
|
39
|
+
"lifecyclePlanChangeSet",
|
|
40
|
+
"readChangeSetPart",
|
|
38
41
|
"httpCheck",
|
|
39
42
|
"policyGate",
|
|
40
43
|
"workflowSupplyChainAudit",
|
package/src/op/types.ts
CHANGED
|
@@ -59,6 +59,14 @@ export interface OpConfig {
|
|
|
59
59
|
* coding agent is editing.
|
|
60
60
|
*/
|
|
61
61
|
changesCheckout?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Approvals for this Op belong to people, so an agent never resolves its
|
|
64
|
+
* gates or runs it over MCP. `op-approve` refuses any gate of this Op and
|
|
65
|
+
* `op-run` refuses the Op, whatever channel the gate was reached on.
|
|
66
|
+
* `op-list`, `op-status` and `op-report` still answer. The shell commands
|
|
67
|
+
* `chant run` and `chant approve` are unchanged.
|
|
68
|
+
*/
|
|
69
|
+
neverOverMcp?: boolean;
|
|
62
70
|
}
|
|
63
71
|
|
|
64
72
|
/**
|
package/src/op/work-lease-run.ts
CHANGED
|
@@ -416,6 +416,9 @@ export class RunWorkLease {
|
|
|
416
416
|
outcome,
|
|
417
417
|
note,
|
|
418
418
|
}).catch(() => undefined);
|
|
419
|
+
// #3172: the box's replicate policy may push the kept attempt and the work branch now. Best effort.
|
|
420
|
+
// Loaded only here, so an Op run outside a workspace never loads workspace modules (#2526).
|
|
421
|
+
if (released?.ok) (await import("../workspace/wip")).replicateAfter("release", this.opts.cwd);
|
|
419
422
|
return { ...base, kept, released: released?.ok === true, outcome: released?.ok ? outcome : null };
|
|
420
423
|
}
|
|
421
424
|
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The grouped plan summary (#3188): its schema, what is never folded into a
|
|
3
|
+
* group, and the size of the markdown note.
|
|
4
|
+
*
|
|
5
|
+
* The normalization vectors and the real N=5 module bump run in
|
|
6
|
+
* `lexicons/terraform/src/plan-summary.test.ts`, which reads them through the
|
|
7
|
+
* terraform adapters. Its JSON golden is validated here.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { readFileSync } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { describe, expect, test } from "vitest";
|
|
13
|
+
import { composeChangeSet, type ChangeSetAction, type ChangeSetEntry, type ChangeSetPart } from "./change-set";
|
|
14
|
+
import {
|
|
15
|
+
GITHUB_COMMENT_LIMIT,
|
|
16
|
+
groupChangeSet,
|
|
17
|
+
planSummaryHeadline,
|
|
18
|
+
PLAN_SUMMARY_SCHEMA_ID,
|
|
19
|
+
renderPlanSummaryMarkdown,
|
|
20
|
+
renderPlanSummaryText,
|
|
21
|
+
splitInstanceKeys,
|
|
22
|
+
escapeMarkerAddress,
|
|
23
|
+
} from "./plan-summary";
|
|
24
|
+
import { contract, REPO, validSchema } from "./workspace/__fixtures__/contract-repo";
|
|
25
|
+
import schema from "./workspace/plan-summary.schema.json";
|
|
26
|
+
|
|
27
|
+
const { expectValid } = contract(schema);
|
|
28
|
+
|
|
29
|
+
let digest = 0;
|
|
30
|
+
|
|
31
|
+
function part(member: string, entries: Array<Partial<ChangeSetEntry> & { address: string; action: ChangeSetAction }>, extra: Partial<ChangeSetPart["member"]> = {}): ChangeSetPart {
|
|
32
|
+
return {
|
|
33
|
+
member: { member, lexicon: "terraform", planner: "terraform", status: "planned", planDigest: `jcs1-sha256:${(++digest).toString(16).padStart(64, "0")}`, holes: [], ...extra },
|
|
34
|
+
entries: entries.map((e) => ({ member, lexicon: "terraform", planner: "terraform", type: e.address.split(".")[0], attributes: [], ...e })),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const tagsUpdate = (address: string, member: string) => ({
|
|
39
|
+
address,
|
|
40
|
+
action: "update" as const,
|
|
41
|
+
attributes: [{ path: "tags", before: { Name: `${member}-app`, v: "1" }, after: { Name: `${member}-app`, v: "2" } }],
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe("the plan-summary schema", () => {
|
|
45
|
+
test("is a valid schema and names this module's id", () => {
|
|
46
|
+
expect(validSchema(schema)).toBe(true);
|
|
47
|
+
expect(schema.$id).toBe(PLAN_SUMMARY_SCHEMA_ID);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("accepts the golden summary of the N=5 module bump", () => {
|
|
51
|
+
const path = join(REPO, "lexicons", "terraform", "src", "__fixtures__", "plan-summary", "largeset-n5.summary.golden.json");
|
|
52
|
+
expectValid(JSON.parse(readFileSync(path, "utf-8")));
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe("provisional members (#3416)", () => {
|
|
57
|
+
// Four roots take the same tag change; two of them were planned before what they read applied.
|
|
58
|
+
const parts = ["r1", "r2", "r3", "r4"].map((m) => part(m, [tagsUpdate(`aws_s3_bucket.b`, m)], m === "r3" || m === "r4" ? { provisional: true } : {}));
|
|
59
|
+
const s = groupChangeSet(composeChangeSet(parts));
|
|
60
|
+
|
|
61
|
+
test("group only with each other, after the real plans, and say so", () => {
|
|
62
|
+
expect(s.groups.map((g) => [g.units, g.provisional])).toEqual([
|
|
63
|
+
[["r1", "r2"], undefined],
|
|
64
|
+
[["r3", "r4"], true],
|
|
65
|
+
]);
|
|
66
|
+
expect(s.groups[0]!.id).not.toBe(s.groups[1]!.id);
|
|
67
|
+
expect(s.groups[1]!.extends).toBeUndefined();
|
|
68
|
+
expectValid(s);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("keep the id a group of real plans had before", () => {
|
|
72
|
+
const real = groupChangeSet(composeChangeSet(parts.slice(0, 2)));
|
|
73
|
+
expect(real.groups[0]!.id).toBe(s.groups[0]!.id);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("are counted in the headline and marked in text and markdown", () => {
|
|
77
|
+
expect(planSummaryHeadline(s)).toBe("4 members: 2 groups, 1 provisional, 0 destroys or replacements.");
|
|
78
|
+
expect(renderPlanSummaryText(s)).toMatch(/Group [0-9a-f]{12}: 2 members \(provisional\), identical change/);
|
|
79
|
+
expect(renderPlanSummaryMarkdown(s)).toMatch(/Provisional: planned before what it reads applied/);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe("what is never folded into a group", () => {
|
|
84
|
+
// Thirty roots take the same tag change. Three of them also destroy or
|
|
85
|
+
// replace something, one failed to plan and one has a hole.
|
|
86
|
+
const parts: ChangeSetPart[] = [];
|
|
87
|
+
for (let i = 1; i <= 30; i++) {
|
|
88
|
+
const m = `roots/r${String(i).padStart(2, "0")}`;
|
|
89
|
+
const entries: Parameters<typeof part>[1] = [tagsUpdate("aws_iam_role.app", `r${String(i).padStart(2, "0")}`)];
|
|
90
|
+
if (i === 3) entries.push({ address: "aws_db_instance.main", action: "delete" });
|
|
91
|
+
if (i === 7 || i === 8) entries.push({ address: "aws_lambda_function.worker", action: "replace", attributes: [{ path: "runtime", before: "nodejs18.x", after: "nodejs22.x", forcesReplacement: true }] });
|
|
92
|
+
parts.push(part(m, entries, { scope: `r${String(i).padStart(2, "0")}` }));
|
|
93
|
+
}
|
|
94
|
+
parts.push(part("roots/broken", [{ address: "aws_s3_bucket.gone", action: "delete" }], { status: "failed", error: "terraform marked the plan errored" }));
|
|
95
|
+
parts.push(part("roots/r99", [tagsUpdate("aws_iam_role.app", "r99")], { scope: "r99", holes: [{ address: "aws_kms_key.k", reason: "access denied" }] }));
|
|
96
|
+
const doc = composeChangeSet(parts);
|
|
97
|
+
const s = groupChangeSet(doc);
|
|
98
|
+
|
|
99
|
+
test("the identical change is one group; the destroys and replacements split off but are each named", () => {
|
|
100
|
+
expect(s.groups.map((g) => g.units.length)).toEqual([28, 2, 1]);
|
|
101
|
+
const named = s.destroys.map((d) => `${d.member} ${d.address} ${d.action}`);
|
|
102
|
+
expect(named).toEqual([
|
|
103
|
+
"roots/broken aws_s3_bucket.gone delete",
|
|
104
|
+
"roots/r03 aws_db_instance.main delete",
|
|
105
|
+
"roots/r07 aws_lambda_function.worker replace",
|
|
106
|
+
"roots/r08 aws_lambda_function.worker replace",
|
|
107
|
+
]);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("every delete and replace in the document is named, in the summary and in its group, in every format", () => {
|
|
111
|
+
const want = [...doc.summary.deletes, ...doc.summary.replacements].map((d) => `${d.member}: ${d.address}`).sort();
|
|
112
|
+
expect(s.destroys.map((d) => `${d.member}: ${d.address}`).sort()).toEqual(want);
|
|
113
|
+
const grouped = s.groups.flatMap((g) => g.destroys.map((d) => `${d.member}: ${d.address}`));
|
|
114
|
+
expect(grouped.sort()).toEqual(want.filter((w) => !w.startsWith("roots/broken")));
|
|
115
|
+
const text = renderPlanSummaryText(s);
|
|
116
|
+
const md = renderPlanSummaryMarkdown(s);
|
|
117
|
+
for (const w of want) {
|
|
118
|
+
expect(text).toContain(w);
|
|
119
|
+
expect(md).toContain(w);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
test("a destroy makes its unit's group differ from one without it, however alike the rest", () => {
|
|
124
|
+
for (const g of s.groups) {
|
|
125
|
+
const destroying = new Set(g.destroys.map((d) => d.member));
|
|
126
|
+
expect(destroying.size === 0 || destroying.size === g.units.length, g.id).toBe(true);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test("a failed member is its own line with its reason, never a group member", () => {
|
|
131
|
+
expect(s.failed).toEqual([{ member: "roots/broken", reason: "terraform marked the plan errored" }]);
|
|
132
|
+
expect(s.groups.flatMap((g) => g.units)).not.toContain("roots/broken");
|
|
133
|
+
expect(renderPlanSummaryText(s)).toContain("roots/broken: terraform marked the plan errored");
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test("a hole is named with its member and reason", () => {
|
|
137
|
+
expect(s.holes).toEqual([{ member: "roots/r99", address: "aws_kms_key.k", reason: "access denied" }]);
|
|
138
|
+
expect(renderPlanSummaryMarkdown(s)).toContain("`roots/r99: aws_kms_key.k`: access denied");
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
test("validates against the schema", () => {
|
|
142
|
+
expectValid(s);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
describe("imports, forgets and triggered actions", () => {
|
|
147
|
+
const parts: ChangeSetPart[] = [];
|
|
148
|
+
for (let i = 1; i <= 6; i++) {
|
|
149
|
+
const r = `r${i}`;
|
|
150
|
+
const entries: Parameters<typeof part>[1] = [tagsUpdate("aws_iam_role.app", r)];
|
|
151
|
+
if (i <= 2) entries.push({ address: "aws_s3_bucket.old", action: "forget" });
|
|
152
|
+
if (i === 3) entries.push({ address: "aws_s3_bucket.old", action: "delete" });
|
|
153
|
+
if (i === 4) entries.push({ address: "aws_s3_bucket.adopted", action: "no-op", importing: true });
|
|
154
|
+
if (i === 5) entries.push({ address: "aws_s3_bucket.adopted", action: "update", importing: true, attributes: [{ path: "tags", before: null, after: { v: "1" } }] });
|
|
155
|
+
const p = part(`roots/${r}`, entries, { scope: r });
|
|
156
|
+
if (i === 6) p.sideEffects = [{ address: "action.aws_lambda_invoke.notify", type: "aws_lambda_invoke", trigger: "aws_iam_role.app", event: "after_update" }];
|
|
157
|
+
parts.push(p);
|
|
158
|
+
}
|
|
159
|
+
const doc = composeChangeSet(parts);
|
|
160
|
+
const s = groupChangeSet(doc);
|
|
161
|
+
|
|
162
|
+
test("a forget is never counted as a destroy, nor a destroy as a forget", () => {
|
|
163
|
+
expect(s.destroys.map((d) => `${d.member} ${d.address} ${d.action}`)).toEqual(["roots/r3 aws_s3_bucket.old delete"]);
|
|
164
|
+
expect(s.forgets.map((f) => `${f.member} ${f.address}`)).toEqual(["roots/r1 aws_s3_bucket.old", "roots/r2 aws_s3_bucket.old"]);
|
|
165
|
+
expect(s.groups.map((g) => g.units)).toContainEqual(["roots/r1", "roots/r2"]);
|
|
166
|
+
expect(s.groups.find((g) => g.units.includes("roots/r3"))?.units).toEqual(["roots/r3"]);
|
|
167
|
+
expect(s.groups.flatMap((g) => g.destroys).map((d) => d.member)).toEqual(["roots/r3"]);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test("an import is named, whether it changes anything or not, and splits from the same change without one", () => {
|
|
171
|
+
expect(s.imports.map((i) => `${i.member} ${i.address} ${i.action}`)).toEqual(["roots/r4 aws_s3_bucket.adopted no-op", "roots/r5 aws_s3_bucket.adopted update"]);
|
|
172
|
+
expect(s.groups.find((g) => g.units.includes("roots/r4"))?.units).toEqual(["roots/r4"]);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test("a triggered action is a side effect, named with what triggers it", () => {
|
|
176
|
+
expect(s.sideEffects).toEqual([{ member: "roots/r6", address: "action.aws_lambda_invoke.notify", type: "aws_lambda_invoke", trigger: "aws_iam_role.app", event: "after_update" }]);
|
|
177
|
+
expect(s.groups.find((g) => g.units.includes("roots/r6"))?.units).toEqual(["roots/r6"]);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test("the headline and both renderings name each kind apart from destroys", () => {
|
|
181
|
+
expect(planSummaryHeadline(s)).toContain("1 destroy or replacement");
|
|
182
|
+
expect(planSummaryHeadline(s)).toContain("2 forgets");
|
|
183
|
+
expect(planSummaryHeadline(s)).toContain("2 imports");
|
|
184
|
+
expect(planSummaryHeadline(s)).toContain("1 triggered action");
|
|
185
|
+
for (const out of [renderPlanSummaryText(s), renderPlanSummaryMarkdown(s)]) {
|
|
186
|
+
expect(out).toContain("Forgets (2)");
|
|
187
|
+
expect(out).toContain("Imports (2)");
|
|
188
|
+
expect(out).toContain("Triggered actions (1)");
|
|
189
|
+
expect(out).toContain("roots/r1: aws_s3_bucket.old");
|
|
190
|
+
expect(out).toContain("roots/r4: aws_s3_bucket.adopted");
|
|
191
|
+
expect(out).toContain("roots/r6: action.aws_lambda_invoke.notify");
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
test("validates against the schema", () => {
|
|
196
|
+
expectValid(s);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
describe("the markdown note", () => {
|
|
201
|
+
// 400 roots in 200 distinct groups of two, one destroy each in the last 20.
|
|
202
|
+
const parts: ChangeSetPart[] = [];
|
|
203
|
+
for (let i = 0; i < 400; i++) {
|
|
204
|
+
const g = Math.floor(i / 2);
|
|
205
|
+
const entries: Parameters<typeof part>[1] = [{ address: `aws_sqs_queue.q${g}`, action: "update", attributes: [{ path: "visibility_timeout_seconds", before: 30, after: 60 + g }] }];
|
|
206
|
+
if (g >= 180) entries.push({ address: `aws_s3_bucket.old${i}`, action: "delete" });
|
|
207
|
+
parts.push(part(`roots/r${String(i).padStart(3, "0")}`, entries));
|
|
208
|
+
}
|
|
209
|
+
const s = groupChangeSet(composeChangeSet(parts));
|
|
210
|
+
|
|
211
|
+
test("fits the limit, keeps every destroy, drops whole groups from the end and says what it dropped", () => {
|
|
212
|
+
expect(s.groups).toHaveLength(400 - 180);
|
|
213
|
+
const limit = 8_000;
|
|
214
|
+
const md = renderPlanSummaryMarkdown(s, { limit });
|
|
215
|
+
expect([...md].length).toBeLessThanOrEqual(limit);
|
|
216
|
+
for (const d of s.destroys) expect(md).toContain(d.address);
|
|
217
|
+
const kept = s.groups.filter((g) => md.includes(`#### Group ${g.id}:`));
|
|
218
|
+
expect(kept.length).toBeGreaterThan(0);
|
|
219
|
+
expect(kept).toEqual(s.groups.slice(0, kept.length));
|
|
220
|
+
const cut = s.groups.length - kept.length;
|
|
221
|
+
const units = s.groups.slice(kept.length).reduce((n, g) => n + g.units.length, 0);
|
|
222
|
+
expect(md.trimEnd().split("\n").pop()).toBe(
|
|
223
|
+
`**Truncated:** this note leaves out ${cut} groups (${units} members) to stay within ${limit} characters. \`chant change-set summary\` prints all of it.`,
|
|
224
|
+
);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
test("is whole under GitHub's comment limit when it fits", () => {
|
|
228
|
+
const md = renderPlanSummaryMarkdown(s);
|
|
229
|
+
expect([...md].length).toBeLessThanOrEqual(GITHUB_COMMENT_LIMIT);
|
|
230
|
+
expect(md).not.toContain("**Truncated:**");
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
test("cuts destroy lines last, and counts them, when they alone are over the limit", () => {
|
|
234
|
+
const md = renderPlanSummaryMarkdown(s, { limit: 1_000 });
|
|
235
|
+
expect([...md].length).toBeLessThanOrEqual(1_000);
|
|
236
|
+
expect(md).not.toContain("#### Group");
|
|
237
|
+
expect(md).toMatch(/\*\*Truncated:\*\* this note leaves out \d+ destroys or replacements, 220 groups \(400 members\)/);
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
describe("group ids", () => {
|
|
242
|
+
test("are the same for the same change whatever the members are called, and differ for a different change", () => {
|
|
243
|
+
const a = groupChangeSet(composeChangeSet([part("x/acme", [tagsUpdate("aws_iam_role.app", "acme")], { scope: "acme" }), part("x/globex", [tagsUpdate("aws_iam_role.app", "globex")], { scope: "globex" })]));
|
|
244
|
+
const b = groupChangeSet(composeChangeSet([part("y/initech", [tagsUpdate("aws_iam_role.app", "initech")], { scope: "initech" }), part("y/hooli", [tagsUpdate("aws_iam_role.app", "hooli")], { scope: "hooli" })]));
|
|
245
|
+
expect(a.groups).toHaveLength(1);
|
|
246
|
+
expect(b.groups[0].id).toBe(a.groups[0].id);
|
|
247
|
+
const c = groupChangeSet(composeChangeSet([part("x/acme", [{ ...tagsUpdate("aws_iam_role.app", "acme"), attributes: [{ path: "tags", before: { v: "1" }, after: { v: "3" } }] }], { scope: "acme" }), part("x/z", [], { scope: "z" })]));
|
|
248
|
+
expect(c.groups[0].id).not.toBe(a.groups[0].id);
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
describe("addresses", () => {
|
|
253
|
+
test("instance keys come off, quoted ones decoded", () => {
|
|
254
|
+
expect(splitInstanceKeys('module.a["x.y"].aws_instance.b[0]')).toEqual({ bare: "module.a.aws_instance.b", keys: ["x.y", "0"] });
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
test("a tofu-address marker escapes keys as choudoufu does", () => {
|
|
258
|
+
expect(escapeMarkerAddress('aws_s3_bucket.logs["a.b"]')).toBe("aws_s3_bucket.logs:a@db");
|
|
259
|
+
expect(escapeMarkerAddress("aws_s3_bucket.logs[3]")).toBe("aws_s3_bucket.logs:3");
|
|
260
|
+
expect(escapeMarkerAddress('aws_s3_bucket.logs["a+b"]')).toBe("aws_s3_bucket.logs:a++b");
|
|
261
|
+
expect(escapeMarkerAddress('aws_s3_bucket.logs["a*b"]')).toBe("aws_s3_bucket.logs:a+00002Ab");
|
|
262
|
+
});
|
|
263
|
+
});
|