@intentius/chant 0.124.46 → 0.124.48
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/__golden__/wave-loop/op-by-apply-after-fails.json +10 -0
- package/dist/__golden__/wave-loop/op-by-apply-hold.json +10 -0
- package/dist/__golden__/wave-loop/op-by-apply-ignored.json +10 -0
- package/dist/__golden__/wave-loop/op-by-apply-pass.json +10 -0
- package/dist/__golden__/wave-loop/op-by-apply-skip.json +10 -0
- package/dist/__golden__/wave-loop/op-cost-member-clash.json +6 -0
- package/dist/__golden__/wave-loop/op-cost-member.json +13 -0
- package/dist/__golden__/wave-loop/op-denied-source.json +16 -0
- package/dist/__golden__/wave-loop/op-denied.json +16 -0
- package/dist/__golden__/wave-loop/op-discover-rest-short.json +6 -0
- package/dist/__golden__/wave-loop/op-discover-rest-stops.json +13 -0
- package/dist/__golden__/wave-loop/op-discover-rest.json +26 -0
- package/dist/__golden__/wave-loop/op-discover-wide.json +26 -0
- package/dist/__golden__/wave-loop/op-held-on-again.json +16 -0
- package/dist/__golden__/wave-loop/op-held-on-before-apply.json +16 -0
- package/dist/__golden__/wave-loop/op-held-on.json +16 -0
- package/dist/__golden__/wave-loop/op-hooks-apply-fails.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-fail-after-apply.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-fail-before-apply.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-fail-before-plan.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-held.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-hold-before-apply.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-pass.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-refused-at-base.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-share.json +33 -0
- package/dist/__golden__/wave-loop/op-outcome-held.json +10 -0
- package/dist/__golden__/wave-loop/op-outcome-replan-approved.json +10 -0
- package/dist/__golden__/wave-loop/op-outcome-replan-forever.json +10 -0
- package/dist/__golden__/wave-loop/op-outcome-replan.json +10 -0
- package/dist/__golden__/wave-loop/op-outcome-stood-down.json +10 -0
- package/dist/__golden__/wave-loop/op-outcome-unreadable.json +10 -0
- package/dist/__golden__/wave-loop/op-overridden.json +16 -0
- package/dist/__golden__/wave-loop/op-per-run.json +20 -0
- package/dist/__golden__/wave-loop/op-point.json +13 -0
- package/dist/__golden__/wave-loop/op-pr-review.json +10 -0
- package/dist/__golden__/wave-loop/op-sealed.json +10 -0
- package/dist/__golden__/wave-loop/op-spend-change-only.json +10 -0
- package/dist/__golden__/wave-loop/op-spend.json +10 -0
- package/dist/__golden__/wave-loop/op-wave-commands.json +55 -0
- package/dist/__golden__/wave-loop/op-wide-refused.json +26 -0
- package/dist/__golden__/wave-loop/op-wide-waiting.json +29 -0
- package/dist/__golden__/wave-loop/op-wide.json +39 -0
- package/dist/action-pins.d.ts +61 -0
- package/dist/action-pins.d.ts.map +1 -0
- package/dist/action-pins.js +77 -0
- package/dist/cli/commands/carve.d.ts +3 -0
- package/dist/cli/commands/carve.d.ts.map +1 -1
- package/dist/cli/commands/carve.js +36 -7
- package/dist/cli/commands/import-report.d.ts +26 -0
- package/dist/cli/commands/import-report.d.ts.map +1 -0
- package/dist/cli/commands/import-report.js +65 -0
- package/dist/cli/commands/import.d.ts +11 -1
- package/dist/cli/commands/import.d.ts.map +1 -1
- package/dist/cli/commands/import.js +22 -3
- package/dist/cli/commands/migrate.d.ts +13 -1
- package/dist/cli/commands/migrate.d.ts.map +1 -1
- package/dist/cli/commands/migrate.js +134 -10
- package/dist/cli/handlers/approve.d.ts.map +1 -1
- package/dist/cli/handlers/approve.js +21 -2
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/build.js +6 -1
- package/dist/cli/handlers/ledger.d.ts +3 -0
- package/dist/cli/handlers/ledger.d.ts.map +1 -0
- package/dist/cli/handlers/ledger.js +55 -0
- package/dist/cli/handlers/migrate.d.ts.map +1 -1
- package/dist/cli/handlers/migrate.js +18 -11
- package/dist/cli/handlers/misc.d.ts.map +1 -1
- package/dist/cli/handlers/misc.js +12 -1
- package/dist/cli/handlers/pr-env.js +2 -2
- package/dist/cli/handlers/pr.d.ts +15 -1
- package/dist/cli/handlers/pr.d.ts.map +1 -1
- package/dist/cli/handlers/pr.js +143 -39
- package/dist/cli/handlers/query.d.ts +7 -2
- package/dist/cli/handlers/query.d.ts.map +1 -1
- package/dist/cli/handlers/query.js +16 -4
- package/dist/cli/handlers/release.d.ts.map +1 -1
- package/dist/cli/handlers/release.js +6 -3
- package/dist/cli/handlers/search.d.ts +2 -4
- package/dist/cli/handlers/search.d.ts.map +1 -1
- package/dist/cli/handlers/search.js +13 -39
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +65 -14
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +36 -2
- package/dist/cli/registry.d.ts +14 -4
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/components/builders.d.ts +5 -1
- package/dist/components/builders.d.ts.map +1 -1
- package/dist/components/builders.js +5 -0
- package/dist/components/capability-plugin-loader.d.ts.map +1 -1
- package/dist/components/capability-plugin-loader.js +16 -1
- package/dist/components/capability-plugin.d.ts +14 -0
- package/dist/components/capability-plugin.d.ts.map +1 -1
- package/dist/components/pr-hooks.d.ts +21 -1
- package/dist/components/pr-hooks.d.ts.map +1 -1
- package/dist/components/pr-hooks.js +72 -4
- package/dist/components/pr-pipeline.d.ts +45 -10
- package/dist/components/pr-pipeline.d.ts.map +1 -1
- package/dist/components/pr-pipeline.js +47 -14
- package/dist/components/pr-policy.d.ts +36 -0
- package/dist/components/pr-policy.d.ts.map +1 -1
- package/dist/components/pr-policy.js +36 -0
- package/dist/components/starter-plugin.d.ts +1 -0
- package/dist/components/starter-plugin.d.ts.map +1 -1
- package/dist/components/starter-plugin.js +5 -1
- package/dist/components/verbs/index.d.ts +2 -0
- package/dist/components/verbs/index.d.ts.map +1 -1
- package/dist/components/verbs/index.js +2 -0
- package/dist/components/verbs/publish-artifact.d.ts +65 -0
- package/dist/components/verbs/publish-artifact.d.ts.map +1 -0
- package/dist/components/verbs/publish-artifact.js +74 -0
- package/dist/components/verbs/publish-image.d.ts +129 -0
- package/dist/components/verbs/publish-image.d.ts.map +1 -0
- package/dist/components/verbs/publish-image.js +145 -0
- package/dist/config-environments.d.ts +20 -0
- package/dist/config-environments.d.ts.map +1 -1
- package/dist/config-environments.js +12 -0
- package/dist/config.d.ts +9 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +6 -2
- package/dist/gate-decision.d.ts +11 -2
- package/dist/gate-decision.d.ts.map +1 -1
- package/dist/gate-decision.js +15 -3
- package/dist/graph-ir.d.ts +25 -0
- package/dist/graph-ir.d.ts.map +1 -1
- package/dist/graph-walk.d.ts +66 -0
- package/dist/graph-walk.d.ts.map +1 -0
- package/dist/graph-walk.js +70 -0
- package/dist/import/parser.d.ts +19 -0
- package/dist/import/parser.d.ts.map +1 -1
- package/dist/lexicon.d.ts +71 -6
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.d.ts +11 -0
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/git.d.ts +2 -5
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lifecycle/ledger-read.d.ts +65 -0
- package/dist/lifecycle/ledger-read.d.ts.map +1 -0
- package/dist/lifecycle/ledger-read.js +160 -0
- package/dist/lifecycle/release-workstation.d.ts +7 -0
- package/dist/lifecycle/release-workstation.d.ts.map +1 -1
- package/dist/lifecycle/release-workstation.js +25 -0
- package/dist/lifecycle/run-ledger.d.ts +4 -3
- package/dist/lifecycle/run-ledger.d.ts.map +1 -1
- package/dist/lifecycle/run-ledger.js +1 -0
- package/dist/lint/discover.js +3 -1
- package/dist/lint/post-synth.d.ts +127 -1
- package/dist/lint/post-synth.d.ts.map +1 -1
- package/dist/lint/post-synth.js +84 -2
- package/dist/lint/rules/op/index.d.ts +1 -0
- package/dist/lint/rules/op/index.d.ts.map +1 -1
- package/dist/lint/rules/op/index.js +2 -0
- package/dist/lint/rules/op/ops019-workspace-op-target.d.ts +32 -0
- package/dist/lint/rules/op/ops019-workspace-op-target.d.ts.map +1 -0
- package/dist/lint/rules/op/ops019-workspace-op-target.js +63 -0
- package/dist/op/activities/activity-contracts.d.ts +5 -2
- package/dist/op/activities/activity-contracts.d.ts.map +1 -1
- package/dist/op/activities/activity-contracts.js +5 -2
- package/dist/op/activities/index.d.ts +2 -2
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/activities/index.js +1 -1
- package/dist/op/activities/review-agent.d.ts +90 -4
- package/dist/op/activities/review-agent.d.ts.map +1 -1
- package/dist/op/activities/review-agent.js +217 -19
- package/dist/op/activities/work-evidence.d.ts +8 -1
- package/dist/op/activities/work-evidence.d.ts.map +1 -1
- package/dist/op/activities/work-evidence.js +1 -0
- package/dist/op/builders.d.ts +9 -5
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/builders.js +9 -5
- package/dist/op/composites/apply-op.d.ts +29 -2
- package/dist/op/composites/apply-op.d.ts.map +1 -1
- package/dist/op/composites/apply-op.js +20 -1
- package/dist/op/gate-approval.d.ts +11 -5
- package/dist/op/gate-approval.d.ts.map +1 -1
- package/dist/op/gate-approval.js +11 -6
- package/dist/op/gate-quorum.d.ts +100 -3
- package/dist/op/gate-quorum.d.ts.map +1 -1
- package/dist/op/gate-quorum.js +108 -6
- package/dist/op/gate-review.d.ts +9 -0
- package/dist/op/gate-review.d.ts.map +1 -1
- package/dist/op/gate-review.js +13 -0
- package/dist/op/gate.d.ts +44 -3
- package/dist/op/gate.d.ts.map +1 -1
- package/dist/op/gate.js +25 -4
- package/dist/op/index.d.ts +3 -3
- package/dist/op/index.d.ts.map +1 -1
- package/dist/op/index.js +1 -1
- package/dist/op/local-executor.d.ts +38 -3
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/local-executor.js +48 -6
- package/dist/op/op-waves-run.d.ts +26 -1
- package/dist/op/op-waves-run.d.ts.map +1 -1
- package/dist/op/op-waves-run.js +259 -13
- package/dist/op/op-waves.d.ts +72 -5
- package/dist/op/op-waves.d.ts.map +1 -1
- package/dist/op/op-waves.js +110 -15
- package/dist/op/runtime.d.ts +11 -0
- package/dist/op/runtime.d.ts.map +1 -1
- package/dist/op/schedule-overdue.d.ts +16 -0
- package/dist/op/schedule-overdue.d.ts.map +1 -1
- package/dist/op/schedule-overdue.js +36 -0
- package/dist/op/stage-hooks.d.ts +9 -2
- package/dist/op/stage-hooks.d.ts.map +1 -1
- package/dist/op/stage-hooks.js +7 -5
- package/dist/op/workspace-run-env.d.ts +22 -0
- package/dist/op/workspace-run-env.d.ts.map +1 -0
- package/dist/op/workspace-run-env.js +21 -0
- package/dist/pr-forge.d.ts +24 -0
- package/dist/pr-forge.d.ts.map +1 -1
- package/dist/pr-forge.js +47 -0
- package/dist/pr-post.d.ts +42 -0
- package/dist/pr-post.d.ts.map +1 -1
- package/dist/pr-post.js +67 -1
- package/dist/read-filter.d.ts +65 -0
- package/dist/read-filter.d.ts.map +1 -0
- package/dist/read-filter.js +179 -0
- package/dist/run-event.d.ts +1 -1
- package/dist/run-event.d.ts.map +1 -1
- package/dist/terraform/carve.d.ts +24 -3
- package/dist/terraform/carve.d.ts.map +1 -1
- package/dist/terraform/carve.js +32 -14
- package/dist/terraform/cuts.d.ts +97 -0
- package/dist/terraform/cuts.d.ts.map +1 -0
- package/dist/terraform/cuts.js +138 -0
- package/dist/terraform/folds.d.ts +26 -0
- package/dist/terraform/folds.d.ts.map +1 -0
- package/dist/terraform/folds.js +38 -0
- package/dist/terraform/graph.d.ts.map +1 -1
- package/dist/terraform/graph.js +10 -0
- package/dist/terraform/reach.d.ts +140 -0
- package/dist/terraform/reach.d.ts.map +1 -0
- package/dist/terraform/reach.js +170 -0
- package/dist/terraform/score.d.ts +14 -0
- package/dist/terraform/score.d.ts.map +1 -1
- package/dist/terraform/score.js +14 -31
- package/dist/terraform/state.d.ts.map +1 -1
- package/dist/terraform/state.js +4 -2
- package/dist/terraform/types.d.ts +8 -0
- package/dist/terraform/types.d.ts.map +1 -1
- package/dist/wave-blocked.d.ts +10 -1
- package/dist/wave-blocked.d.ts.map +1 -1
- package/dist/wave-blocked.js +31 -3
- package/dist/wave-runtime.mjs +263 -254
- package/dist/workspace/check.schema.json +11 -2
- package/dist/workspace/checks/ci-branch.d.ts +44 -0
- package/dist/workspace/checks/ci-branch.d.ts.map +1 -0
- package/dist/workspace/checks/ci-branch.js +133 -0
- package/dist/workspace/checks/links.d.ts +3 -0
- package/dist/workspace/checks/links.d.ts.map +1 -1
- package/dist/workspace/checks/links.js +12 -1
- package/dist/workspace/checks/org.d.ts +48 -0
- package/dist/workspace/checks/org.d.ts.map +1 -0
- package/dist/workspace/checks/org.js +156 -0
- package/dist/workspace/checks.d.ts +11 -1
- package/dist/workspace/checks.d.ts.map +1 -1
- package/dist/workspace/checks.js +59 -7
- package/dist/workspace/ci-branches.d.ts +16 -0
- package/dist/workspace/ci-branches.d.ts.map +1 -1
- package/dist/workspace/ci-branches.js +27 -0
- package/dist/workspace/ci-green-cli.js +7 -7
- package/dist/workspace/ci-green-workflow.d.ts +1 -1
- package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
- package/dist/workspace/ci-green-workflow.js +13 -8
- package/dist/workspace/ci-green.d.ts +14 -0
- package/dist/workspace/ci-green.d.ts.map +1 -1
- package/dist/workspace/ci-green.js +44 -11
- package/dist/workspace/ci-run.d.ts +9 -1
- package/dist/workspace/ci-run.d.ts.map +1 -1
- package/dist/workspace/ci-run.js +67 -6
- package/dist/workspace/ci-serve.d.ts +9 -0
- package/dist/workspace/ci-serve.d.ts.map +1 -1
- package/dist/workspace/ci-serve.js +114 -76
- package/dist/workspace/compose-graph.d.ts +14 -0
- package/dist/workspace/compose-graph.d.ts.map +1 -1
- package/dist/workspace/composites.d.ts +4 -1
- package/dist/workspace/composites.d.ts.map +1 -1
- package/dist/workspace/composites.js +5 -2
- package/dist/workspace/composites.schema.json +22 -0
- package/dist/workspace/conformance/__writer_fixture__/work/work.schema.json +105 -1
- package/dist/workspace/cross-root-lint.d.ts +56 -0
- package/dist/workspace/cross-root-lint.d.ts.map +1 -0
- package/dist/workspace/cross-root-lint.js +111 -0
- package/dist/workspace/dbt-models-reader.d.ts +44 -0
- package/dist/workspace/dbt-models-reader.d.ts.map +1 -0
- package/dist/workspace/dbt-models-reader.js +356 -0
- package/dist/workspace/dbt-project-common.d.ts +40 -0
- package/dist/workspace/dbt-project-common.d.ts.map +1 -0
- package/dist/workspace/dbt-project-common.js +106 -0
- package/dist/workspace/dbt-project-reader.d.ts +4 -3
- package/dist/workspace/dbt-project-reader.d.ts.map +1 -1
- package/dist/workspace/dbt-project-reader.js +14 -108
- package/dist/workspace/decision-rank.d.ts +26 -0
- package/dist/workspace/decision-rank.d.ts.map +1 -0
- package/dist/workspace/decision-rank.js +16 -0
- package/dist/workspace/declaration.d.ts +43 -2
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.js +45 -11
- package/dist/workspace/declaration.schema.json +133 -24
- package/dist/workspace/environments.d.ts +26 -2
- package/dist/workspace/environments.d.ts.map +1 -1
- package/dist/workspace/environments.js +26 -2
- package/dist/workspace/flyway-dir.d.ts +39 -0
- package/dist/workspace/flyway-dir.d.ts.map +1 -0
- package/dist/workspace/flyway-dir.js +104 -0
- package/dist/workspace/flyway-layout.d.ts +96 -0
- package/dist/workspace/flyway-layout.d.ts.map +1 -0
- package/dist/workspace/flyway-layout.js +308 -0
- package/dist/workspace/graph-cli.d.ts.map +1 -1
- package/dist/workspace/graph-cli.js +26 -8
- package/dist/workspace/graph.schema.json +34 -0
- package/dist/workspace/intent.d.ts +2 -3
- package/dist/workspace/intent.d.ts.map +1 -1
- package/dist/workspace/intent.js +5 -9
- package/dist/workspace/kind-link-readers.d.ts +59 -2
- package/dist/workspace/kind-link-readers.d.ts.map +1 -1
- package/dist/workspace/kind-link-readers.js +17 -1
- package/dist/workspace/kinds.d.ts +66 -2
- package/dist/workspace/kinds.d.ts.map +1 -1
- package/dist/workspace/kinds.js +98 -4
- package/dist/workspace/ledger.schema.json +158 -0
- package/dist/workspace/lexicon-outputs.d.ts +20 -1
- package/dist/workspace/lexicon-outputs.d.ts.map +1 -1
- package/dist/workspace/lexicon-outputs.js +102 -10
- package/dist/workspace/lineage-check.d.ts +3 -0
- package/dist/workspace/lineage-check.d.ts.map +1 -1
- package/dist/workspace/lineage-check.js +23 -4
- package/dist/workspace/links.d.ts +8 -1
- package/dist/workspace/links.d.ts.map +1 -1
- package/dist/workspace/links.js +25 -1
- package/dist/workspace/ls.d.ts +8 -0
- package/dist/workspace/ls.d.ts.map +1 -1
- package/dist/workspace/ls.js +7 -1
- package/dist/workspace/ls.schema.json +7 -0
- package/dist/workspace/member-commands.d.ts.map +1 -1
- package/dist/workspace/member-commands.js +54 -5
- package/dist/workspace/migrate-links.d.ts +45 -0
- package/dist/workspace/migrate-links.d.ts.map +1 -0
- package/dist/workspace/migrate-links.js +100 -0
- package/dist/workspace/migration-dirs.d.ts +74 -0
- package/dist/workspace/migration-dirs.d.ts.map +1 -0
- package/dist/workspace/migration-dirs.js +254 -0
- package/dist/workspace/reason-codes.d.ts +8 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +11 -0
- package/dist/workspace/records-cli.d.ts +11 -0
- package/dist/workspace/records-cli.d.ts.map +1 -1
- package/dist/workspace/records-cli.js +57 -5
- package/dist/workspace/records.schema.json +5 -0
- package/dist/workspace/release-candidates.d.ts +2 -0
- package/dist/workspace/release-candidates.d.ts.map +1 -1
- package/dist/workspace/release-candidates.js +5 -2
- package/dist/workspace/release-train.d.ts +53 -0
- package/dist/workspace/release-train.d.ts.map +1 -0
- package/dist/workspace/release-train.js +134 -0
- package/dist/workspace/release-workflow.d.ts.map +1 -1
- package/dist/workspace/release-workflow.js +4 -3
- package/dist/workspace/repo-ref.d.ts +45 -0
- package/dist/workspace/repo-ref.d.ts.map +1 -0
- package/dist/workspace/repo-ref.js +114 -0
- package/dist/workspace/run-event.schema.json +2 -2
- package/dist/workspace/runs-cli.d.ts +9 -0
- package/dist/workspace/runs-cli.d.ts.map +1 -1
- package/dist/workspace/runs-cli.js +48 -3
- package/dist/workspace/runs.schema.json +7 -0
- package/dist/workspace/search-contract.d.ts +1 -1
- package/dist/workspace/search-contract.d.ts.map +1 -1
- package/dist/workspace/status-decisions.d.ts +37 -0
- package/dist/workspace/status-decisions.d.ts.map +1 -0
- package/dist/workspace/status-decisions.js +147 -0
- package/dist/workspace/status-gates.d.ts +9 -0
- package/dist/workspace/status-gates.d.ts.map +1 -1
- package/dist/workspace/status.d.ts +4 -0
- package/dist/workspace/status.d.ts.map +1 -1
- package/dist/workspace/status.js +14 -2
- package/dist/workspace/status.schema.json +6 -0
- package/dist/workspace/work-cli.d.ts.map +1 -1
- package/dist/workspace/work-cli.js +5 -3
- package/dist/workspace/work-evidence-ops.d.ts +83 -0
- package/dist/workspace/work-evidence-ops.d.ts.map +1 -0
- package/dist/workspace/work-evidence-ops.js +169 -0
- package/dist/workspace/work-evidence.d.ts +12 -2
- package/dist/workspace/work-evidence.d.ts.map +1 -1
- package/dist/workspace/work-evidence.js +21 -3
- package/dist/workspace/work-evidence.schema.json +49 -2
- package/dist/workspace/workspace-gates.d.ts +110 -0
- package/dist/workspace/workspace-gates.d.ts.map +1 -0
- package/dist/workspace/workspace-gates.js +140 -0
- package/dist/workspace/workspace-kinds.schema.json +58 -3
- package/dist/workspace/workspace-ledger.d.ts +76 -0
- package/dist/workspace/workspace-ledger.d.ts.map +1 -0
- package/dist/workspace/workspace-ledger.js +91 -0
- package/dist/workspace/workspace-run.d.ts +112 -0
- package/dist/workspace/workspace-run.d.ts.map +1 -0
- package/dist/workspace/workspace-run.js +432 -0
- package/package.json +1 -1
- package/src/__golden__/wave-loop/op-by-apply-after-fails.json +10 -0
- package/src/__golden__/wave-loop/op-by-apply-hold.json +10 -0
- package/src/__golden__/wave-loop/op-by-apply-ignored.json +10 -0
- package/src/__golden__/wave-loop/op-by-apply-pass.json +10 -0
- package/src/__golden__/wave-loop/op-by-apply-skip.json +10 -0
- package/src/__golden__/wave-loop/op-cost-member-clash.json +6 -0
- package/src/__golden__/wave-loop/op-cost-member.json +13 -0
- package/src/__golden__/wave-loop/op-denied-source.json +16 -0
- package/src/__golden__/wave-loop/op-denied.json +16 -0
- package/src/__golden__/wave-loop/op-discover-rest-short.json +6 -0
- package/src/__golden__/wave-loop/op-discover-rest-stops.json +13 -0
- package/src/__golden__/wave-loop/op-discover-rest.json +26 -0
- package/src/__golden__/wave-loop/op-discover-wide.json +26 -0
- package/src/__golden__/wave-loop/op-held-on-again.json +16 -0
- package/src/__golden__/wave-loop/op-held-on-before-apply.json +16 -0
- package/src/__golden__/wave-loop/op-held-on.json +16 -0
- package/src/__golden__/wave-loop/op-hooks-apply-fails.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-fail-after-apply.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-fail-before-apply.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-fail-before-plan.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-held.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-hold-before-apply.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-pass.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-refused-at-base.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-share.json +33 -0
- package/src/__golden__/wave-loop/op-outcome-held.json +10 -0
- package/src/__golden__/wave-loop/op-outcome-replan-approved.json +10 -0
- package/src/__golden__/wave-loop/op-outcome-replan-forever.json +10 -0
- package/src/__golden__/wave-loop/op-outcome-replan.json +10 -0
- package/src/__golden__/wave-loop/op-outcome-stood-down.json +10 -0
- package/src/__golden__/wave-loop/op-outcome-unreadable.json +10 -0
- package/src/__golden__/wave-loop/op-overridden.json +16 -0
- package/src/__golden__/wave-loop/op-per-run.json +20 -0
- package/src/__golden__/wave-loop/op-point.json +13 -0
- package/src/__golden__/wave-loop/op-pr-review.json +10 -0
- package/src/__golden__/wave-loop/op-sealed.json +10 -0
- package/src/__golden__/wave-loop/op-spend-change-only.json +10 -0
- package/src/__golden__/wave-loop/op-spend.json +10 -0
- package/src/__golden__/wave-loop/op-wave-commands.json +55 -0
- package/src/__golden__/wave-loop/op-wide-refused.json +26 -0
- package/src/__golden__/wave-loop/op-wide-waiting.json +29 -0
- package/src/__golden__/wave-loop/op-wide.json +39 -0
- package/src/action-pins.test.ts +78 -0
- package/src/action-pins.ts +92 -0
- package/src/cli/commands/carve-score-once.test.ts +99 -0
- package/src/cli/commands/carve.ts +37 -6
- package/src/cli/commands/check-lexicon.test.ts +2 -2
- package/src/cli/commands/import-report.ts +71 -0
- package/src/cli/commands/import.ts +33 -3
- package/src/cli/commands/migrate-dialect.test.ts +145 -0
- package/src/cli/commands/migrate.ts +132 -11
- package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +4 -4
- package/src/cli/handlers/approve.ts +23 -2
- package/src/cli/handlers/build.ts +7 -1
- package/src/cli/handlers/ledger.ts +54 -0
- package/src/cli/handlers/migrate.ts +21 -12
- package/src/cli/handlers/misc.ts +10 -1
- package/src/cli/handlers/pr-env.ts +2 -2
- package/src/cli/handlers/pr.ts +138 -36
- package/src/cli/handlers/query.ts +16 -4
- package/src/cli/handlers/release.ts +6 -3
- package/src/cli/handlers/search.ts +13 -34
- package/src/cli/main.test.ts +15 -0
- package/src/cli/main.ts +65 -14
- package/src/cli/parse-args.ts +27 -2
- package/src/cli/registry.ts +14 -4
- package/src/components/builders.ts +8 -0
- package/src/components/capability-plugin-loader.ts +13 -1
- package/src/components/capability-plugin.ts +16 -0
- package/src/components/pr-hooks.test.ts +73 -5
- package/src/components/pr-hooks.ts +95 -5
- package/src/components/pr-pipeline.ts +64 -16
- package/src/components/pr-policy.test.ts +64 -1
- package/src/components/pr-policy.ts +53 -0
- package/src/components/registry.test.ts +1 -1
- package/src/components/starter-plugin.ts +6 -0
- package/src/components/verbs/index.ts +2 -0
- package/src/components/verbs/publish-artifact.test.ts +60 -0
- package/src/components/verbs/publish-artifact.ts +122 -0
- package/src/components/verbs/publish-image.test.ts +101 -0
- package/src/components/verbs/publish-image.ts +265 -0
- package/src/config-environments.ts +28 -1
- package/src/config.ts +8 -1
- package/src/gate-decision-bundle.test.ts +1 -0
- package/src/gate-decision-identity.test.ts +9 -0
- package/src/gate-decision.ts +26 -3
- package/src/graph-ir.ts +27 -0
- package/src/graph-walk.test.ts +44 -0
- package/src/graph-walk.ts +102 -0
- package/src/import/parser.ts +20 -0
- package/src/lexicon.ts +74 -6
- package/src/lifecycle/gate-ledger.ts +8 -0
- package/src/lifecycle/git.ts +2 -2
- package/src/lifecycle/ledger-read.test.ts +107 -0
- package/src/lifecycle/ledger-read.ts +195 -0
- package/src/lifecycle/release-workstation.ts +24 -0
- package/src/lifecycle/run-ledger.ts +5 -2
- package/src/lint/cross-root.test.ts +122 -0
- package/src/lint/discover.ts +3 -1
- package/src/lint/post-synth.ts +212 -2
- package/src/lint/rules/op/index.ts +2 -0
- package/src/lint/rules/op/ops019-workspace-op-target.ts +89 -0
- package/src/op/activities/activity-contracts.ts +5 -2
- package/src/op/activities/index.ts +2 -2
- package/src/op/activities/review-agent.test.ts +221 -4
- package/src/op/activities/review-agent.ts +265 -22
- package/src/op/activities/work-evidence.ts +9 -1
- package/src/op/builders.ts +9 -5
- package/src/op/composites/apply-op.test.ts +108 -0
- package/src/op/composites/apply-op.ts +37 -2
- package/src/op/gate-approval.test.ts +6 -1
- package/src/op/gate-approval.ts +12 -6
- package/src/op/gate-quorum-at-base.test.ts +211 -0
- package/src/op/gate-quorum.ts +156 -8
- package/src/op/gate-review.ts +14 -0
- package/src/op/gate.ts +67 -8
- package/src/op/index.ts +3 -2
- package/src/op/local-executor.ts +69 -9
- package/src/op/op-waves-depends-on.test.ts +81 -0
- package/src/op/op-waves-hook-targets.test.ts +4 -2
- package/src/op/op-waves-quorum-product.test.ts +158 -0
- package/src/op/op-waves-run.ts +288 -14
- package/src/op/op-waves.ts +143 -14
- package/src/op/runtime.ts +8 -0
- package/src/op/schedule-overdue.ts +33 -0
- package/src/op/stage-hooks.ts +13 -5
- package/src/op/workspace-run-env.ts +29 -0
- package/src/pr-forge-bundle.test.ts +2 -2
- package/src/pr-forge.test.ts +47 -0
- package/src/pr-forge.ts +68 -0
- package/src/pr-post-open.e2e.test.ts +36 -0
- package/src/pr-post.test.ts +102 -3
- package/src/pr-post.ts +89 -1
- package/src/read-filter.test.ts +54 -0
- package/src/read-filter.ts +193 -0
- package/src/run-event.ts +1 -1
- package/src/stage-hooks-bundle.test.ts +1 -0
- package/src/terraform/carve.ts +52 -15
- package/src/terraform/cuts.test.ts +173 -0
- package/src/terraform/cuts.ts +188 -0
- package/src/terraform/folds.ts +44 -0
- package/src/terraform/graph.ts +9 -0
- package/src/terraform/radius.test.ts +90 -0
- package/src/terraform/reach.test.ts +146 -0
- package/src/terraform/reach.ts +247 -0
- package/src/terraform/score.ts +27 -29
- package/src/terraform/state.ts +3 -1
- package/src/terraform/types.ts +8 -0
- package/src/wave-blocked.ts +28 -3
- package/src/wave-loop-golden.test.ts +4 -3
- package/src/workspace/behold-kinds.test.ts +1 -1
- package/src/workspace/check-contract.test.ts +7 -6
- package/src/workspace/check.schema.json +11 -2
- package/src/workspace/checks/ci-branch.test.ts +128 -0
- package/src/workspace/checks/ci-branch.ts +141 -0
- package/src/workspace/checks/links.ts +12 -1
- package/src/workspace/checks/org.ts +169 -0
- package/src/workspace/checks.ts +64 -7
- package/src/workspace/ci-branches.ts +31 -0
- package/src/workspace/ci-green-branches.test.ts +153 -0
- package/src/workspace/ci-green-cli.ts +7 -7
- package/src/workspace/ci-green-workflow.test.ts +4 -3
- package/src/workspace/ci-green-workflow.ts +13 -9
- package/src/workspace/ci-green.ts +49 -12
- package/src/workspace/ci-run.test.ts +72 -1
- package/src/workspace/ci-run.ts +68 -8
- package/src/workspace/ci-serve.test.ts +95 -0
- package/src/workspace/ci-serve.ts +106 -65
- package/src/workspace/component-environments.test.ts +25 -2
- package/src/workspace/compose-graph.ts +9 -2
- package/src/workspace/composites.schema.json +22 -0
- package/src/workspace/composites.test.ts +39 -8
- package/src/workspace/composites.ts +6 -2
- package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +105 -1
- package/src/workspace/cross-root-lint.test.ts +90 -0
- package/src/workspace/cross-root-lint.ts +126 -0
- package/src/workspace/dbt-kind.test.ts +3 -2
- package/src/workspace/dbt-models-reader.ts +362 -0
- package/src/workspace/dbt-models.test.ts +248 -0
- package/src/workspace/dbt-project-common.ts +113 -0
- package/src/workspace/dbt-project-reader.ts +29 -112
- package/src/workspace/decision-rank.ts +40 -0
- package/src/workspace/declaration.schema.json +133 -24
- package/src/workspace/declaration.ts +84 -15
- package/src/workspace/environments.ts +40 -4
- package/src/workspace/flyway-dir.ts +113 -0
- package/src/workspace/flyway-layout.ts +337 -0
- package/src/workspace/graph-cli.ts +25 -10
- package/src/workspace/graph-contract.test.ts +4 -2
- package/src/workspace/graph.schema.json +34 -0
- package/src/workspace/identity.test.ts +14 -2
- package/src/workspace/intent.ts +6 -14
- package/src/workspace/kind-link-readers.ts +68 -3
- package/src/workspace/kinds.test.ts +12 -7
- package/src/workspace/kinds.ts +132 -7
- package/src/workspace/ledger.schema.json +158 -0
- package/src/workspace/lexicon-outputs.ts +132 -13
- package/src/workspace/lineage-check.ts +30 -7
- package/src/workspace/links.ts +24 -1
- package/src/workspace/ls-contract.test.ts +1 -1
- package/src/workspace/ls.schema.json +7 -0
- package/src/workspace/ls.ts +10 -1
- package/src/workspace/member-commands.ts +60 -2
- package/src/workspace/member-file-schema.test.ts +124 -0
- package/src/workspace/migrate-links.test.ts +99 -0
- package/src/workspace/migrate-links.ts +108 -0
- package/src/workspace/migration-dirs.test.ts +272 -0
- package/src/workspace/migration-dirs.ts +267 -0
- package/src/workspace/org-scope.test.ts +238 -0
- package/src/workspace/reason-codes.test.ts +6 -1
- package/src/workspace/reason-codes.ts +11 -0
- package/src/workspace/records-cli.ts +58 -5
- package/src/workspace/records.schema.json +5 -0
- package/src/workspace/release-candidates.ts +7 -2
- package/src/workspace/release-train.ts +157 -0
- package/src/workspace/release-workflow.ts +4 -3
- package/src/workspace/repo-ref.ts +113 -0
- package/src/workspace/run-event.schema.json +2 -2
- package/src/workspace/runs-cli.ts +48 -4
- package/src/workspace/runs.schema.json +7 -0
- package/src/workspace/status-contract.test.ts +46 -1
- package/src/workspace/status-decisions.test.ts +100 -0
- package/src/workspace/status-decisions.ts +151 -0
- package/src/workspace/status-gates.ts +9 -0
- package/src/workspace/status.schema.json +6 -0
- package/src/workspace/status.ts +17 -3
- package/src/workspace/where-filters.test.ts +39 -0
- package/src/workspace/work-cli.ts +5 -3
- package/src/workspace/work-evidence-ops.test.ts +176 -0
- package/src/workspace/work-evidence-ops.ts +189 -0
- package/src/workspace/work-evidence.schema.json +49 -2
- package/src/workspace/work-evidence.ts +22 -3
- package/src/workspace/workspace-gates.ts +200 -0
- package/src/workspace/workspace-kinds.schema.json +58 -3
- package/src/workspace/workspace-ledger.ts +130 -0
- package/src/workspace/workspace-run.test.ts +322 -0
- package/src/workspace/workspace-run.ts +461 -0
package/src/cli/main.ts
CHANGED
|
@@ -183,7 +183,14 @@ Commands:
|
|
|
183
183
|
the resources and snapshots each lexicon observed, Op
|
|
184
184
|
runs, gates, deploys, releases and cuts, loaded into
|
|
185
185
|
node:sqlite (schema v1, listed in chant_schema).
|
|
186
|
-
--member <name> keeps members; --json prints rows
|
|
186
|
+
--member <name> keeps members; --json prints rows.
|
|
187
|
+
For a read contract, use chant ledger
|
|
188
|
+
ledger <table> [dir] One ledger's rows from chant/lifecycle as a read
|
|
189
|
+
contract (resources, snapshots, runs, gates, deploys,
|
|
190
|
+
releases, cuts; the columns chant query loads).
|
|
191
|
+
--where <field><op><value> (= != < <= > >= ~,
|
|
192
|
+
repeatable), --since <time|7d>, --at <rev> of
|
|
193
|
+
chant/lifecycle, --member <name>, --json
|
|
187
194
|
generate Generate typed code from sources chant.config declares
|
|
188
195
|
(k8s.crds, helm.charts) into src/generated/<lexicon>/
|
|
189
196
|
(codegen.outDir); --check exits 1 when the committed
|
|
@@ -626,7 +633,7 @@ Workspace (level 1, #2524):
|
|
|
626
633
|
restore, from the deploy records, releases and ci
|
|
627
634
|
revoked tags. Eight weeks back by default. Read only;
|
|
628
635
|
never fetches. --json prints the read-contract document
|
|
629
|
-
workspace records [--kind <kind file>] [--current] [--uncommitted | --at <rev>] [--base <rev>] [--require attested] [--json]
|
|
636
|
+
workspace records [--kind <kind file>] [--current] [--uncommitted | --at <rev>] [--base <rev>] [--require attested] [--where <field><op><value>]... [--json]
|
|
630
637
|
Without --kind, every record kind the declaration
|
|
631
638
|
names. Read the records a record kind locates, validated
|
|
632
639
|
against its schema, with reason codes for invalid
|
|
@@ -639,7 +646,9 @@ Workspace (level 1, #2524):
|
|
|
639
646
|
asset-drift or asset-missing. In the working tree,
|
|
640
647
|
each record says whether it is committed, modified
|
|
641
648
|
or new against HEAD, with the branch and base;
|
|
642
|
-
--uncommitted lists only the modified and new ones
|
|
649
|
+
--uncommitted lists only the modified and new ones;
|
|
650
|
+
--where keeps the records a typed filter matches
|
|
651
|
+
(id, path, state, valid, data.<key>, ...)
|
|
643
652
|
workspace records [--kind <kind file>] --since <rev|session id> [--at <rev>] [--json]
|
|
644
653
|
What changed in the records between <rev> and --at
|
|
645
654
|
(default: the working tree): new and removed records,
|
|
@@ -709,14 +718,16 @@ Workspace (level 1, #2524):
|
|
|
709
718
|
a url or a path pinned by hash) is appended to the
|
|
710
719
|
item's pins through records amend. Prints the
|
|
711
720
|
work-evidence document and never commits
|
|
712
|
-
workspace runs [--unit <id>] [--decision <id>] [--by <principal>] [--since <rev>] [--follow-squash] [--json]
|
|
721
|
+
workspace runs [--unit <id>] [--decision <id>] [--by <principal>] [--since <rev>] [--where <field><op><value>]... [--follow-squash] [--json]
|
|
713
722
|
The agent runs in the run ledger on chant/lifecycle, each
|
|
714
723
|
with its model, tokens, cost and the commits it made,
|
|
715
724
|
and totals per work item, decision and principal; a run
|
|
716
725
|
that reports no cost is listed as unpriced, never zero.
|
|
717
726
|
Read-only, never fetches; --follow-squash joins each
|
|
718
727
|
squash merge to its pull request's runs, fetching a
|
|
719
|
-
missing refs/pull/<n>/head from origin
|
|
728
|
+
missing refs/pull/<n>/head from origin; --where keeps
|
|
729
|
+
the runs a typed filter matches (state, model,
|
|
730
|
+
startedAt, cost.amount, ...) before the totals
|
|
720
731
|
workspace runs start --from <file|->
|
|
721
732
|
Record that an agent run started: who it worked for,
|
|
722
733
|
its harness, model, work item and lease. Prints the run
|
|
@@ -888,7 +899,7 @@ Workspace (level 1, #2524):
|
|
|
888
899
|
workspace admit <return id> [--note <text>] [--dry-run] [--json]
|
|
889
900
|
Admit the signers of a return in .chant/trust.json, so
|
|
890
901
|
its signed work reads as attested once merged
|
|
891
|
-
workspace check [--at <rev>] [--json] [--format stylish|json|sarif] [--generated] [--kind <kind file>] [--live --env <env>]
|
|
902
|
+
workspace check [--at <rev>] [--json] [--format stylish|json|sarif] [--generated] [--kind <kind file>] [--live --env <env>] [--forge-repos <file>]
|
|
892
903
|
Fail on an unreadable lineage lock or an open manual
|
|
893
904
|
step, and, in a declared workspace, on a WSP check of
|
|
894
905
|
the declaration, member ledgers, pipelines or
|
|
@@ -900,7 +911,10 @@ Workspace (level 1, #2524):
|
|
|
900
911
|
resolves each declared member link against the live
|
|
901
912
|
graph of <env> (each chant member runs chant graph
|
|
902
913
|
--live, which reaches the account) and reports
|
|
903
|
-
WSP141 and WSP142
|
|
914
|
+
WSP141 and WSP142. --forge-repos reads a forge's
|
|
915
|
+
repository list from a file and reports repos an
|
|
916
|
+
org workspace lacks (WSP014) or names that the
|
|
917
|
+
forge no longer has (WSP015)
|
|
904
918
|
workspace check --changes <base>..<head> [--work <id>] [--severity off|warn|fail] [--kind <kind file>...] [--json]
|
|
905
919
|
Map each path the diff changes to the current records
|
|
906
920
|
whose constrains cover it: change-uncovered when none
|
|
@@ -928,9 +942,12 @@ Workspace (level 1, #2524):
|
|
|
928
942
|
its own chant, one process per toolchain. -o <dir>
|
|
929
943
|
writes <dir>/<member>.json; --member narrows the run;
|
|
930
944
|
--dry-run prints which chant runs which project
|
|
931
|
-
workspace lint [dir] [--format stylish|json|sarif] [--member <name>]
|
|
945
|
+
workspace lint [dir] [--format stylish|json|sarif] [--member <name>] [--cross-root]
|
|
932
946
|
Lint every chant member and example project with its
|
|
933
|
-
own chant; sarif writes one run per member
|
|
947
|
+
own chant; sarif writes one run per member.
|
|
948
|
+
--cross-root adds the disagreement lint (LNK001 and
|
|
949
|
+
the lexicons' cross-root checks) over every member's
|
|
950
|
+
graph, where declared links and the graphs disagree
|
|
934
951
|
workspace audit [dir] [--json] [--member <name>]
|
|
935
952
|
Audit each chant member with its own .chant-audit.json;
|
|
936
953
|
every finding carries a member field
|
|
@@ -967,6 +984,29 @@ Workspace (level 1, #2524):
|
|
|
967
984
|
One decision's intent walk over every path: and member:
|
|
968
985
|
entry it constrains: the commits in its window, each
|
|
969
986
|
own, worked, within-other or unexplained, with counts
|
|
987
|
+
workspace run <member>/<op>... [--env <env>] [--gate <name>] [--on <lexicon>] [--dry-run] [--json]
|
|
988
|
+
Run Ops that span members (#2554): each target's chant
|
|
989
|
+
run <op> in the member's directory, under its own
|
|
990
|
+
chant, producers before the members that link to them.
|
|
991
|
+
OPS019 checks every target against the composed graph
|
|
992
|
+
first. Member run records cite the workspace run,
|
|
993
|
+
whose record goes under _members/_workspace/<env>/.
|
|
994
|
+
Exits 3 when a step stops at a gate
|
|
995
|
+
workspace run --dependents-of <member> --op <op> [--env <env>] [--gate <name>] [--dry-run] [--json]
|
|
996
|
+
Run <op> in every member that links to <member>,
|
|
997
|
+
directly or not, nearest first; members without the
|
|
998
|
+
Op are listed as skipped
|
|
999
|
+
workspace run approve <gate> [--plan <digest>] [--approver <principal>]
|
|
1000
|
+
Approve a workspace gate's pending fact. It stands in
|
|
1001
|
+
for a member gate only when it covers that member's
|
|
1002
|
+
plan and the member sets acceptWorkspaceGates at base
|
|
1003
|
+
workspace train <env> [--pin <member>=<label|digest>]... [--dry-run] [--json]
|
|
1004
|
+
Record a release train: one cut release of every
|
|
1005
|
+
chant member (the newest, unless --pin picks one),
|
|
1006
|
+
under _members/_workspace/<env>/trains.jsonl. Refuses
|
|
1007
|
+
when a member has no release
|
|
1008
|
+
workspace train list <env> [--json]
|
|
1009
|
+
The release trains recorded for <env>, oldest first
|
|
970
1010
|
|
|
971
1011
|
Lifecycle (alias: lc):
|
|
972
1012
|
lifecycle snapshot <env> Query API, save metadata to orphan branch
|
|
@@ -1040,7 +1080,9 @@ Component release ledger + status:
|
|
|
1040
1080
|
from the report pr-plan --no-status wrote
|
|
1041
1081
|
(--pr <n> --head <sha> --env <env> --forge
|
|
1042
1082
|
<kind>), in a job that runs none of the
|
|
1043
|
-
change's code (#4295)
|
|
1083
|
+
change's code (#4295); --open posts every
|
|
1084
|
+
open merge request's from a GitLab pipeline
|
|
1085
|
+
of the target branch (#4328)
|
|
1044
1086
|
components pr-record On merge (#4168): plan the same members again,
|
|
1045
1087
|
store the change set and write the merge record
|
|
1046
1088
|
_merges/<commit>.json; applies and refuses
|
|
@@ -1198,12 +1240,16 @@ Options:
|
|
|
1198
1240
|
JSON (lifecycle plan)
|
|
1199
1241
|
OR '--report markdown': emit a reviewer-facing markdown
|
|
1200
1242
|
render, holes and disruption included (lifecycle plan)
|
|
1201
|
-
--from <name> Source
|
|
1202
|
-
|
|
1203
|
-
--
|
|
1243
|
+
--from <name> Source for migrate: a lexicon, or lexicon/dialect such
|
|
1244
|
+
as sql/postgres (default: github)
|
|
1245
|
+
--to <name> Target for migrate, same form, such as sql/clickhouse
|
|
1246
|
+
(default: gitlab)
|
|
1247
|
+
--emit <fmt> Migration output format: yaml (default), ts, or sql;
|
|
1248
|
+
sql/clickhouse defaults to ts
|
|
1204
1249
|
--strict Escalate needs-review/validation to errors (migrate);
|
|
1205
1250
|
exit nonzero on an unresolved identity (lifecycle whoami)
|
|
1206
|
-
--validate Run external validator
|
|
1251
|
+
--validate Run external validator after migrate: glci/glab, or the
|
|
1252
|
+
ClickHouse emulator for sql/clickhouse
|
|
1207
1253
|
--use-composites Rewrite to composite calls when patterns match (migrate)
|
|
1208
1254
|
--components Target discovered Component declarations instead of
|
|
1209
1255
|
lexicon resources (list, describe, graph, build, run)
|
|
@@ -1498,6 +1544,7 @@ export const commandRegistry: CommandDef[] = [
|
|
|
1498
1544
|
{ name: "search", handler: runSearch },
|
|
1499
1545
|
// #4297 — SQL over the snapshots, runs, gates, deploys and releases on chant/lifecycle. Imported on first use.
|
|
1500
1546
|
{ name: "query", runsNoConfig: true, handler: async (ctx) => (await import("./handlers/query")).runQueryCommand(ctx) },
|
|
1547
|
+
{ name: "ledger", runsNoConfig: true, handler: async (ctx) => (await import("./handlers/ledger")).runLedgerCommand(ctx) },
|
|
1501
1548
|
// chant#2591 — `import --agents` and `audit` read chant.config statically
|
|
1502
1549
|
// and never evaluate it (chant#2589 for audit, which audits code it must not run).
|
|
1503
1550
|
{ name: "import", handler: runImport, runsNoConfig: (args) => args.agents === true },
|
|
@@ -1629,6 +1676,10 @@ export const commandRegistry: CommandDef[] = [
|
|
|
1629
1676
|
{ name: "workspace audit", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/member-commands")).runWorkspaceMembers(ctx, "audit") },
|
|
1630
1677
|
{ name: "workspace graph", handler: async (ctx) => (await import("../workspace/member-commands")).runWorkspaceMembers(ctx, "graph") },
|
|
1631
1678
|
// #4374 — chant search in every member, under its own chant, composed with workspace graph's ids: the search document.
|
|
1679
|
+
// #2554 — Ops that span members, as <member>/<op> targets, each run under its member's own chant.
|
|
1680
|
+
{ name: "workspace run", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/workspace-run")).runWorkspaceRun(ctx) },
|
|
1681
|
+
// #2554 — a release train: one release of every chant member, pinned in the workspace ledger.
|
|
1682
|
+
{ name: "workspace train", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/release-train")).runWorkspaceTrain(ctx) },
|
|
1632
1683
|
{ name: "workspace search", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/search-cli")).runWorkspaceSearch(ctx) },
|
|
1633
1684
|
// Each unit decides for itself whether its config is loaded (runCommandInProcess).
|
|
1634
1685
|
{ name: "workspace member-run", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/member-run")).runWorkspaceMemberRun(ctx, runCommandInProcess) },
|
package/src/cli/parse-args.ts
CHANGED
|
@@ -47,6 +47,7 @@ const BOOLEAN_FLAGS = new Set([
|
|
|
47
47
|
"--up",
|
|
48
48
|
"--down",
|
|
49
49
|
"--include-dependents",
|
|
50
|
+
"--cross-root",
|
|
50
51
|
"--local",
|
|
51
52
|
"--json",
|
|
52
53
|
"--progress-json",
|
|
@@ -380,6 +381,19 @@ export function parseArgs(args: string[]): ParsedArgs {
|
|
|
380
381
|
result.head = args[++i];
|
|
381
382
|
} else if (arg === "--include-dependents") {
|
|
382
383
|
result.includeDependents = true;
|
|
384
|
+
} else if (arg === "--cross-root") {
|
|
385
|
+
// `chant workspace lint --cross-root` (#2549): the disagreement lint over every member's graph.
|
|
386
|
+
result.crossRoot = true;
|
|
387
|
+
} else if (arg === "--dependents-of") {
|
|
388
|
+
// `chant workspace run --dependents-of <member> --op <op>` (#2554).
|
|
389
|
+
const value = args[++i];
|
|
390
|
+
if (!value || value.startsWith("-")) throw new Error("--dependents-of needs a member name: --dependents-of <member>");
|
|
391
|
+
result.dependentsOf = value;
|
|
392
|
+
} else if (arg === "--pin") {
|
|
393
|
+
// `chant workspace train <env> --pin <member>=<label|digest>` (#2554), repeatable.
|
|
394
|
+
const value = args[++i];
|
|
395
|
+
if (!value || value.startsWith("-") || !value.includes("=")) throw new Error("--pin needs a member and a release: --pin <member>=<label|digest>");
|
|
396
|
+
(result.pins ??= []).push(value);
|
|
383
397
|
} else if (arg === "--from-affected") {
|
|
384
398
|
result.fromAffected = args[++i];
|
|
385
399
|
} else if (arg === "--gate") {
|
|
@@ -932,8 +946,8 @@ export function parseArgs(args: string[]): ParsedArgs {
|
|
|
932
946
|
} else if (arg === "--expire") {
|
|
933
947
|
result.expire = true;
|
|
934
948
|
} else if (arg === "--role") {
|
|
935
|
-
// #2508 — a role the approver claims,
|
|
936
|
-
//
|
|
949
|
+
// #2508 — a role the approver claims, recorded on the approval. A quorum
|
|
950
|
+
// (#4290) and a gate policy (#4324) read roles from .chant/trust.json at base.
|
|
937
951
|
// Repeatable, and a comma list works too.
|
|
938
952
|
const value = args[++i] ?? "";
|
|
939
953
|
result.roles = [...(result.roles ?? []), ...value.split(",").map((r) => r.trim()).filter(Boolean)];
|
|
@@ -971,6 +985,12 @@ export function parseArgs(args: string[]): ParsedArgs {
|
|
|
971
985
|
// #2537 — `chant build` and `chant lint` at a declared workspace root
|
|
972
986
|
// run on the root project alone instead of refusing with WSP000.
|
|
973
987
|
result.rootOnly = true;
|
|
988
|
+
} else if (arg === "--forge-repos") {
|
|
989
|
+
// #3168 — `chant workspace check --forge-repos <file>`: the forge's
|
|
990
|
+
// repository list, as a warden reads it, for an org workspace's checks.
|
|
991
|
+
const value = args[++i];
|
|
992
|
+
if (!value || value.startsWith("-")) throw new Error("--forge-repos needs a file: --forge-repos <repos.json>");
|
|
993
|
+
result.forgeRepos = value;
|
|
974
994
|
} else if (arg === "--generated") {
|
|
975
995
|
// #2641 — `chant workspace check --generated` runs each declared
|
|
976
996
|
// generator and compares its output with the file in the tree.
|
|
@@ -991,6 +1011,11 @@ export function parseArgs(args: string[]): ParsedArgs {
|
|
|
991
1011
|
result.url = args[++i];
|
|
992
1012
|
} else if (arg === "--op") {
|
|
993
1013
|
result.op = args[++i];
|
|
1014
|
+
} else if (arg === "--where") {
|
|
1015
|
+
// #4363 — a typed filter on a contract read; repeatable, every clause has to hold.
|
|
1016
|
+
const value = args[++i];
|
|
1017
|
+
if (value === undefined || value.startsWith("--")) throw new Error("--where needs a clause: --where <field><op><value>");
|
|
1018
|
+
result.where = [...(result.where ?? []), value];
|
|
994
1019
|
} else if (arg === "--since") {
|
|
995
1020
|
result.since = args[++i];
|
|
996
1021
|
} else if (arg === "--limit") {
|
package/src/cli/registry.ts
CHANGED
|
@@ -83,7 +83,7 @@ export interface ParsedArgs {
|
|
|
83
83
|
/** `chant run events <run> --follow` (#4042) — stream the run's events as they happen, until `run-settle`. */
|
|
84
84
|
follow?: boolean;
|
|
85
85
|
live: boolean;
|
|
86
|
-
/** `chant migrate --from <name>` (default "github") */
|
|
86
|
+
/** `chant migrate --from <name>` (default "github"); `lexicon/dialect` for the sql lexicon */
|
|
87
87
|
migrateFrom?: string;
|
|
88
88
|
/** `chant import --kustomize <dir>` — render the kustomization, then import (#1548) */
|
|
89
89
|
kustomize?: string;
|
|
@@ -103,9 +103,9 @@ export interface ParsedArgs {
|
|
|
103
103
|
write?: boolean;
|
|
104
104
|
/** `chant carve apply --write-source` — stamp the ownership marker into the emitted source */
|
|
105
105
|
writeSource?: boolean;
|
|
106
|
-
/** `chant migrate --to <name>` (default "gitlab") */
|
|
106
|
+
/** `chant migrate --to <name>` (default "gitlab"); `lexicon/dialect` for the sql lexicon */
|
|
107
107
|
migrateTo?: string;
|
|
108
|
-
/** `chant migrate --emit yaml|ts` */
|
|
108
|
+
/** `chant migrate --emit yaml|ts|sql` */
|
|
109
109
|
emit?: string;
|
|
110
110
|
/** Escalate needs-review diagnostics to errors (migrate command) */
|
|
111
111
|
strict?: boolean;
|
|
@@ -263,6 +263,12 @@ export interface ParsedArgs {
|
|
|
263
263
|
head?: string;
|
|
264
264
|
/** `chant lifecycle affected --include-dependents` — add downstream consumers */
|
|
265
265
|
includeDependents?: boolean;
|
|
266
|
+
/** `chant workspace run --dependents-of <member> --op <op>` (#2554): run the Op in every member that links to this one, directly or not. */
|
|
267
|
+
dependentsOf?: string;
|
|
268
|
+
/** `chant workspace lint --cross-root` (#2549): also run the disagreement lint and the lexicons' cross-root checks over every member's graph. */
|
|
269
|
+
crossRoot?: boolean;
|
|
270
|
+
/** `chant workspace train <env> --pin <member>=<label|digest>` (#2554), repeatable: the release a train pins for that member instead of its newest. */
|
|
271
|
+
pins?: string[];
|
|
266
272
|
/**
|
|
267
273
|
* `chant components fan-out --from-affected <file>` (#2420) — read the
|
|
268
274
|
* stack-level change signal from the JSON `chant lifecycle affected --json`
|
|
@@ -640,6 +646,8 @@ export interface ParsedArgs {
|
|
|
640
646
|
* generators run member code.
|
|
641
647
|
*/
|
|
642
648
|
generated?: boolean;
|
|
649
|
+
/** `chant workspace check --forge-repos <file>` (#3168): the forge's repository list, checked against an org workspace's repo members (WSP014, WSP015). */
|
|
650
|
+
forgeRepos?: string;
|
|
643
651
|
/**
|
|
644
652
|
* `chant workspace build|lint|audit|graph --member <name>` (#2537): run only
|
|
645
653
|
* the named members or example groups. Repeatable, and a comma list works too.
|
|
@@ -788,7 +796,7 @@ export interface ParsedArgs {
|
|
|
788
796
|
* on a model-authored channel.
|
|
789
797
|
*/
|
|
790
798
|
allowSameOrigin?: boolean;
|
|
791
|
-
/** `chant approve --role <name>` (#2508) — roles the approver claims,
|
|
799
|
+
/** `chant approve --role <name>` (#2508) — roles the approver claims, recorded on the approval. Nothing trusts them: a quorum (#4290) and a gate policy (#4324) read roles from `.chant/trust.json` at base, for a sealed approval. Repeatable; a comma list also works. */
|
|
792
800
|
roles?: string[];
|
|
793
801
|
/** `chant approve --agent` (#2508) — record the approval as an agent's. An agent never counts toward a quorum; it passes a gate only through a policy permit in `enforce` mode. */
|
|
794
802
|
agent?: boolean;
|
|
@@ -798,6 +806,8 @@ export interface ParsedArgs {
|
|
|
798
806
|
op?: string;
|
|
799
807
|
/** `chant operator log --since <iso>` (#2029) — only entries at or after this ISO-8601 instant. `chant workspace records --since <rev>` (#2673) — the revision to compare the records with. `chant workspace metrics --since <date>` (#4039) — the start of the window the metrics count. */
|
|
800
808
|
since?: string;
|
|
809
|
+
/** `chant ledger`, `chant workspace records` and `chant workspace runs --where <field><op><value>` (#4363): typed filters, repeatable, all of which have to hold. */
|
|
810
|
+
where?: string[];
|
|
801
811
|
/** `chant operator log --limit <n>` (#2029) — keep only the newest n entries (still printed oldest-first). */
|
|
802
812
|
limit?: number;
|
|
803
813
|
/** `chant approve <op> <gate> --url <url>` (#2028) — the address this resolution happened at (the PR/MR that carried the change), recorded typed on the gate-resolution fact so a reader is not sniffing `--note` for something link-shaped. Defaults to the PR/MR the surrounding CI job is for, when there is one. Must be an absolute http/https URL. */
|
|
@@ -19,6 +19,8 @@ import type {
|
|
|
19
19
|
ZipPackageInput,
|
|
20
20
|
JvmBuildInput,
|
|
21
21
|
GenerateSbomInput,
|
|
22
|
+
PublishImageInput,
|
|
23
|
+
PublishArtifactInput,
|
|
22
24
|
SignInput,
|
|
23
25
|
AttestProvenanceInput,
|
|
24
26
|
VerifyInput,
|
|
@@ -64,6 +66,12 @@ export const vulnGate = step<VulnGateInput>("vuln-gate");
|
|
|
64
66
|
// The cloud-specific waits (`wait-for-stack`/`wait-steady-state`/`wait-job`)
|
|
65
67
|
// ship as builders from the aws lexicon, alongside their capabilities.
|
|
66
68
|
export const waitClusterHealthy = step<WaitClusterHealthyInput>("wait-cluster-healthy");
|
|
69
|
+
// ── publish (core owns the verb; each cloud lexicon contributes a registry login backend) ──
|
|
70
|
+
export const publishImage = step<PublishImageInput>("publish-image");
|
|
71
|
+
export const publishArtifact = step<PublishArtifactInput>("publish-artifact");
|
|
72
|
+
/** Alias for {@link publishArtifact}. */
|
|
73
|
+
export const publishAsset = publishArtifact;
|
|
74
|
+
|
|
67
75
|
export const waitEndpoint = step<WaitEndpointInput>("wait-endpoint");
|
|
68
76
|
export const healthGate = step<HealthGateInput>("health-gate");
|
|
69
77
|
|
|
@@ -26,6 +26,8 @@ import { lexiconModulePath, importLexiconPackage } from "../lexicon-module";
|
|
|
26
26
|
import type { CapabilityPlugin } from "./capability-plugin";
|
|
27
27
|
import { isCapabilityPlugin } from "./capability-plugin";
|
|
28
28
|
import { starterCapabilityPlugin } from "./starter-plugin";
|
|
29
|
+
import { isRegistryBackendConsumer, type RegistryLoginBackend } from "./verbs/publish-image";
|
|
30
|
+
import { isStorageBackendConsumer, type ArtifactStorageBackend } from "./verbs/publish-artifact";
|
|
29
31
|
|
|
30
32
|
/** Thrown when a dynamically-imported capability package does not satisfy `CapabilityPlugin` — the "malformed capability package" case #559 asks doctor/validation to detect. */
|
|
31
33
|
export class MalformedCapabilityPluginError extends Error {
|
|
@@ -165,9 +167,19 @@ export function registerCapabilityPlugins(
|
|
|
165
167
|
}
|
|
166
168
|
}
|
|
167
169
|
|
|
170
|
+
const backends: RegistryLoginBackend[] = [];
|
|
171
|
+
for (const plugin of plugins) backends.push(...(plugin.registryBackends?.() ?? []));
|
|
172
|
+
const storage: ArtifactStorageBackend[] = [];
|
|
173
|
+
for (const plugin of plugins) storage.push(...(plugin.storageBackends?.() ?? []));
|
|
174
|
+
|
|
168
175
|
for (const plugin of plugins) {
|
|
169
176
|
for (const capability of plugin.capabilities()) {
|
|
170
|
-
registry
|
|
177
|
+
// A capability that consumes registry login backends (`publish-image`)
|
|
178
|
+
// is re-bound to the backends of the plugins loaded for this registry.
|
|
179
|
+
let bound = capability;
|
|
180
|
+
if (isRegistryBackendConsumer(bound)) bound = bound.withRegistryBackends(backends) as typeof bound;
|
|
181
|
+
if (isStorageBackendConsumer(bound)) bound = bound.withStorageBackends(storage) as typeof bound;
|
|
182
|
+
registry.register(bound);
|
|
171
183
|
}
|
|
172
184
|
}
|
|
173
185
|
return registry;
|
|
@@ -32,6 +32,8 @@ import { readFileSync } from "node:fs";
|
|
|
32
32
|
import { dirname, join } from "node:path";
|
|
33
33
|
import { fileURLToPath } from "node:url";
|
|
34
34
|
import type { Capability } from "./capability";
|
|
35
|
+
import type { RegistryLoginBackend } from "./verbs/publish-image";
|
|
36
|
+
import type { ArtifactStorageBackend } from "./verbs/publish-artifact";
|
|
35
37
|
|
|
36
38
|
/**
|
|
37
39
|
* Manifest for a packaged capability plugin — the capability-side analogue
|
|
@@ -88,6 +90,20 @@ export interface CapabilityPlugin {
|
|
|
88
90
|
/** Capability kinds grouped by family, informational — mirrors `STARTER_VERB_FAMILIES` (./registry.ts) shape for third-party plugins that want to publish the same grouping. */
|
|
89
91
|
families?(): Record<string, readonly string[]>;
|
|
90
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Registry login backends this plugin contributes to core's `publish-image`
|
|
95
|
+
* verb (aws: ECR, azure: ACR, gcp: Artifact Registry). Not capabilities, so
|
|
96
|
+
* several plugins may contribute without a duplicate-kind clash.
|
|
97
|
+
*/
|
|
98
|
+
registryBackends?(): RegistryLoginBackend[];
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Object-storage backends this plugin contributes to core's
|
|
102
|
+
* `publish-artifact` verb (aws: S3, azure: Blob, gcp: GCS). Like
|
|
103
|
+
* `registryBackends`, not capabilities, so several plugins may contribute.
|
|
104
|
+
*/
|
|
105
|
+
storageBackends?(): ArtifactStorageBackend[];
|
|
106
|
+
|
|
91
107
|
/** Optional initialization hook, called once after load (mirrors `LexiconPlugin.init`). */
|
|
92
108
|
init?(): void | Promise<void>;
|
|
93
109
|
}
|
|
@@ -8,6 +8,7 @@ import { mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, writeFileSy
|
|
|
8
8
|
import { join } from "node:path";
|
|
9
9
|
import { tmpdir } from "node:os";
|
|
10
10
|
import { parseDeclaration, WorkspaceReadError } from "../workspace/declaration";
|
|
11
|
+
import { PR_LOOP_HOOK_MOMENTS } from "../op/op-waves";
|
|
11
12
|
import { prLoopHooksAt, prLoopHooksOf, runPrHooks } from "./pr-hooks";
|
|
12
13
|
import type { OpWaveExec } from "../op/op-waves-run";
|
|
13
14
|
|
|
@@ -30,6 +31,12 @@ const declaration = (hooks: unknown, memberHooks?: unknown) => ({
|
|
|
30
31
|
});
|
|
31
32
|
|
|
32
33
|
describe("ci.hooks in the declaration (#4288)", () => {
|
|
34
|
+
test("accepts after.gate, and runs it after the plan-side moments (#4323)", () => {
|
|
35
|
+
const d = parseDeclaration(JSON.stringify(declaration({ after: { gate: [{ name: "report", command: ["report"] }] } }, { after: { gate: [{ name: "member-report", command: ["mr"] }] } })), "chant.workspace.json", "0.124.41");
|
|
36
|
+
expect(prLoopHooksOf(d, "infra")["after-gate"]!.map((h) => h.name)).toEqual(["report", "member-report"]);
|
|
37
|
+
expect(PR_LOOP_HOOK_MOMENTS).toContain("after-gate");
|
|
38
|
+
});
|
|
39
|
+
|
|
33
40
|
test("parses at the top level and on a member; the member's run after the top level's", () => {
|
|
34
41
|
const d = parseDeclaration(
|
|
35
42
|
JSON.stringify(declaration({ before: { observe: [{ name: "init", command: ["init"] }] } }, { before: { observe: [{ name: "member-init", command: ["mi"], targets: ["db*"] }] } })),
|
|
@@ -43,7 +50,7 @@ describe("ci.hooks in the declaration (#4288)", () => {
|
|
|
43
50
|
|
|
44
51
|
test("refuses hooks a pull-request job cannot run", () => {
|
|
45
52
|
const read = (hooks: unknown) => () => parseDeclaration(JSON.stringify(declaration(hooks)), "chant.workspace.json", "0.124.41");
|
|
46
|
-
expect(read({
|
|
53
|
+
expect(read({ before: { plan: [{ command: ["x"], onFailure: "bogus" }] } })).toThrow(WorkspaceReadError);
|
|
47
54
|
expect(read({ before: { plan: [{ command: [] }] } })).toThrow(/must be a command as argv/);
|
|
48
55
|
expect(read({ apply: { runBy: "apply" } })).toThrow(/runBy is for an Op waves spec/);
|
|
49
56
|
});
|
|
@@ -84,7 +91,7 @@ describe("prLoopHooksAt (#4288)", () => {
|
|
|
84
91
|
});
|
|
85
92
|
|
|
86
93
|
describe("runPrHooks (#4288)", () => {
|
|
87
|
-
test("runs a moment for the selected components, writes the runs and plan files, and reports a failure", () => {
|
|
94
|
+
test("runs a moment for the selected components, writes the runs and plan files, and reports a failure", async () => {
|
|
88
95
|
const cwd = tmp();
|
|
89
96
|
const calls: Array<{ argv: string; env?: Record<string, string> }> = [];
|
|
90
97
|
const exec: OpWaveExec = (argv, _dir, env) => {
|
|
@@ -95,7 +102,7 @@ describe("runPrHooks (#4288)", () => {
|
|
|
95
102
|
base: "b".repeat(40),
|
|
96
103
|
hooks: { "after-plan": [{ name: "check", command: ["check", "{target}", "{plan}"], perRun: true, targets: ["api", "web"] }] },
|
|
97
104
|
};
|
|
98
|
-
const ran = runPrHooks(read, "after-plan", { op: "pr-7", env: "prod", stage: "plan", dir: ".chant/pr", cwd, exec, log: () => {} }, ["api", "db", "web"], {
|
|
105
|
+
const ran = await runPrHooks(read, "after-plan", { op: "pr-7", env: "prod", stage: "plan", dir: ".chant/pr", cwd, exec, log: () => {} }, ["api", "db", "web"], {
|
|
99
106
|
members: [{ member: "api", component: "api", planDigest: "sha256:1", status: "planned", counts: { create: 1, update: 0, replace: 0, delete: 0 } }],
|
|
100
107
|
plans: { api: { api: { file: "plan.bin" } } },
|
|
101
108
|
});
|
|
@@ -110,9 +117,70 @@ describe("runPrHooks (#4288)", () => {
|
|
|
110
117
|
expect(ran.failed).toBe("after-plan hook check (web) exited 1");
|
|
111
118
|
});
|
|
112
119
|
|
|
113
|
-
test("a moment with no hooks runs nothing and writes nothing", () => {
|
|
120
|
+
test("a moment with no hooks runs nothing and writes nothing", async () => {
|
|
114
121
|
const cwd = tmp();
|
|
115
|
-
const ran = runPrHooks({ base: "b", hooks: {} }, "before-apply", { op: "pr-7", env: "prod", stage: "apply", dir: ".chant/pr", cwd, log: () => {} }, ["api"]);
|
|
122
|
+
const ran = await runPrHooks({ base: "b", hooks: {} }, "before-apply", { op: "pr-7", env: "prod", stage: "apply", dir: ".chant/pr", cwd, log: () => {} }, ["api"]);
|
|
116
123
|
expect(ran).toEqual({ outcomes: [], holds: [] });
|
|
117
124
|
});
|
|
125
|
+
|
|
126
|
+
const holdBody = { gate: "db-migrate", digest: "sha256:m1", op: "other-op" };
|
|
127
|
+
/** An exec for a hook that holds on db-migrate until CHANT_HOLD_APPROVED is set. */
|
|
128
|
+
const holdingExec = (cwd: string, calls: Array<Record<string, string> | undefined>): OpWaveExec => (argv, _dir, env) => {
|
|
129
|
+
calls.push(env);
|
|
130
|
+
if (env?.CHANT_HOLD_APPROVED) return 0;
|
|
131
|
+
writeFileSync(join(cwd, env!.CHANT_HOLD!), JSON.stringify(holdBody));
|
|
132
|
+
return argv[0] === "hold" ? 1 : 0;
|
|
133
|
+
};
|
|
134
|
+
const gateHooks = { "after-gate": [{ name: "migrate", command: ["hold"], onFailure: "approve" as const }] };
|
|
135
|
+
const place = (cwd: string, exec: OpWaveExec) => ({ op: "pr-7", env: "prod", stage: "apply" as const, dir: ".chant/pr", cwd, exec, log: () => {} });
|
|
136
|
+
|
|
137
|
+
test("an after-gate hook gets the gate's decision in its environment (#4323)", async () => {
|
|
138
|
+
const cwd = tmp();
|
|
139
|
+
const calls: Array<Record<string, string> | undefined> = [];
|
|
140
|
+
const exec: OpWaveExec = (_argv, _dir, env) => (calls.push(env), 0);
|
|
141
|
+
const read = { base: "b", hooks: { "after-gate": [{ name: "report", command: ["report"] }] } };
|
|
142
|
+
const decision = { CHANT_GATE_STATUS: "approved", CHANT_GATE_OP: "pr-7", CHANT_GATE: "pr-apply", CHANT_GATE_DIGEST: "sha256:p" };
|
|
143
|
+
const ran = await runPrHooks(read, "after-gate", place(cwd, exec), ["api"], undefined, { env: decision });
|
|
144
|
+
expect(calls[0]).toMatchObject({ CHANT_HOOK: "after-gate", ...decision });
|
|
145
|
+
expect(ran.outcomes).toEqual([{ moment: "after-gate", name: "report", exit: 0, outcome: "passed" }]);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
test("a hold on another gate clears once that gate is approved: the hook runs again with CHANT_HOLD_APPROVED (#4323)", async () => {
|
|
149
|
+
const cwd = tmp();
|
|
150
|
+
const calls: Array<Record<string, string> | undefined> = [];
|
|
151
|
+
let approved = false;
|
|
152
|
+
const asked: string[] = [];
|
|
153
|
+
const settle = async (hold: { request: { gate: string; digest: string; op?: string } }) => {
|
|
154
|
+
asked.push(`${hold.request.op} / ${hold.request.gate} @ ${hold.request.digest}`);
|
|
155
|
+
return approved ? { status: "approved" as const, approvedBy: "alice", approvedAt: "2026-10-23T00:00:00Z" } : { status: "waiting" as const };
|
|
156
|
+
};
|
|
157
|
+
const read = { base: "b", hooks: gateHooks };
|
|
158
|
+
const first = await runPrHooks(read, "after-gate", place(cwd, holdingExec(cwd, calls)), ["api"], undefined, { settle });
|
|
159
|
+
expect(first.failed).toMatch(/^after-gate hook migrate waits on other-op \/ db-migrate, which nobody approved at sha256:m1\. Approve: /);
|
|
160
|
+
expect(first.holds).toEqual([]);
|
|
161
|
+
|
|
162
|
+
approved = true;
|
|
163
|
+
calls.length = 0;
|
|
164
|
+
const second = await runPrHooks(read, "after-gate", place(cwd, holdingExec(cwd, calls)), ["api"], undefined, { settle });
|
|
165
|
+
expect(second.failed).toBeUndefined();
|
|
166
|
+
expect(second.holds).toEqual([]);
|
|
167
|
+
expect(asked).toEqual(["other-op / db-migrate @ sha256:m1", "other-op / db-migrate @ sha256:m1"]);
|
|
168
|
+
expect(JSON.parse(calls[1]!.CHANT_HOLD_APPROVED!)).toEqual({ op: "other-op", gate: "db-migrate", digest: "sha256:m1", approvedBy: "alice", approvedAt: "2026-10-23T00:00:00Z" });
|
|
169
|
+
expect(second.outcomes.map((o) => o.outcome)).toEqual(["held", "passed"]);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
test("a re-run that holds on a gate already approved fails the stage (#4323)", async () => {
|
|
173
|
+
const cwd = tmp();
|
|
174
|
+
const exec: OpWaveExec = (_argv, _dir, env) => (writeFileSync(join(cwd, env!.CHANT_HOLD!), JSON.stringify(holdBody)), 1);
|
|
175
|
+
const settle = async () => ({ status: "approved" as const, approvedBy: "alice", approvedAt: "t" });
|
|
176
|
+
const ran = await runPrHooks({ base: "b", hooks: gateHooks }, "after-gate", place(cwd, exec), ["api"], undefined, { settle });
|
|
177
|
+
expect(ran.failed).toMatch(/holds again on other-op \/ db-migrate at sha256:m1, which is already approved/);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test("without a settler a hold on another gate stays a plain hold", async () => {
|
|
181
|
+
const cwd = tmp();
|
|
182
|
+
const ran = await runPrHooks({ base: "b", hooks: gateHooks }, "after-gate", place(cwd, holdingExec(cwd, [])), ["api"]);
|
|
183
|
+
expect(ran.holds).toEqual(["after-gate hook migrate (on other-op / db-migrate)"]);
|
|
184
|
+
expect(ran.failed).toBeUndefined();
|
|
185
|
+
});
|
|
118
186
|
});
|