@intentius/chant 0.57.0 → 0.58.0
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/catalog.d.ts +51 -1
- package/dist/audit/catalog.d.ts.map +1 -1
- package/dist/audit/core.d.ts +20 -1
- package/dist/audit/core.d.ts.map +1 -1
- package/dist/audit/discover.d.ts +14 -8
- package/dist/audit/discover.d.ts.map +1 -1
- package/dist/audit/lineage.d.ts +10 -0
- package/dist/audit/lineage.d.ts.map +1 -0
- package/dist/audit/prior-art.d.ts +385 -0
- package/dist/audit/prior-art.d.ts.map +1 -0
- package/dist/audit/proof.d.ts +16 -0
- package/dist/audit/proof.d.ts.map +1 -1
- package/dist/audit/report-html.d.ts.map +1 -1
- package/dist/audit/report-model.d.ts +8 -1
- package/dist/audit/report-model.d.ts.map +1 -1
- package/dist/audit/report.d.ts.map +1 -1
- package/dist/audit/rules-doc.d.ts +3 -0
- package/dist/audit/rules-doc.d.ts.map +1 -1
- package/dist/audit/secrets.d.ts +15 -0
- package/dist/audit/secrets.d.ts.map +1 -1
- package/dist/audit/terraform-state.d.ts +46 -0
- package/dist/audit/terraform-state.d.ts.map +1 -0
- package/dist/build.d.ts +17 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/claimed-fields.d.ts +161 -0
- package/dist/claimed-fields.d.ts.map +1 -0
- package/dist/cli/build-params-cli.d.ts +2 -2
- package/dist/cli/command-group.d.ts +14 -0
- package/dist/cli/command-group.d.ts.map +1 -1
- package/dist/cli/commands/audit.d.ts +17 -1
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon-docs.d.ts +1 -1
- package/dist/cli/commands/check-lexicon-examples.d.ts +16 -6
- package/dist/cli/commands/check-lexicon-examples.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon/templates/codegen.d.ts +1 -0
- package/dist/cli/commands/init-lexicon/templates/codegen.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon/templates/project.d.ts +7 -0
- package/dist/cli/commands/init-lexicon/templates/project.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/onboard.d.ts +2 -0
- package/dist/cli/commands/onboard.d.ts.map +1 -1
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
- package/dist/cli/handlers/operator.d.ts +82 -16
- package/dist/cli/handlers/operator.d.ts.map +1 -1
- package/dist/cli/handlers/run.d.ts +49 -42
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/main.d.ts +28 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/mcp/op-tools.d.ts +16 -1
- package/dist/cli/mcp/op-tools.d.ts.map +1 -1
- package/dist/cli/mcp/resource-handlers.d.ts.map +1 -1
- package/dist/cli/mcp/resources/context.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +26 -9
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/codegen/generate-post-synth-barrel.d.ts +1 -1
- package/dist/components/auto-release.d.ts +10 -20
- package/dist/components/auto-release.d.ts.map +1 -1
- package/dist/components/capability.d.ts +4 -4
- package/dist/components/cli-support.d.ts +20 -21
- package/dist/components/cli-support.d.ts.map +1 -1
- package/dist/components/component.d.ts +3 -3
- package/dist/components/component.d.ts.map +1 -1
- package/dist/components/driver-output.d.ts.map +1 -1
- package/dist/components/driver.d.ts +66 -36
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/index.d.ts +1 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/manifest-persistence.d.ts +1 -9
- package/dist/components/manifest-persistence.d.ts.map +1 -1
- package/dist/components/run-progress.d.ts +6 -6
- package/dist/components/run-progress.d.ts.map +1 -1
- package/dist/components/verbs/run-agent.d.ts +9 -15
- package/dist/components/verbs/run-agent.d.ts.map +1 -1
- package/dist/components/verbs/verify.d.ts +2 -2
- package/dist/deep-observation.d.ts +17 -0
- package/dist/deep-observation.d.ts.map +1 -1
- package/dist/discovery/files.d.ts +4 -4
- package/dist/discovery/fold-import.d.ts.map +1 -1
- package/dist/discovery/param-deps.d.ts +33 -0
- package/dist/discovery/param-deps.d.ts.map +1 -1
- package/dist/discovery/sandbox/bundle.d.ts.map +1 -1
- package/dist/discovery/sandbox/config-wire.d.ts +2 -2
- package/dist/fold/foldable-helpers.d.ts +5 -1
- package/dist/fold/foldable-helpers.d.ts.map +1 -1
- package/dist/fold-provenance.d.ts +236 -0
- package/dist/fold-provenance.d.ts.map +1 -0
- package/dist/graph-ops.d.ts +1 -1
- package/dist/held-elsewhere.d.ts +85 -0
- package/dist/held-elsewhere.d.ts.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/kubectl-context.d.ts +3 -3
- package/dist/lexicon-config.d.ts +4 -4
- package/dist/lexicon-plugin-helpers.d.ts +1 -1
- package/dist/lexicon.d.ts +104 -14
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/change-set.d.ts +13 -0
- package/dist/lifecycle/change-set.d.ts.map +1 -1
- package/dist/lifecycle/deep-diff.d.ts +133 -6
- package/dist/lifecycle/deep-diff.d.ts.map +1 -1
- package/dist/lifecycle/deep-observe.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.d.ts +71 -3
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/index.d.ts +1 -0
- package/dist/lifecycle/index.d.ts.map +1 -1
- package/dist/lifecycle/release-ledger.d.ts +2 -2
- package/dist/lifecycle/run-ledger.d.ts +53 -0
- package/dist/lifecycle/run-ledger.d.ts.map +1 -0
- package/dist/lifecycle/symptoms.d.ts +3 -3
- package/dist/lifecycle/symptoms.d.ts.map +1 -1
- package/dist/lint/config.d.ts +81 -2
- package/dist/lint/config.d.ts.map +1 -1
- package/dist/lint/post-synth.d.ts +55 -2
- package/dist/lint/post-synth.d.ts.map +1 -1
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts +1 -1
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts.map +1 -1
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts +1 -1
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts.map +1 -1
- package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts +44 -0
- package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts.map +1 -0
- package/dist/lint/rules/comp/index.d.ts +1 -1
- package/dist/lint/rules/comp/index.d.ts.map +1 -1
- package/dist/lint/rules/op/index.d.ts +16 -0
- package/dist/lint/rules/op/index.d.ts.map +1 -0
- package/dist/lint/rules/op/ops012-activity-contract.d.ts +27 -0
- package/dist/lint/rules/op/ops012-activity-contract.d.ts.map +1 -0
- package/dist/lint/rules/op/ops013-step-output-ref.d.ts +61 -0
- package/dist/lint/rules/op/ops013-step-output-ref.d.ts.map +1 -0
- package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts +55 -0
- package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts.map +1 -0
- package/dist/lint/rules/op/support.d.ts +12 -0
- package/dist/lint/rules/op/support.d.ts.map +1 -0
- package/dist/lint/suppressions.d.ts +108 -0
- package/dist/lint/suppressions.d.ts.map +1 -0
- package/dist/live-endpoint.d.ts +1 -1
- package/dist/op/activities/activity-contracts.d.ts +54 -0
- package/dist/op/activities/activity-contracts.d.ts.map +1 -0
- package/dist/op/activities/apply.d.ts +262 -0
- package/dist/op/activities/apply.d.ts.map +1 -0
- package/dist/op/activities/build.d.ts +13 -0
- package/dist/op/activities/build.d.ts.map +1 -0
- package/dist/op/activities/converge.d.ts +110 -0
- package/dist/op/activities/converge.d.ts.map +1 -0
- package/dist/op/activities/env-teardown.d.ts +76 -0
- package/dist/op/activities/env-teardown.d.ts.map +1 -0
- package/dist/op/activities/guard-validate.d.ts +64 -0
- package/dist/op/activities/guard-validate.d.ts.map +1 -0
- package/dist/op/activities/http-check.d.ts +34 -0
- package/dist/op/activities/http-check.d.ts.map +1 -0
- package/dist/op/activities/index.d.ts +31 -0
- package/dist/op/activities/index.d.ts.map +1 -0
- package/dist/op/activities/lexicon-upgrade.d.ts +182 -0
- package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -0
- package/dist/op/activities/lifecycle.d.ts +42 -0
- package/dist/op/activities/lifecycle.d.ts.map +1 -0
- package/dist/op/activities/pipeline-audit.d.ts +84 -0
- package/dist/op/activities/pipeline-audit.d.ts.map +1 -0
- package/dist/op/activities/policy.d.ts +17 -0
- package/dist/op/activities/policy.d.ts.map +1 -0
- package/dist/op/activities/reconcile.d.ts +89 -0
- package/dist/op/activities/reconcile.d.ts.map +1 -0
- package/dist/op/activities/shell.d.ts +13 -0
- package/dist/op/activities/shell.d.ts.map +1 -0
- package/dist/op/activities/teardown.d.ts +10 -0
- package/dist/op/activities/teardown.d.ts.map +1 -0
- package/dist/op/activities/util.d.ts +7 -0
- package/dist/op/activities/util.d.ts.map +1 -0
- package/dist/op/activities/wait.d.ts +28 -0
- package/dist/op/activities/wait.d.ts.map +1 -0
- package/dist/op/activities/workflow-audit.d.ts +92 -0
- package/dist/op/activities/workflow-audit.d.ts.map +1 -0
- package/dist/op/activity-contract-registry.d.ts +76 -0
- package/dist/op/activity-contract-registry.d.ts.map +1 -0
- package/dist/op/activity-contract.d.ts +25 -18
- package/dist/op/activity-contract.d.ts.map +1 -1
- package/dist/op/activity-failure.d.ts +28 -0
- package/dist/op/activity-failure.d.ts.map +1 -0
- package/dist/op/activity-profiles.d.ts +118 -0
- package/dist/op/activity-profiles.d.ts.map +1 -0
- package/dist/op/activity-registry.d.ts +22 -38
- package/dist/op/activity-registry.d.ts.map +1 -1
- package/dist/op/activity-runtime.d.ts +3 -14
- package/dist/op/activity-runtime.d.ts.map +1 -1
- package/dist/op/builders.d.ts +84 -29
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/composites/apply-op.d.ts +113 -0
- package/dist/op/composites/apply-op.d.ts.map +1 -0
- package/dist/op/composites/converge-op.d.ts +120 -0
- package/dist/op/composites/converge-op.d.ts.map +1 -0
- package/dist/op/composites/index.d.ts +26 -0
- package/dist/op/composites/index.d.ts.map +1 -0
- package/dist/op/composites/lexicon-upgrade-op.d.ts +78 -0
- package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -0
- package/dist/op/composites/pipeline-audit-op.d.ts +50 -0
- package/dist/op/composites/pipeline-audit-op.d.ts.map +1 -0
- package/dist/op/composites/reconcile-op.d.ts +57 -0
- package/dist/op/composites/reconcile-op.d.ts.map +1 -0
- package/dist/op/composites/watch-op.d.ts +60 -0
- package/dist/op/composites/watch-op.d.ts.map +1 -0
- package/dist/op/composites/workflow-audit-op.d.ts +57 -0
- package/dist/op/composites/workflow-audit-op.d.ts.map +1 -0
- package/dist/op/converge-rule.d.ts +12 -10
- package/dist/op/converge-rule.d.ts.map +1 -1
- package/dist/op/cron.d.ts +51 -0
- package/dist/op/cron.d.ts.map +1 -0
- package/dist/op/discover.d.ts +9 -0
- package/dist/op/discover.d.ts.map +1 -1
- package/dist/op/duration.d.ts +11 -0
- package/dist/op/duration.d.ts.map +1 -0
- package/dist/op/emulator-lifecycle.d.ts.map +1 -1
- package/dist/op/gate.d.ts +90 -0
- package/dist/op/gate.d.ts.map +1 -0
- package/dist/op/generate-pipeline.d.ts +9 -0
- package/dist/op/generate-pipeline.d.ts.map +1 -1
- package/dist/op/index.d.ts +23 -7
- package/dist/op/index.d.ts.map +1 -1
- package/dist/op/local-executor.d.ts +114 -28
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/local-output.d.ts +11 -1
- package/dist/op/local-output.d.ts.map +1 -1
- package/dist/op/op-ir.d.ts +184 -0
- package/dist/op/op-ir.d.ts.map +1 -0
- package/dist/op/op-verb-class.d.ts +10 -2
- package/dist/op/op-verb-class.d.ts.map +1 -1
- package/dist/op/operator.d.ts +30 -5
- package/dist/op/operator.d.ts.map +1 -1
- package/dist/op/receipt-store.d.ts +1 -1
- package/dist/op/receipt-store.d.ts.map +1 -1
- package/dist/op/resource.d.ts +15 -1
- package/dist/op/resource.d.ts.map +1 -1
- package/dist/op/runtime.d.ts +200 -0
- package/dist/op/runtime.d.ts.map +1 -0
- package/dist/op/runtimes/local.d.ts +29 -0
- package/dist/op/runtimes/local.d.ts.map +1 -0
- package/dist/op/step-output-ref.d.ts +15 -13
- package/dist/op/step-output-ref.d.ts.map +1 -1
- package/dist/op/types.d.ts +79 -27
- package/dist/op/types.d.ts.map +1 -1
- package/dist/ownership.d.ts +1 -1
- package/dist/provenance.d.ts +21 -0
- package/dist/provenance.d.ts.map +1 -1
- package/dist/serializer-walker.d.ts.map +1 -1
- package/package.json +6 -1
- package/src/audit/catalog.test.ts +79 -3
- package/src/audit/catalog.ts +111 -13
- package/src/audit/core.test.ts +26 -0
- package/src/audit/core.ts +61 -17
- package/src/audit/discover.test.ts +39 -0
- package/src/audit/discover.ts +91 -15
- package/src/audit/lineage.ts +100 -0
- package/src/audit/prior-art.ts +153 -0
- package/src/audit/proof.test.ts +67 -0
- package/src/audit/proof.ts +70 -0
- package/src/audit/report-html.ts +9 -4
- package/src/audit/report-model.ts +16 -2
- package/src/audit/report.test.ts +33 -0
- package/src/audit/report.ts +5 -3
- package/src/audit/rules-doc.test.ts +34 -2
- package/src/audit/rules-doc.ts +82 -9
- package/src/audit/secrets.ts +15 -3
- package/src/audit/terraform-state.test.ts +144 -0
- package/src/audit/terraform-state.ts +131 -0
- package/src/build.ts +31 -1
- package/src/claimed-fields.test.ts +145 -0
- package/src/claimed-fields.ts +208 -0
- package/src/cli/build-params-cli.ts +2 -2
- package/src/cli/command-group.ts +14 -0
- package/src/cli/commands/__fixtures__/audit-terraform/infra/.terraform/providers/lock.txt +1 -0
- package/src/cli/commands/__fixtures__/audit-terraform/infra/main.tf +1 -0
- package/src/cli/commands/__fixtures__/audit-terraform/infra/modules/foo/main.tf +1 -0
- package/src/cli/commands/__fixtures__/audit-terraform/infra/variables.tf +3 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +13 -4
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/docs-cli.ts +4 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/package.ts +1 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/package-cli.ts +21 -0
- package/src/cli/commands/__snapshots__/init-lexicon.test.ts.snap +1 -0
- package/src/cli/commands/audit.test.ts +189 -11
- package/src/cli/commands/audit.ts +73 -27
- package/src/cli/commands/build.test.ts +292 -9
- package/src/cli/commands/build.ts +156 -24
- package/src/cli/commands/check-lexicon-docs.ts +1 -1
- package/src/cli/commands/check-lexicon-examples.test.ts +29 -1
- package/src/cli/commands/check-lexicon-examples.ts +42 -10
- package/src/cli/commands/init-lexicon/templates/codegen.ts +9 -0
- package/src/cli/commands/init-lexicon/templates/project.ts +44 -4
- package/src/cli/commands/init-lexicon.test.ts +97 -2
- package/src/cli/commands/init-lexicon.ts +4 -2
- package/src/cli/commands/init.test.ts +35 -1
- package/src/cli/commands/init.ts +14 -3
- package/src/cli/commands/lint.test.ts +48 -0
- package/src/cli/commands/lint.ts +123 -0
- package/src/cli/commands/onboard.test.ts +75 -0
- package/src/cli/commands/onboard.ts +54 -23
- package/src/cli/handlers/build.test.ts +81 -1
- package/src/cli/handlers/build.ts +15 -1
- package/src/cli/handlers/graph.test.ts +3 -3
- package/src/cli/handlers/lifecycle.test.ts +195 -12
- package/src/cli/handlers/lifecycle.ts +123 -6
- package/src/cli/handlers/misc.ts +1 -1
- package/src/cli/handlers/operator.test.ts +183 -11
- package/src/cli/handlers/operator.ts +260 -55
- package/src/cli/handlers/run.test.ts +431 -1287
- package/src/cli/handlers/run.ts +365 -915
- package/src/cli/main.test.ts +23 -15
- package/src/cli/main.ts +88 -33
- package/src/cli/mcp/op-tools.ts +147 -88
- package/src/cli/mcp/resource-handlers.ts +10 -37
- package/src/cli/mcp/resources/context.ts +11 -12
- package/src/cli/mcp/server.test.ts +25 -27
- package/src/cli/mcp/server.ts +2 -2
- package/src/cli/registry.ts +26 -9
- package/src/codegen/docs.ts +1 -1
- package/src/codegen/generate-post-synth-barrel.test.ts +1 -1
- package/src/codegen/generate-post-synth-barrel.ts +1 -1
- package/src/components/README.md +3 -2
- package/src/components/auto-release.test.ts +4 -20
- package/src/components/auto-release.ts +17 -42
- package/src/components/capability.ts +4 -4
- package/src/components/cli-support.test.ts +10 -5
- package/src/components/cli-support.ts +52 -44
- package/src/components/component.schema.json +2 -2
- package/src/components/component.ts +3 -3
- package/src/components/driver-output.ts +14 -2
- package/src/components/driver.test.ts +92 -22
- package/src/components/driver.ts +193 -83
- package/src/components/index.ts +1 -6
- package/src/components/manifest-persistence.test.ts +2 -20
- package/src/components/manifest-persistence.ts +4 -24
- package/src/components/pilots/pilots-lint-clean.test.ts +11 -10
- package/src/components/run-progress.ts +6 -6
- package/src/components/verbs/run-agent.ts +11 -17
- package/src/components/verbs/verify.ts +2 -2
- package/src/deep-observation.test.ts +75 -0
- package/src/deep-observation.ts +48 -0
- package/src/discovery/collect.test.ts +3 -3
- package/src/discovery/files.ts +4 -4
- package/src/discovery/fold-import.ts +105 -2
- package/src/discovery/param-deps.test.ts +112 -1
- package/src/discovery/param-deps.ts +193 -0
- package/src/discovery/sandbox/bundle.ts +15 -1
- package/src/discovery/sandbox/config-wire.test.ts +2 -2
- package/src/discovery/sandbox/config-wire.ts +2 -2
- package/src/fold/fold.test.ts +56 -0
- package/src/fold/foldable-helpers.ts +81 -1
- package/src/fold-provenance-exclusion.test.ts +186 -0
- package/src/fold-provenance.test.ts +495 -0
- package/src/fold-provenance.ts +441 -0
- package/src/graph-ops.test.ts +2 -2
- package/src/graph-ops.ts +1 -1
- package/src/held-elsewhere.test.ts +102 -0
- package/src/held-elsewhere.ts +114 -0
- package/src/index.ts +3 -0
- package/src/kubectl-context.ts +3 -3
- package/src/lexicon-config.test.ts +5 -5
- package/src/lexicon-config.ts +4 -4
- package/src/lexicon-plugin-helpers.ts +1 -1
- package/src/lexicon.ts +120 -14
- package/src/lifecycle/change-set.test.ts +49 -0
- package/src/lifecycle/change-set.ts +67 -0
- package/src/lifecycle/converge-ledger.ts +1 -1
- package/src/lifecycle/deep-diff.test.ts +267 -14
- package/src/lifecycle/deep-diff.ts +217 -14
- package/src/lifecycle/deep-observe.test.ts +3 -1
- package/src/lifecycle/deep-observe.ts +16 -6
- package/src/lifecycle/gate-ledger.test.ts +74 -2
- package/src/lifecycle/gate-ledger.ts +143 -36
- package/src/lifecycle/index.ts +1 -0
- package/src/lifecycle/release-ledger.ts +2 -2
- package/src/lifecycle/run-ledger.test.ts +268 -0
- package/src/lifecycle/run-ledger.ts +201 -0
- package/src/lifecycle/symptoms.ts +3 -3
- package/src/lint/config.test.ts +82 -1
- package/src/lint/config.ts +112 -3
- package/src/lint/policy.test.ts +1 -1
- package/src/lint/post-synth.test.ts +31 -0
- package/src/lint/post-synth.ts +54 -1
- package/src/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.ts +2 -2
- package/src/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.ts +1 -1
- package/src/lint/rules/comp/comp.test.ts +1 -1
- package/src/lint/rules/comp/comp004-gate-needs-durable-runtime.ts +74 -0
- package/src/lint/rules/comp/index.ts +3 -3
- package/src/lint/rules/op/index.ts +23 -0
- package/src/lint/rules/op/ops012-activity-contract.test.ts +161 -0
- package/src/lint/rules/op/ops012-activity-contract.ts +64 -0
- package/src/lint/rules/op/ops013-step-output-ref.test.ts +237 -0
- package/src/lint/rules/op/ops013-step-output-ref.ts +98 -0
- package/src/lint/rules/op/ops014-converge-rule-refusals.test.ts +263 -0
- package/src/lint/rules/op/ops014-converge-rule-refusals.ts +179 -0
- package/src/lint/rules/op/support.ts +11 -0
- package/src/lint/suppressions.test.ts +163 -0
- package/src/lint/suppressions.ts +204 -0
- package/src/live-endpoint.ts +1 -1
- package/src/op/activities/activity-contracts.ts +66 -0
- package/src/op/activities/apply.test.ts +567 -0
- package/src/op/activities/apply.ts +662 -0
- package/src/op/activities/build.ts +26 -0
- package/src/op/activities/converge.test.ts +330 -0
- package/src/op/activities/converge.ts +449 -0
- package/src/op/activities/env-teardown.test.ts +187 -0
- package/src/op/activities/env-teardown.ts +171 -0
- package/src/op/activities/guard-validate.test.ts +139 -0
- package/src/op/activities/guard-validate.ts +223 -0
- package/src/op/activities/http-check.test.ts +48 -0
- package/src/op/activities/http-check.ts +55 -0
- package/src/op/activities/index.ts +119 -0
- package/src/op/activities/lexicon-upgrade.test.ts +492 -0
- package/src/op/activities/lexicon-upgrade.ts +673 -0
- package/src/op/activities/lifecycle.ts +85 -0
- package/src/op/activities/pipeline-audit.test.ts +67 -0
- package/src/op/activities/pipeline-audit.ts +201 -0
- package/src/op/activities/policy.test.ts +19 -0
- package/src/op/activities/policy.ts +37 -0
- package/src/op/activities/reconcile.test.ts +81 -0
- package/src/op/activities/reconcile.ts +187 -0
- package/src/op/activities/shell.ts +26 -0
- package/src/op/activities/teardown.ts +22 -0
- package/src/op/activities/util.ts +6 -0
- package/src/op/activities/wait.ts +69 -0
- package/src/op/activities/workflow-audit.test.ts +90 -0
- package/src/op/activities/workflow-audit.ts +203 -0
- package/src/op/activity-contract-registry.test.ts +98 -0
- package/src/op/activity-contract-registry.ts +114 -0
- package/src/op/activity-contract.test.ts +1 -1
- package/src/op/activity-contract.ts +37 -33
- package/src/op/activity-failure.ts +34 -0
- package/src/op/activity-profiles.test.ts +56 -0
- package/src/op/activity-profiles.ts +116 -0
- package/src/op/activity-registry.test.ts +37 -28
- package/src/op/activity-registry.ts +27 -56
- package/src/op/activity-runtime.ts +3 -47
- package/src/op/builders-exports.test.ts +0 -49
- package/src/op/builders-typed.test.ts +164 -0
- package/src/op/builders.ts +123 -39
- package/src/op/composites/apply-op.ts +208 -0
- package/src/op/composites/composites.test.ts +366 -0
- package/src/op/composites/converge-op.test.ts +168 -0
- package/src/op/composites/converge-op.ts +214 -0
- package/src/op/composites/index.ts +26 -0
- package/src/op/composites/lexicon-upgrade-op.test.ts +68 -0
- package/src/op/composites/lexicon-upgrade-op.ts +134 -0
- package/src/op/composites/pipeline-audit-op.test.ts +25 -0
- package/src/op/composites/pipeline-audit-op.ts +78 -0
- package/src/op/composites/reconcile-op.test.ts +51 -0
- package/src/op/composites/reconcile-op.ts +107 -0
- package/src/op/composites/watch-op.ts +108 -0
- package/src/op/composites/workflow-audit-op.test.ts +25 -0
- package/src/op/composites/workflow-audit-op.ts +88 -0
- package/src/op/converge-rule.ts +12 -10
- package/src/op/cron.test.ts +128 -0
- package/src/op/cron.ts +149 -0
- package/src/op/discover-root.test.ts +105 -1
- package/src/op/discover.test.ts +6 -2
- package/src/op/discover.ts +84 -16
- package/src/op/duration.ts +21 -0
- package/src/op/effect-step.test.ts +26 -11
- package/src/op/emulator-lifecycle.ts +1 -2
- package/src/op/gate.ts +155 -0
- package/src/op/generate-pipeline.test.ts +65 -3
- package/src/op/generate-pipeline.ts +19 -2
- package/src/op/index.ts +39 -6
- package/src/op/local-executor.test.ts +163 -34
- package/src/op/local-executor.ts +370 -102
- package/src/op/local-output.test.ts +95 -11
- package/src/op/local-output.ts +33 -4
- package/src/op/op-ir.test.ts +281 -0
- package/src/op/op-ir.ts +417 -0
- package/src/op/op-verb-class.ts +19 -5
- package/src/op/op.test.ts +26 -5
- package/src/op/operator.test.ts +175 -6
- package/src/op/operator.ts +63 -16
- package/src/op/receipt-store.ts +1 -1
- package/src/op/resource.ts +20 -2
- package/src/op/runtime.ts +203 -0
- package/src/op/runtimes/local.test.ts +181 -0
- package/src/op/runtimes/local.ts +212 -0
- package/src/op/step-output-ref.ts +15 -13
- package/src/op/types.ts +84 -24
- package/src/ownership.ts +1 -1
- package/src/provenance.test.ts +6 -0
- package/src/provenance.ts +21 -1
- package/src/serializer-walker.test.ts +42 -0
- package/src/serializer-walker.ts +21 -2
- package/dist/cli/handlers/op-progress.d.ts +0 -90
- package/dist/cli/handlers/op-progress.d.ts.map +0 -1
- package/dist/cli/handlers/run-client.d.ts +0 -127
- package/dist/cli/handlers/run-client.d.ts.map +0 -1
- package/dist/cli/handlers/run-report.d.ts +0 -5
- package/dist/cli/handlers/run-report.d.ts.map +0 -1
- package/dist/components/temporal-codegen-loader.d.ts +0 -27
- package/dist/components/temporal-codegen-loader.d.ts.map +0 -1
- package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts +0 -37
- package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts.map +0 -1
- package/src/cli/handlers/op-progress.test.ts +0 -268
- package/src/cli/handlers/op-progress.ts +0 -248
- package/src/cli/handlers/run-client.test.ts +0 -82
- package/src/cli/handlers/run-client.ts +0 -219
- package/src/cli/handlers/run-report.test.ts +0 -62
- package/src/cli/handlers/run-report.ts +0 -122
- package/src/components/temporal-codegen-loader.ts +0 -41
- package/src/lint/rules/comp/comp004-gate-needs-temporal.ts +0 -66
|
@@ -0,0 +1,673 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lexiconUpgrade — the upgrade-detection and PR-automation activity for
|
|
3
|
+
* in-scope lexicons (k8s, gcp, docker, gitlab, aws, azure, github).
|
|
4
|
+
*
|
|
5
|
+
* Classifies the lexicon as pinned or rolling, calls the right check function,
|
|
6
|
+
* then surfaces the result in the requested mode: report (default), issue, or
|
|
7
|
+
* pull-request. In pull-request mode it maintains a long-lived branch per
|
|
8
|
+
* lexicon (`lexicon-upgrade/<lexicon>`), updates the PR in place when the delta
|
|
9
|
+
* changes, and applies a semver label derived from the surface severity.
|
|
10
|
+
*
|
|
11
|
+
* For pinned lexicons in pull-request mode, the PR also bumps the lexicon's
|
|
12
|
+
* own package.json version according to the semver label (minor → minor bump,
|
|
13
|
+
* breaking → major bump). Merging the PR carries the version change so
|
|
14
|
+
* publish-on-merge can ship just that lexicon without a full monorepo release.
|
|
15
|
+
*
|
|
16
|
+
* Rolling lexicons (aws, azure, github) drift on their own cadence and are not
|
|
17
|
+
* version-bumped here — they move to drift-issues per #546.
|
|
18
|
+
*
|
|
19
|
+
* Supply-chain note: this activity never executes spec-provided content.
|
|
20
|
+
* It only reads the artifacts produced by the lexicon's own generate step,
|
|
21
|
+
* which is called through the lexicon's npm prepack chain.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { exec } from "node:child_process";
|
|
25
|
+
import { promisify } from "node:util";
|
|
26
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
27
|
+
import { join } from "node:path";
|
|
28
|
+
import type { UpgradeCheckResult, LexiconId } from "../../codegen/pinned-upgrade";
|
|
29
|
+
import type { RollingUpgradeResult, RollingLexicon } from "../../codegen/rolling-upgrade";
|
|
30
|
+
import { bumpForSeverity, bumpPackageJsonVersion } from "../../codegen/version-bump";
|
|
31
|
+
|
|
32
|
+
export { bumpPackageJsonVersion };
|
|
33
|
+
|
|
34
|
+
const execAsync = promisify(exec);
|
|
35
|
+
|
|
36
|
+
// ── Public types ──────────────────────────────────────────────────────
|
|
37
|
+
|
|
38
|
+
/** Finding mode, mirrors ReconcileOp's mode. */
|
|
39
|
+
export type LexiconUpgradeMode = "report" | "issue" | "pull-request";
|
|
40
|
+
|
|
41
|
+
/** All lexicons supported by this activity. */
|
|
42
|
+
export type SupportedLexicon = LexiconId | RollingLexicon;
|
|
43
|
+
|
|
44
|
+
/** Semver label applied to upgrade PRs. */
|
|
45
|
+
export type SemverLabel = "minor" | "breaking";
|
|
46
|
+
|
|
47
|
+
export interface LexiconUpgradeArgs {
|
|
48
|
+
/**
|
|
49
|
+
* Which lexicon to check. Determines pinned vs rolling dispatch:
|
|
50
|
+
* PINNED: k8s, gcp, docker, gitlab, cedar
|
|
51
|
+
* ROLLING: aws, azure, github, fly
|
|
52
|
+
*/
|
|
53
|
+
lexicon: SupportedLexicon;
|
|
54
|
+
/**
|
|
55
|
+
* Absolute path to the lexicon root directory.
|
|
56
|
+
* Defaults to `<cwd>/lexicons/<lexicon>`.
|
|
57
|
+
*/
|
|
58
|
+
lexiconDir?: string;
|
|
59
|
+
/** What to produce. Default: "report". */
|
|
60
|
+
mode?: LexiconUpgradeMode;
|
|
61
|
+
/**
|
|
62
|
+
* Override the pinned check function — inject a mock in tests.
|
|
63
|
+
* The real implementation calls checkPinnedUpgrade from core.
|
|
64
|
+
*/
|
|
65
|
+
_checkPinned?: CheckPinnedFn;
|
|
66
|
+
/**
|
|
67
|
+
* Override the rolling check function — inject a mock in tests.
|
|
68
|
+
* The real implementation calls checkRollingUpgrade from core.
|
|
69
|
+
*/
|
|
70
|
+
_checkRolling?: CheckRollingFn;
|
|
71
|
+
/**
|
|
72
|
+
* Override the gh/git runner — inject a mock in tests.
|
|
73
|
+
*/
|
|
74
|
+
_gh?: GhRunner;
|
|
75
|
+
/**
|
|
76
|
+
* Override the applyPinnedVersionBump function — inject a mock in tests.
|
|
77
|
+
*/
|
|
78
|
+
_applyBump?: ApplyBumpFn;
|
|
79
|
+
/**
|
|
80
|
+
* Override the package.json version writer — inject a mock in tests.
|
|
81
|
+
* Defaults to bumpPackageJsonVersion.
|
|
82
|
+
*/
|
|
83
|
+
_bumpPackageVersion?: BumpPackageVersionFn;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface LexiconUpgradeResult {
|
|
87
|
+
lexicon: SupportedLexicon;
|
|
88
|
+
mode: LexiconUpgradeMode;
|
|
89
|
+
/** True when an upgrade is available and validation passed. */
|
|
90
|
+
hasUpgrade: boolean;
|
|
91
|
+
/** Human-readable surface delta summary. Empty when no upgrade. */
|
|
92
|
+
deltaText: string;
|
|
93
|
+
/** Semver label applied to the PR. null when no upgrade or no change. */
|
|
94
|
+
semverLabel: SemverLabel | null;
|
|
95
|
+
/** URL of the opened/updated PR (pull-request mode). */
|
|
96
|
+
prUrl?: string;
|
|
97
|
+
/** URL of the opened issue (issue mode). */
|
|
98
|
+
issueUrl?: string;
|
|
99
|
+
/** Full markdown summary, used as PR/issue body or printed in report mode. */
|
|
100
|
+
summary: string;
|
|
101
|
+
/** Whether validation passed. False means a breakage report was produced. */
|
|
102
|
+
validationOk: boolean;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ── Injected dependency types ─────────────────────────────────────────
|
|
106
|
+
|
|
107
|
+
/** Matches checkPinnedUpgrade from core. */
|
|
108
|
+
export type CheckPinnedFn = (opts: {
|
|
109
|
+
lexiconDir: string;
|
|
110
|
+
lexicon: LexiconId;
|
|
111
|
+
force?: boolean;
|
|
112
|
+
verbose?: boolean;
|
|
113
|
+
}) => Promise<UpgradeCheckResult>;
|
|
114
|
+
|
|
115
|
+
/** Matches checkRollingUpgrade from core. */
|
|
116
|
+
export type CheckRollingFn = (opts: {
|
|
117
|
+
lexiconDir: string;
|
|
118
|
+
force?: boolean;
|
|
119
|
+
verbose?: boolean;
|
|
120
|
+
}) => Promise<RollingUpgradeResult>;
|
|
121
|
+
|
|
122
|
+
/** Minimal shell-exec interface for gh/git invocations. */
|
|
123
|
+
export type GhRunner = (cmd: string) => Promise<{ stdout: string; stderr: string }>;
|
|
124
|
+
|
|
125
|
+
/** Applies a pinned version bump permanently (no revert). Async (core loads the lexicon's pin descriptor); a sync mock is also accepted. */
|
|
126
|
+
export type ApplyBumpFn = (
|
|
127
|
+
lexicon: LexiconId,
|
|
128
|
+
lexiconDir: string,
|
|
129
|
+
newVersion: string,
|
|
130
|
+
) => { filePath: string } | Promise<{ filePath: string }>;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Write a new version into a package.json, returning the file path.
|
|
134
|
+
* Injectable for tests via LexiconUpgradeArgs._bumpPackageVersion.
|
|
135
|
+
*/
|
|
136
|
+
export type BumpPackageVersionFn = (packageJsonPath: string, newVersion: string) => void;
|
|
137
|
+
|
|
138
|
+
// ── Package.json version bumping ──────────────────────────────────────
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Compute a bumped semver string from a current version and a semver label.
|
|
142
|
+
*
|
|
143
|
+
* The mapping is 0.x-aware, because promoting to 1.0.0 should signal the
|
|
144
|
+
* lexicon's own API stability, not track an upstream spec's breaking change:
|
|
145
|
+
*
|
|
146
|
+
* - Pre-1.0 (major === 0): "breaking" bumps the minor (0.13.1 → 0.14.0),
|
|
147
|
+
* "minor" (additive) bumps the patch (0.13.1 → 0.13.2). Never auto-1.0.0.
|
|
148
|
+
* - >= 1.0.0: "minor" bumps the minor (1.2.3 → 1.3.0), "breaking" bumps the
|
|
149
|
+
* major (1.2.3 → 2.0.0).
|
|
150
|
+
*
|
|
151
|
+
* Handles the common "MAJOR.MINOR.PATCH" form. Returns null when the
|
|
152
|
+
* current version string cannot be parsed as M.m.p.
|
|
153
|
+
*/
|
|
154
|
+
export function computeBumpedVersion(
|
|
155
|
+
current: string,
|
|
156
|
+
label: SemverLabel,
|
|
157
|
+
): string | null {
|
|
158
|
+
// Single source of truth for the 0.x-aware rule lives in core (#616). The
|
|
159
|
+
// pinned Op's "minor" label maps to an additive surface change; "breaking"
|
|
160
|
+
// maps straight through.
|
|
161
|
+
return bumpForSeverity(current, label === "breaking" ? "breaking" : "additive");
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// ── Classification ────────────────────────────────────────────────────
|
|
165
|
+
|
|
166
|
+
// cedar pins `CEDAR_WASM_VERSION`, a dependency version rather than a spec
|
|
167
|
+
// URL, but the pinned-constant machinery is the same (#1650).
|
|
168
|
+
const PINNED_LEXICONS: ReadonlySet<string> = new Set<LexiconId>(["k8s", "gcp", "docker", "gitlab", "cedar"]);
|
|
169
|
+
const ROLLING_LEXICONS: ReadonlySet<string> = new Set<RollingLexicon>(["aws", "azure", "github", "fly"]);
|
|
170
|
+
|
|
171
|
+
/** Return true when the lexicon uses a pinned version constant. */
|
|
172
|
+
export function isPinned(lexicon: SupportedLexicon): lexicon is LexiconId {
|
|
173
|
+
return PINNED_LEXICONS.has(lexicon);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** Return true when the lexicon follows a rolling spec (no pinned constant). */
|
|
177
|
+
export function isRolling(lexicon: SupportedLexicon): lexicon is RollingLexicon {
|
|
178
|
+
return ROLLING_LEXICONS.has(lexicon);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ── Semver labeling ───────────────────────────────────────────────────
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Map a surface severity to a semver label for the PR.
|
|
185
|
+
*
|
|
186
|
+
* "additive" → "minor" (new resources/properties added)
|
|
187
|
+
* "breaking" → "breaking" (removed or changed resources/properties)
|
|
188
|
+
* "none" → null (surface unchanged)
|
|
189
|
+
*/
|
|
190
|
+
export function severityToLabel(severity: string): SemverLabel | null {
|
|
191
|
+
if (severity === "additive") return "minor";
|
|
192
|
+
if (severity === "breaking") return "breaking";
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// ── Branch / PR naming ────────────────────────────────────────────────
|
|
197
|
+
|
|
198
|
+
/** Long-lived branch name for a lexicon upgrade PR. */
|
|
199
|
+
export function upgradeBranchName(lexicon: SupportedLexicon): string {
|
|
200
|
+
return `lexicon-upgrade/${lexicon}`;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** PR title for an upgrade. */
|
|
204
|
+
export function upgradePrTitle(
|
|
205
|
+
lexicon: SupportedLexicon,
|
|
206
|
+
from?: string,
|
|
207
|
+
to?: string | null,
|
|
208
|
+
): string {
|
|
209
|
+
if (from && to) return `feat(${lexicon}): upgrade spec ${from} to ${to}`;
|
|
210
|
+
return `feat(${lexicon}): upgrade to latest spec`;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// ── Markdown summary builder ──────────────────────────────────────────
|
|
214
|
+
|
|
215
|
+
/** Build the PR/issue/report body from the upgrade result data. */
|
|
216
|
+
export function buildUpgradeSummary(opts: {
|
|
217
|
+
lexicon: SupportedLexicon;
|
|
218
|
+
from?: string;
|
|
219
|
+
to?: string | null;
|
|
220
|
+
deltaText: string;
|
|
221
|
+
semverLabel: SemverLabel | null;
|
|
222
|
+
validationOk: boolean;
|
|
223
|
+
failures?: Array<{ step: string; output: string }>;
|
|
224
|
+
}): string {
|
|
225
|
+
const { lexicon, from, to, deltaText, semverLabel, validationOk, failures = [] } = opts;
|
|
226
|
+
|
|
227
|
+
// Example validation status (#604): the upgrade check lints the lexicon's
|
|
228
|
+
// examples (regenLexicon step 6), and an example failure makes validation
|
|
229
|
+
// fail. Surface it explicitly so the PR / drift issue states example health
|
|
230
|
+
// instead of leaving it implicit in CI. (The authoritative example *build*
|
|
231
|
+
// still runs in CI — the pinned PR's test job, and main's continuous build
|
|
232
|
+
// for rolling lexicons.)
|
|
233
|
+
const exampleFailures = failures.filter((f) => f.step === "lint" || f.step === "examples");
|
|
234
|
+
|
|
235
|
+
const lines: string[] = [`## Lexicon upgrade: ${lexicon}`];
|
|
236
|
+
if (from) lines.push(``, `**From:** \`${from}\` **To:** \`${to ?? "latest"}\``);
|
|
237
|
+
if (semverLabel) lines.push(`**Semver label:** \`${semverLabel}\``);
|
|
238
|
+
lines.push(
|
|
239
|
+
exampleFailures.length > 0
|
|
240
|
+
? `**Examples:** ⚠️ ${exampleFailures.length} check(s) failing — see Validation failures below`
|
|
241
|
+
: `**Examples:** lint clean`,
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
lines.push(``);
|
|
245
|
+
|
|
246
|
+
if (!validationOk) {
|
|
247
|
+
lines.push(`### Validation failures`);
|
|
248
|
+
lines.push(``);
|
|
249
|
+
lines.push(`Regen or validation did not pass. Review the failures before merging.`);
|
|
250
|
+
for (const f of failures) {
|
|
251
|
+
lines.push(``, `**Step: ${f.step}**`, "```", f.output.slice(0, 2000), "```");
|
|
252
|
+
}
|
|
253
|
+
lines.push(``);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (deltaText) {
|
|
257
|
+
lines.push(`### Surface delta`);
|
|
258
|
+
lines.push(``);
|
|
259
|
+
lines.push(deltaText);
|
|
260
|
+
lines.push(``);
|
|
261
|
+
} else if (validationOk) {
|
|
262
|
+
lines.push(`No surface delta detected.`);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// #616: rolling lexicons carry no version pin, so accepting drift must also
|
|
266
|
+
// bump the package version — otherwise skip-if-unchanged strands the new
|
|
267
|
+
// surface at publish time. Spell out the `--bump` re-baseline in the issue.
|
|
268
|
+
if (deltaText && isRolling(lexicon)) {
|
|
269
|
+
lines.push(`### Accepting this drift`);
|
|
270
|
+
lines.push(``);
|
|
271
|
+
lines.push(`Re-baseline and bump the version in one step (bump matches the drift severity, 0.x-aware):`);
|
|
272
|
+
lines.push(``, "```", `chant dev surface-diff lexicons/${lexicon} --update-snapshot --bump`, "```");
|
|
273
|
+
lines.push(``);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return lines.join("\n");
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// ── Shell helpers ─────────────────────────────────────────────────────
|
|
280
|
+
|
|
281
|
+
function shellQuote(s: string): string {
|
|
282
|
+
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const defaultGh: GhRunner = async (cmd) => execAsync(cmd);
|
|
286
|
+
|
|
287
|
+
// ── PR idempotency helpers ────────────────────────────────────────────
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Check whether an open PR exists for the given branch.
|
|
291
|
+
* Returns the PR URL, or null if none.
|
|
292
|
+
*/
|
|
293
|
+
async function openPrUrl(branch: string, gh: GhRunner): Promise<string | null> {
|
|
294
|
+
try {
|
|
295
|
+
const { stdout } = await gh(
|
|
296
|
+
`gh pr view ${shellQuote(branch)} --json url,state --jq 'select(.state=="OPEN") | .url'`,
|
|
297
|
+
);
|
|
298
|
+
const url = stdout.trim();
|
|
299
|
+
return url || null;
|
|
300
|
+
} catch {
|
|
301
|
+
return null;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Read the body of the open PR for `branch`, if any.
|
|
307
|
+
* Returns null when there is no open PR or gh is unavailable.
|
|
308
|
+
*/
|
|
309
|
+
async function currentPrBody(branch: string, gh: GhRunner): Promise<string | null> {
|
|
310
|
+
try {
|
|
311
|
+
const { stdout } = await gh(
|
|
312
|
+
`gh pr view ${shellQuote(branch)} --json body,state --jq 'select(.state=="OPEN") | .body'`,
|
|
313
|
+
);
|
|
314
|
+
const body = stdout.trim();
|
|
315
|
+
return body || null;
|
|
316
|
+
} catch {
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Apply or ensure a label exists on the repo, then add it to the PR.
|
|
323
|
+
* Best-effort — never throws.
|
|
324
|
+
*/
|
|
325
|
+
async function ensureLabelOnPr(branch: string, label: SemverLabel, gh: GhRunner): Promise<void> {
|
|
326
|
+
try {
|
|
327
|
+
const color = label === "breaking" ? "B60205" : "0075CA";
|
|
328
|
+
await gh(`gh label create ${shellQuote(label)} --color ${shellQuote(color)} --force`).catch(
|
|
329
|
+
() => {/* label already exists */},
|
|
330
|
+
);
|
|
331
|
+
await gh(`gh pr edit ${shellQuote(branch)} --add-label ${shellQuote(label)}`);
|
|
332
|
+
} catch {
|
|
333
|
+
// Best-effort
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// ── Real check function loaders ───────────────────────────────────────
|
|
338
|
+
|
|
339
|
+
let _realCheckPinned: CheckPinnedFn | null = null;
|
|
340
|
+
let _realCheckRolling: CheckRollingFn | null = null;
|
|
341
|
+
let _realApplyBump: ApplyBumpFn | null = null;
|
|
342
|
+
|
|
343
|
+
async function getRealCheckPinned(): Promise<CheckPinnedFn> {
|
|
344
|
+
if (!_realCheckPinned) {
|
|
345
|
+
const mod = await import("../../codegen/pinned-upgrade");
|
|
346
|
+
_realCheckPinned = (opts) => mod.checkPinnedUpgrade(opts);
|
|
347
|
+
}
|
|
348
|
+
return _realCheckPinned;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
async function getRealCheckRolling(): Promise<CheckRollingFn> {
|
|
352
|
+
if (!_realCheckRolling) {
|
|
353
|
+
const mod = await import("../../codegen/rolling-upgrade");
|
|
354
|
+
_realCheckRolling = (opts) => mod.checkRollingUpgrade(opts);
|
|
355
|
+
}
|
|
356
|
+
return _realCheckRolling;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
async function getRealApplyBump(): Promise<ApplyBumpFn> {
|
|
360
|
+
if (!_realApplyBump) {
|
|
361
|
+
const mod = await import("../../codegen/pinned-upgrade");
|
|
362
|
+
_realApplyBump = (lexicon, lexiconDir, newVersion) =>
|
|
363
|
+
mod.applyPinnedVersionBump(lexicon, lexiconDir, newVersion);
|
|
364
|
+
}
|
|
365
|
+
return _realApplyBump;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// ── Main activity ─────────────────────────────────────────────────────
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Run the lexicon upgrade check for one lexicon and surface the result.
|
|
372
|
+
*
|
|
373
|
+
* Pinned lexicons (k8s, gcp, docker, gitlab):
|
|
374
|
+
* Calls checkPinnedUpgrade. A PR is opened only when hasUpgrade=true AND
|
|
375
|
+
* validation passed. Validation failures produce a report or issue.
|
|
376
|
+
*
|
|
377
|
+
* Rolling lexicons (aws, azure, github):
|
|
378
|
+
* Calls checkRollingUpgrade. A PR is opened only when the surface changed
|
|
379
|
+
* AND validation passed. Surface unchanged = no action.
|
|
380
|
+
*
|
|
381
|
+
* In pull-request mode:
|
|
382
|
+
* - Branch: lexicon-upgrade/<lexicon> (long-lived, one per lexicon).
|
|
383
|
+
* - Idempotent: if the open PR body matches the new summary, skip re-push.
|
|
384
|
+
* - Semver label: "minor" (additive) or "breaking" (changed/removed).
|
|
385
|
+
* - Validation failure falls back to issue mode.
|
|
386
|
+
*
|
|
387
|
+
* Never auto-merges or auto-publishes.
|
|
388
|
+
*/
|
|
389
|
+
export async function lexiconUpgrade(args: LexiconUpgradeArgs): Promise<LexiconUpgradeResult> {
|
|
390
|
+
const {
|
|
391
|
+
lexicon,
|
|
392
|
+
mode = "report",
|
|
393
|
+
_gh: gh = defaultGh,
|
|
394
|
+
} = args;
|
|
395
|
+
|
|
396
|
+
const lexiconDir = args.lexiconDir ?? `${process.cwd()}/lexicons/${lexicon}`;
|
|
397
|
+
|
|
398
|
+
// ── 1. Run the appropriate check ──────────────────────────────────
|
|
399
|
+
|
|
400
|
+
let hasUpgrade: boolean;
|
|
401
|
+
let deltaText: string;
|
|
402
|
+
let severity: string;
|
|
403
|
+
let validationOk: boolean;
|
|
404
|
+
let failures: Array<{ step: string; output: string }> = [];
|
|
405
|
+
let from: string | undefined;
|
|
406
|
+
let to: string | null | undefined;
|
|
407
|
+
let freshSnapshotJson: string | null = null;
|
|
408
|
+
|
|
409
|
+
if (isPinned(lexicon)) {
|
|
410
|
+
const checkPinned = args._checkPinned ?? (await getRealCheckPinned());
|
|
411
|
+
const result = await checkPinned({ lexiconDir, lexicon });
|
|
412
|
+
|
|
413
|
+
if (result.fetchError) {
|
|
414
|
+
const summary = buildUpgradeSummary({
|
|
415
|
+
lexicon,
|
|
416
|
+
from: result.from,
|
|
417
|
+
to: result.to,
|
|
418
|
+
deltaText: "",
|
|
419
|
+
semverLabel: null,
|
|
420
|
+
validationOk: false,
|
|
421
|
+
failures: [{ step: "upstream-fetch", output: result.fetchError }],
|
|
422
|
+
});
|
|
423
|
+
return {
|
|
424
|
+
lexicon,
|
|
425
|
+
mode,
|
|
426
|
+
hasUpgrade: false,
|
|
427
|
+
deltaText: "",
|
|
428
|
+
semverLabel: null,
|
|
429
|
+
summary,
|
|
430
|
+
validationOk: false,
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
hasUpgrade = result.hasUpgrade;
|
|
435
|
+
from = result.from;
|
|
436
|
+
to = result.to;
|
|
437
|
+
severity = result.validation?.severity ?? "none";
|
|
438
|
+
deltaText = result.validation?.deltaText ?? "";
|
|
439
|
+
validationOk = result.validation?.ok ?? true;
|
|
440
|
+
failures = (result.validation?.failures ?? []).map((f) => ({ step: f.step, output: f.output }));
|
|
441
|
+
if (result.validation?.freshSnapshot) {
|
|
442
|
+
const { serializeSnapshot } = await import("../../codegen/surface-snapshot");
|
|
443
|
+
freshSnapshotJson = serializeSnapshot(result.validation.freshSnapshot);
|
|
444
|
+
}
|
|
445
|
+
} else if (isRolling(lexicon)) {
|
|
446
|
+
const checkRolling = args._checkRolling ?? (await getRealCheckRolling());
|
|
447
|
+
const result = await checkRolling({ lexiconDir });
|
|
448
|
+
|
|
449
|
+
hasUpgrade = result.hasUpgrade;
|
|
450
|
+
severity = result.severity;
|
|
451
|
+
deltaText = result.deltaText;
|
|
452
|
+
validationOk = result.validationOk;
|
|
453
|
+
failures = (result.failures ?? []).map((f) => ({ step: f.step, output: f.output }));
|
|
454
|
+
if (result.freshSnapshot) {
|
|
455
|
+
const { serializeSnapshot } = await import("../../codegen/surface-snapshot");
|
|
456
|
+
freshSnapshotJson = serializeSnapshot(result.freshSnapshot);
|
|
457
|
+
}
|
|
458
|
+
} else {
|
|
459
|
+
throw new Error(
|
|
460
|
+
`Lexicon "${lexicon as string}" is not supported by LexiconUpgradeOp. ` +
|
|
461
|
+
`Supported: k8s, gcp, docker, gitlab, aws, azure, github`,
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
const semverLabel = severityToLabel(severity);
|
|
466
|
+
const summary = buildUpgradeSummary({
|
|
467
|
+
lexicon,
|
|
468
|
+
from,
|
|
469
|
+
to,
|
|
470
|
+
deltaText,
|
|
471
|
+
semverLabel,
|
|
472
|
+
validationOk,
|
|
473
|
+
failures,
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
// ── 2. No upgrade ─────────────────────────────────────────────────
|
|
477
|
+
|
|
478
|
+
if (!hasUpgrade) {
|
|
479
|
+
return {
|
|
480
|
+
lexicon,
|
|
481
|
+
mode,
|
|
482
|
+
hasUpgrade: false,
|
|
483
|
+
deltaText,
|
|
484
|
+
semverLabel: null,
|
|
485
|
+
summary,
|
|
486
|
+
validationOk,
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// ── 3. Validation failure: surface as report or issue, never PR ───
|
|
491
|
+
|
|
492
|
+
if (!validationOk) {
|
|
493
|
+
const effectiveMode: LexiconUpgradeMode = mode === "pull-request" ? "issue" : mode;
|
|
494
|
+
if (effectiveMode === "issue") {
|
|
495
|
+
const title = `chore(${lexicon}): spec upgrade validation failed`;
|
|
496
|
+
const { stdout } = await gh(
|
|
497
|
+
`gh issue create --title ${shellQuote(title)} --body ${shellQuote(summary)}`,
|
|
498
|
+
);
|
|
499
|
+
return {
|
|
500
|
+
lexicon,
|
|
501
|
+
mode,
|
|
502
|
+
hasUpgrade: true,
|
|
503
|
+
deltaText,
|
|
504
|
+
semverLabel,
|
|
505
|
+
issueUrl: stdout.trim(),
|
|
506
|
+
summary,
|
|
507
|
+
validationOk: false,
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
return {
|
|
511
|
+
lexicon,
|
|
512
|
+
mode,
|
|
513
|
+
hasUpgrade: true,
|
|
514
|
+
deltaText,
|
|
515
|
+
semverLabel,
|
|
516
|
+
summary,
|
|
517
|
+
validationOk: false,
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// ── 4. Upgrade ready: surface according to mode ───────────────────
|
|
522
|
+
|
|
523
|
+
const title = upgradePrTitle(lexicon, from, to);
|
|
524
|
+
|
|
525
|
+
// #546: rolling lexicons have no version pin, so a "pull-request" would only
|
|
526
|
+
// refresh the baseline snapshot — low signal, no build-output change. Surface
|
|
527
|
+
// rolling drift as an issue instead; re-baselining stays a deliberate
|
|
528
|
+
// maintainer action (`chant dev surface-diff <lexicon> --update-snapshot --bump`).
|
|
529
|
+
// Pinned lexicons keep opening version-bump PRs.
|
|
530
|
+
const effectiveMode: LexiconUpgradeMode =
|
|
531
|
+
mode === "pull-request" && isRolling(lexicon) ? "issue" : mode;
|
|
532
|
+
|
|
533
|
+
if (effectiveMode === "report") {
|
|
534
|
+
return {
|
|
535
|
+
lexicon,
|
|
536
|
+
mode: effectiveMode,
|
|
537
|
+
hasUpgrade: true,
|
|
538
|
+
deltaText,
|
|
539
|
+
semverLabel,
|
|
540
|
+
summary,
|
|
541
|
+
validationOk: true,
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
if (effectiveMode === "issue") {
|
|
546
|
+
const { stdout } = await gh(
|
|
547
|
+
`gh issue create --title ${shellQuote(title)} --body ${shellQuote(summary)}`,
|
|
548
|
+
);
|
|
549
|
+
return {
|
|
550
|
+
lexicon,
|
|
551
|
+
mode: effectiveMode,
|
|
552
|
+
hasUpgrade: true,
|
|
553
|
+
deltaText,
|
|
554
|
+
semverLabel,
|
|
555
|
+
issueUrl: stdout.trim(),
|
|
556
|
+
summary,
|
|
557
|
+
validationOk: true,
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// ── 5. pull-request mode: idempotent branch + PR management ──────
|
|
562
|
+
|
|
563
|
+
const branch = upgradeBranchName(lexicon);
|
|
564
|
+
|
|
565
|
+
// Idempotency check: if the open PR already has this summary, nothing changed.
|
|
566
|
+
// Compare trimmed — gh/git round-trips can alter trailing whitespace.
|
|
567
|
+
const existingPrBody = await currentPrBody(branch, gh);
|
|
568
|
+
if (existingPrBody !== null && existingPrBody.trim() === summary.trim()) {
|
|
569
|
+
const existingUrl = await openPrUrl(branch, gh);
|
|
570
|
+
return {
|
|
571
|
+
lexicon,
|
|
572
|
+
mode,
|
|
573
|
+
hasUpgrade: true,
|
|
574
|
+
deltaText,
|
|
575
|
+
semverLabel,
|
|
576
|
+
prUrl: existingUrl ?? undefined,
|
|
577
|
+
summary,
|
|
578
|
+
validationOk: true,
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
// Reset/create the long-lived branch from main and commit the changes.
|
|
583
|
+
// All git shell-outs go through the injectable `gh` runner (which defaults to
|
|
584
|
+
// execAsync) so tests can mock them — a test must never touch the real repo
|
|
585
|
+
// or push to origin.
|
|
586
|
+
await gh(`git fetch origin main`);
|
|
587
|
+
await gh(
|
|
588
|
+
`git branch -f ${shellQuote(branch)} origin/main`,
|
|
589
|
+
).catch(async () => {
|
|
590
|
+
await gh(`git branch ${shellQuote(branch)} origin/main`);
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
// Save current branch, switch to upgrade branch.
|
|
594
|
+
const { stdout: currentBranch } = await gh(`git rev-parse --abbrev-ref HEAD`);
|
|
595
|
+
const savedBranch = currentBranch.trim();
|
|
596
|
+
|
|
597
|
+
await gh(`git stash --include-untracked`).catch(() => {/* nothing to stash */});
|
|
598
|
+
|
|
599
|
+
try {
|
|
600
|
+
await gh(`git checkout ${shellQuote(branch)}`);
|
|
601
|
+
|
|
602
|
+
// For pinned lexicons: apply the spec version bump permanently on this branch.
|
|
603
|
+
if (isPinned(lexicon) && to) {
|
|
604
|
+
const applyBump = args._applyBump ?? (await getRealApplyBump());
|
|
605
|
+
const { filePath } = await applyBump(lexicon, lexiconDir, to);
|
|
606
|
+
await gh(`git add ${shellQuote(filePath)}`).catch(() => {/* best-effort */});
|
|
607
|
+
|
|
608
|
+
// Bump the lexicon's package.json version so merging this PR causes
|
|
609
|
+
// publish-on-merge to ship exactly this lexicon (minor → minor bump,
|
|
610
|
+
// breaking → major bump). Rolling lexicons are excluded — they use
|
|
611
|
+
// drift-issues (#546) and do not pin to a version constant.
|
|
612
|
+
if (semverLabel) {
|
|
613
|
+
const pkgJsonPath = join(lexiconDir, "package.json");
|
|
614
|
+
const raw = readFileSync(pkgJsonPath, "utf-8");
|
|
615
|
+
const pkg = JSON.parse(raw) as { version?: string };
|
|
616
|
+
const currentVersion = pkg.version ?? "0.0.0";
|
|
617
|
+
const bumpedVersion = computeBumpedVersion(currentVersion, semverLabel);
|
|
618
|
+
if (bumpedVersion) {
|
|
619
|
+
const doBump = args._bumpPackageVersion ?? bumpPackageJsonVersion;
|
|
620
|
+
doBump(pkgJsonPath, bumpedVersion);
|
|
621
|
+
await gh(`git add ${shellQuote(pkgJsonPath)}`).catch(() => {/* best-effort */});
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
// Write and stage the fresh surface snapshot.
|
|
627
|
+
if (freshSnapshotJson) {
|
|
628
|
+
const { SNAPSHOT_FILENAME } = await import("../../codegen/lexicon-regen");
|
|
629
|
+
const snapshotPath = join(lexiconDir, SNAPSHOT_FILENAME);
|
|
630
|
+
writeFileSync(snapshotPath, freshSnapshotJson, "utf-8");
|
|
631
|
+
await gh(`git add ${shellQuote(snapshotPath)}`).catch(() => {/* best-effort */});
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
await gh(`git commit -m ${shellQuote(title)} --allow-empty`);
|
|
635
|
+
|
|
636
|
+
// Push to origin — force-with-lease, then fall back to force on first push.
|
|
637
|
+
await gh(`git push -u origin ${shellQuote(branch)} --force-with-lease`).catch(async () => {
|
|
638
|
+
await gh(`git push -u origin ${shellQuote(branch)} --force`);
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
// Open or update the PR.
|
|
642
|
+
const existingUrl = await openPrUrl(branch, gh);
|
|
643
|
+
let prUrl: string;
|
|
644
|
+
|
|
645
|
+
if (existingUrl) {
|
|
646
|
+
await gh(`gh pr edit ${shellQuote(branch)} --title ${shellQuote(title)} --body ${shellQuote(summary)}`);
|
|
647
|
+
prUrl = existingUrl;
|
|
648
|
+
} else {
|
|
649
|
+
const { stdout } = await gh(
|
|
650
|
+
`gh pr create --title ${shellQuote(title)} --body ${shellQuote(summary)} --head ${shellQuote(branch)} --base main`,
|
|
651
|
+
);
|
|
652
|
+
prUrl = stdout.trim();
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
if (semverLabel) {
|
|
656
|
+
await ensureLabelOnPr(branch, semverLabel, gh);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
return {
|
|
660
|
+
lexicon,
|
|
661
|
+
mode,
|
|
662
|
+
hasUpgrade: true,
|
|
663
|
+
deltaText,
|
|
664
|
+
semverLabel,
|
|
665
|
+
prUrl,
|
|
666
|
+
summary,
|
|
667
|
+
validationOk: true,
|
|
668
|
+
};
|
|
669
|
+
} finally {
|
|
670
|
+
await gh(`git checkout ${shellQuote(savedBranch)}`).catch(() => {/* best-effort */});
|
|
671
|
+
await gh(`git stash pop`).catch(() => {/* nothing to pop */});
|
|
672
|
+
}
|
|
673
|
+
}
|