@intentius/chant 0.124.46 → 0.124.49
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 +41 -14
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/build.js +6 -1
- package/dist/cli/handlers/graph-reader.d.ts +26 -0
- package/dist/cli/handlers/graph-reader.d.ts.map +1 -0
- package/dist/cli/handlers/graph-reader.js +41 -0
- package/dist/cli/handlers/graph.d.ts.map +1 -1
- package/dist/cli/handlers/graph.js +14 -0
- 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 +183 -40
- 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 +87 -14
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +47 -2
- package/dist/cli/registry.d.ts +22 -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/pr-run.d.ts +3 -0
- package/dist/components/pr-run.d.ts.map +1 -1
- package/dist/components/pr-run.js +1 -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 +25 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +10 -2
- package/dist/gate-decision.d.ts +20 -2
- package/dist/gate-decision.d.ts.map +1 -1
- package/dist/gate-decision.js +30 -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 +94 -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 +9 -6
- 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-base.d.ts +25 -0
- package/dist/op/gate-approval-base.d.ts.map +1 -0
- package/dist/op/gate-approval-base.js +71 -0
- package/dist/op/gate-approval.d.ts +18 -9
- package/dist/op/gate-approval.d.ts.map +1 -1
- package/dist/op/gate-approval.js +13 -31
- package/dist/op/gate-name.d.ts +13 -0
- package/dist/op/gate-name.d.ts.map +1 -1
- package/dist/op/gate-name.js +14 -1
- 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 +47 -5
- 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 +45 -3
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/local-executor.js +68 -7
- 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-loop.d.ts +10 -0
- package/dist/pr-loop.d.ts.map +1 -1
- package/dist/pr-loop.js +4 -0
- package/dist/pr-migrations.d.ts +62 -0
- package/dist/pr-migrations.d.ts.map +1 -0
- package/dist/pr-migrations.js +50 -0
- package/dist/pr-post.d.ts +42 -0
- package/dist/pr-post.d.ts.map +1 -1
- package/dist/pr-post.js +68 -2
- 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 +264 -254
- package/dist/workspace/check.schema.json +13 -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/gate-approval.d.ts +58 -0
- package/dist/workspace/checks/gate-approval.d.ts.map +1 -0
- package/dist/workspace/checks/gate-approval.js +103 -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 +12 -1
- package/dist/workspace/checks.d.ts.map +1 -1
- package/dist/workspace/checks.js +63 -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 +50 -2
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.js +57 -11
- package/dist/workspace/declaration.schema.json +166 -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/exit-cli.d.ts +44 -0
- package/dist/workspace/exit-cli.d.ts.map +1 -0
- package/dist/workspace/exit-cli.js +198 -0
- package/dist/workspace/exit.d.ts +159 -0
- package/dist/workspace/exit.d.ts.map +1 -0
- package/dist/workspace/exit.js +480 -0
- package/dist/workspace/exit.schema.json +257 -0
- 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-cache.d.ts +3 -1
- package/dist/workspace/graph-cache.d.ts.map +1 -1
- package/dist/workspace/graph-cache.js +12 -1
- 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/import-fetch.d.ts +38 -0
- package/dist/workspace/import-fetch.d.ts.map +1 -0
- package/dist/workspace/import-fetch.js +99 -0
- package/dist/workspace/import-init.d.ts +26 -0
- package/dist/workspace/import-init.d.ts.map +1 -0
- package/dist/workspace/import-init.js +130 -0
- package/dist/workspace/import-source.d.ts +147 -0
- package/dist/workspace/import-source.d.ts.map +1 -0
- package/dist/workspace/import-source.js +370 -0
- package/dist/workspace/init.d.ts +4 -0
- package/dist/workspace/init.d.ts.map +1 -1
- package/dist/workspace/init.js +70 -3
- 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/kind-readers.d.ts +6 -0
- package/dist/workspace/kind-readers.d.ts.map +1 -1
- package/dist/workspace/kind-readers.js +18 -0
- package/dist/workspace/kinds.d.ts +90 -3
- package/dist/workspace/kinds.d.ts.map +1 -1
- package/dist/workspace/kinds.js +161 -7
- 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/lineage-upgrade.d.ts.map +1 -1
- package/dist/workspace/lineage-upgrade.js +13 -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/new-migrations.d.ts +47 -0
- package/dist/workspace/new-migrations.d.ts.map +1 -0
- package/dist/workspace/new-migrations.js +91 -0
- package/dist/workspace/pr-report.schema.json +46 -0
- package/dist/workspace/promote.d.ts +96 -0
- package/dist/workspace/promote.d.ts.map +1 -0
- package/dist/workspace/promote.js +263 -0
- package/dist/workspace/reason-codes.d.ts +21 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +25 -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 +108 -10
- 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 +33 -4
- package/src/cli/handlers/build.ts +7 -1
- package/src/cli/handlers/graph-reader.test.ts +31 -0
- package/src/cli/handlers/graph-reader.ts +51 -0
- package/src/cli/handlers/graph.ts +14 -0
- 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 +176 -37
- 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 +17 -0
- package/src/cli/main.ts +87 -14
- package/src/cli/parse-args.ts +35 -2
- package/src/cli/registry.ts +22 -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-env-run-bundle.test.ts +1 -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/pr-run.ts +4 -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 +24 -1
- package/src/gate-decision-bundle.test.ts +5 -2
- package/src/gate-decision-identity.test.ts +20 -0
- package/src/gate-decision.ts +46 -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 +98 -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-at-base.test.ts +97 -0
- package/src/op/gate-approval-base.ts +72 -0
- package/src/op/gate-approval.test.ts +6 -1
- package/src/op/gate-approval.ts +22 -27
- package/src/op/gate-name.ts +16 -1
- 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 +69 -9
- package/src/op/index.ts +3 -2
- package/src/op/local-executor.ts +91 -11
- 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-loop-bundle.test.ts +3 -2
- package/src/pr-loop.test.ts +52 -0
- package/src/pr-loop.ts +12 -0
- package/src/pr-migrations.ts +97 -0
- package/src/pr-post-open.e2e.test.ts +36 -0
- package/src/pr-post.test.ts +102 -3
- package/src/pr-post.ts +90 -2
- 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/__fixtures__/import/spacelift.json +9 -0
- package/src/workspace/__fixtures__/import/tfc.json +13 -0
- package/src/workspace/behold-kinds.test.ts +2 -1
- package/src/workspace/check-contract.test.ts +8 -6
- package/src/workspace/check.schema.json +13 -2
- package/src/workspace/checks/ci-branch.test.ts +128 -0
- package/src/workspace/checks/ci-branch.ts +141 -0
- package/src/workspace/checks/gate-approval.test.ts +77 -0
- package/src/workspace/checks/gate-approval.ts +121 -0
- package/src/workspace/checks/links.ts +12 -1
- package/src/workspace/checks/org.ts +169 -0
- package/src/workspace/checks.ts +68 -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 +166 -24
- package/src/workspace/declaration.ts +101 -15
- package/src/workspace/environments.ts +40 -4
- package/src/workspace/exit-cli.ts +219 -0
- package/src/workspace/exit.schema.json +257 -0
- package/src/workspace/exit.test.ts +185 -0
- package/src/workspace/exit.ts +560 -0
- package/src/workspace/flyway-dir.ts +113 -0
- package/src/workspace/flyway-layout.ts +337 -0
- package/src/workspace/graph-cache.ts +12 -2
- 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 +29 -2
- package/src/workspace/import-fetch.ts +151 -0
- package/src/workspace/import-init.ts +147 -0
- package/src/workspace/import-source.test.ts +183 -0
- package/src/workspace/import-source.ts +462 -0
- package/src/workspace/init.test.ts +55 -1
- package/src/workspace/init.ts +66 -4
- package/src/workspace/intent.ts +6 -14
- package/src/workspace/kind-link-readers.ts +68 -3
- package/src/workspace/kind-readers.test.ts +36 -0
- package/src/workspace/kind-readers.ts +18 -1
- package/src/workspace/kinds.test.ts +35 -7
- package/src/workspace/kinds.ts +212 -11
- 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/lineage-upgrade.test.ts +20 -0
- package/src/workspace/lineage-upgrade.ts +16 -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/new-migrations.test.ts +98 -0
- package/src/workspace/new-migrations.ts +109 -0
- package/src/workspace/org-scope.test.ts +238 -0
- package/src/workspace/pr-report.schema.json +46 -0
- package/src/workspace/promote.test.ts +114 -0
- package/src/workspace/promote.ts +302 -0
- package/src/workspace/reason-codes.test.ts +10 -1
- package/src/workspace/reason-codes.ts +25 -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 +108 -10
- 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/op/op-waves-run.ts
CHANGED
|
@@ -63,6 +63,16 @@ import {
|
|
|
63
63
|
type WaveStep,
|
|
64
64
|
} from "../wave-engine";
|
|
65
65
|
import type { ReviewApproval } from "../gate-decision";
|
|
66
|
+
import {
|
|
67
|
+
blockedMembers,
|
|
68
|
+
blockedWords,
|
|
69
|
+
earlierWaveOutcomes,
|
|
70
|
+
passesThrough,
|
|
71
|
+
readWaveOutcomeFile,
|
|
72
|
+
waveOutcomeFileName,
|
|
73
|
+
writeWaveOutcomeFile,
|
|
74
|
+
type WaveMemberOutcome,
|
|
75
|
+
} from "../wave-blocked";
|
|
66
76
|
import { approveCommand, evaluateGate, gitGateLedgerPort, type GateCheck, type GateDigestMismatch, type GateLedgerPort } from "./gate";
|
|
67
77
|
import type { GateAnswerRef, PendingGateRecord } from "../lifecycle/gate-ledger";
|
|
68
78
|
import type { GatePointAsker } from "../point-decision";
|
|
@@ -75,8 +85,8 @@ import type { TrustPolicy } from "../workspace/trust/policy";
|
|
|
75
85
|
import type { GateSigners } from "../lifecycle/gate-seal";
|
|
76
86
|
import { ciRunIdFromEnv } from "./gate-run-locator";
|
|
77
87
|
import {
|
|
78
|
-
quorumProblems, quorumRuleLine, quorumRulesFor, quorumWaiting, ruleNeedsProof, samePrincipal, trustQuorumJudge,
|
|
79
|
-
type GateQuorumRule, type GateQuorumRuleProgress,
|
|
88
|
+
changeInvolvement, quorumProblems, quorumRuleLine, quorumRulesFor, quorumWaiting, recordedReviewApprovals, ruleNeedsProof, samePrincipal, trustQuorumJudge,
|
|
89
|
+
type GateQuorumJudge, type GateQuorumRule, type GateQuorumRuleProgress, type QuorumJudgement,
|
|
80
90
|
} from "./gate-quorum";
|
|
81
91
|
import {
|
|
82
92
|
OP_WAVE_DEFAULT_APPLY,
|
|
@@ -89,6 +99,7 @@ import {
|
|
|
89
99
|
opWaveGateName,
|
|
90
100
|
opWaveHooksAt,
|
|
91
101
|
opWaveHookRuns,
|
|
102
|
+
opWaveOutcomeDir,
|
|
92
103
|
opWavePointAt,
|
|
93
104
|
opWavePointProblems,
|
|
94
105
|
opWaveRecordPath,
|
|
@@ -103,7 +114,10 @@ import {
|
|
|
103
114
|
type OpWaveHookMoment,
|
|
104
115
|
type OpWavePoint,
|
|
105
116
|
type OpWaveRun,
|
|
117
|
+
type OpWavesInvolved,
|
|
106
118
|
type OpWavesSpec,
|
|
119
|
+
OP_LEDGER_NAME,
|
|
120
|
+
opWavesInvolvedProblems,
|
|
107
121
|
} from "./op-waves";
|
|
108
122
|
import {
|
|
109
123
|
OP_WAVE_PENDING_RESERVED,
|
|
@@ -242,6 +256,10 @@ export interface OpWaveDecision {
|
|
|
242
256
|
review?: { pr?: number; head?: string; approvers?: string[]; url?: string; reason?: string };
|
|
243
257
|
/** The approval rules at base the wave's targets take (#4290). Absent when it takes none. */
|
|
244
258
|
quorum?: GateQuorumRule[];
|
|
259
|
+
/** The op whose ledger holds the product's own reviews, read at base (#4333). */
|
|
260
|
+
reviewLedger?: string;
|
|
261
|
+
/** Who else counts as involved in the change, read at base (#4333). */
|
|
262
|
+
involved?: OpWavesInvolved;
|
|
245
263
|
/** Where each of those rules stands (#4290), while the wave waits. */
|
|
246
264
|
quorumProgress?: GateQuorumRuleProgress[];
|
|
247
265
|
/** The command that approves this digest, when waiting. */
|
|
@@ -489,6 +507,10 @@ export interface OpWaveBaseRules {
|
|
|
489
507
|
quorum?: GateQuorumRule[];
|
|
490
508
|
/** Set when the rules at base cannot be read: the wave fails rather than wait on fewer approvers than they ask. */
|
|
491
509
|
quorumRefused?: string;
|
|
510
|
+
/** `approvals.reviewLedger` at base (#4333): the op whose ledger holds a product's own reviews. */
|
|
511
|
+
reviewLedger?: string;
|
|
512
|
+
/** `approvals.involved` at base (#4333). */
|
|
513
|
+
involved?: OpWavesInvolved;
|
|
492
514
|
}
|
|
493
515
|
|
|
494
516
|
const noHooks = (): Record<OpWaveHookMoment, OpWaveHook[]> =>
|
|
@@ -541,12 +563,24 @@ export function readOpWavePolicy(
|
|
|
541
563
|
}
|
|
542
564
|
|
|
543
565
|
/** The approval rules at base (#4290), or why they cannot be read. A spec at base with none has none. */
|
|
544
|
-
function quorumAtBase(spec: OpWavesSpec, where: string): Pick<OpWaveBaseRules, "quorum" | "quorumRefused"> {
|
|
545
|
-
const
|
|
566
|
+
function quorumAtBase(spec: OpWavesSpec, where: string): Pick<OpWaveBaseRules, "quorum" | "quorumRefused" | "reviewLedger" | "involved"> {
|
|
567
|
+
const a = (spec as { approvals?: { quorum?: unknown; reviewLedger?: unknown; involved?: unknown } }).approvals;
|
|
568
|
+
const raw = a?.quorum;
|
|
569
|
+
// #4333: where a product's reviews are, and who counts as involved, read at base with the rules.
|
|
570
|
+
const extra: Pick<OpWaveBaseRules, "reviewLedger" | "involved"> = {};
|
|
571
|
+
if (a?.reviewLedger !== undefined) {
|
|
572
|
+
if (typeof a.reviewLedger !== "string" || !OP_LEDGER_NAME.test(a.reviewLedger)) return { quorumRefused: `the approval rules in ${where} cannot be read (approvals.reviewLedger must name an op)` };
|
|
573
|
+
extra.reviewLedger = a.reviewLedger;
|
|
574
|
+
}
|
|
575
|
+
if (a?.involved !== undefined) {
|
|
576
|
+
const bad = opWavesInvolvedProblems(a.involved);
|
|
577
|
+
if (bad.length > 0) return { quorumRefused: `the approval rules in ${where} cannot be read (${bad.join("; ")})` };
|
|
578
|
+
extra.involved = structuredClone(a.involved as OpWavesInvolved);
|
|
579
|
+
}
|
|
546
580
|
if (raw === undefined) return {};
|
|
547
581
|
const problems = Array.isArray(raw) ? quorumProblems(raw, "approvals.quorum", { notAuthor: true }) : ["`approvals.quorum` must be a list of rules"];
|
|
548
582
|
if (problems.length > 0) return { quorumRefused: `the approval rules in ${where} cannot be read (${problems.join("; ")})` };
|
|
549
|
-
return (raw as GateQuorumRule[]).length > 0 ? { quorum: raw as GateQuorumRule[] } : {};
|
|
583
|
+
return (raw as GateQuorumRule[]).length > 0 ? { quorum: raw as GateQuorumRule[], ...extra } : {};
|
|
550
584
|
}
|
|
551
585
|
|
|
552
586
|
/** The point wave `name` asks at base (#3836), or why it cannot be asked. */
|
|
@@ -607,6 +641,14 @@ export interface RunOpWaveOptions {
|
|
|
607
641
|
signers?: (base: string) => GateSigners;
|
|
608
642
|
/** How a gate with a `point` asks it (#3836). Default: `workspaceGatePointAsker` over `cwd`. A tool that bundles chant passes `chantGatePointAsker`. */
|
|
609
643
|
points?: GatePointAsker;
|
|
644
|
+
/**
|
|
645
|
+
* Where the jobs' outcome files are (#4322), from `cwd`: the job reads the
|
|
646
|
+
* earlier waves' (a share job, its deciding job's) at any depth under it,
|
|
647
|
+
* and writes its own there. Default {@link opWaveOutcomeDir}.
|
|
648
|
+
*/
|
|
649
|
+
outcomeDir?: string;
|
|
650
|
+
/** The commits after base up to the applied head, for `Requested-by:` trailers (#4333). Default: `git log`. */
|
|
651
|
+
commits?: (base: string, head: string) => { sha: string; message: string }[];
|
|
610
652
|
}
|
|
611
653
|
|
|
612
654
|
export interface RunOpWaveResult {
|
|
@@ -630,6 +672,12 @@ export interface RunOpWaveResult {
|
|
|
630
672
|
failed: string[];
|
|
631
673
|
/** Runs a share job refused because their plan moved since the decision. */
|
|
632
674
|
moved: string[];
|
|
675
|
+
/**
|
|
676
|
+
* The runs a failure blocked (#4322), each with the run whose failure
|
|
677
|
+
* blocked it: a run of an earlier wave, or one listed before it in this
|
|
678
|
+
* wave. None of them was planned or applied.
|
|
679
|
+
*/
|
|
680
|
+
blocked?: Record<string, string>;
|
|
633
681
|
/** The hooks that ran (#3762). */
|
|
634
682
|
hooks: OpWaveHookOutcome[];
|
|
635
683
|
}
|
|
@@ -1150,12 +1198,55 @@ export async function runOpWave(options: RunOpWaveOptions): Promise<RunOpWaveRes
|
|
|
1150
1198
|
const { spec } = options;
|
|
1151
1199
|
assertOpWavesSpec(spec);
|
|
1152
1200
|
const log = options.log ?? ((line: string) => console.error(line));
|
|
1153
|
-
const
|
|
1201
|
+
const cwd = options.cwd ?? process.cwd();
|
|
1202
|
+
const outcomeDir = options.outcomeDir ?? opWaveOutcomeDir(spec);
|
|
1203
|
+
const dir = isAbsolute(outcomeDir) ? outcomeDir : join(cwd, outcomeDir);
|
|
1204
|
+
// #4322: what the earlier jobs' outcome files say: an earlier wave that stopped stops this one, and a failure blocks its dependents.
|
|
1205
|
+
const before = opWaveBefore(options, dir);
|
|
1206
|
+
const blocked = before.blocked;
|
|
1207
|
+
if (before.stop) {
|
|
1208
|
+
log(before.stop.line);
|
|
1209
|
+
const stopped: RunOpWaveResult = { exitCode: before.stop.exitCode, applied: [], failed: [], moved: [], hooks: [], ...(blocked.size > 0 ? { blocked: Object.fromEntries(blocked) } : {}) };
|
|
1210
|
+
writeOpWaveOutcome(options, dir, stopped, before.stop.members);
|
|
1211
|
+
return stopped;
|
|
1212
|
+
}
|
|
1213
|
+
if (blocked.size > 0) log(`wave ${options.wave}: ${blockedWords(blocked)}, so not planned or applied`);
|
|
1214
|
+
const mine = jobRuns(options);
|
|
1215
|
+
if (mine.length > 0 && mine.every((t) => blocked.has(t))) {
|
|
1216
|
+
// Every run of this job is blocked: nothing to plan, decide or apply.
|
|
1217
|
+
const none: RunOpWaveResult = { exitCode: options.decide ? 0 : 1, applied: [], failed: [], moved: [], hooks: [], blocked: Object.fromEntries(blocked) };
|
|
1218
|
+
writeOpWaveOutcome(options, dir, none);
|
|
1219
|
+
return none;
|
|
1220
|
+
}
|
|
1221
|
+
let result: RunOpWaveResult;
|
|
1154
1222
|
const applied: string[] = [];
|
|
1223
|
+
try {
|
|
1224
|
+
result = await runOpWaveLoop(options, log, applied, blocked);
|
|
1225
|
+
} catch (err) {
|
|
1226
|
+
writeOpWaveOutcome(options, dir, { exitCode: 1, applied, failed: [], moved: [], hooks: [], ...(blocked.size > 0 ? { blocked: Object.fromEntries(blocked) } : {}) });
|
|
1227
|
+
throw err;
|
|
1228
|
+
}
|
|
1229
|
+
const all = { ...Object.fromEntries(blocked), ...(result.blocked ?? {}) };
|
|
1230
|
+
if (Object.keys(all).length > 0) {
|
|
1231
|
+
result.blocked = all;
|
|
1232
|
+
// A deciding job applies nothing; its share jobs fail for the blocked runs of their slices.
|
|
1233
|
+
if (result.exitCode === 0 && !options.decide) {
|
|
1234
|
+
log(`wave ${options.wave}: the runs that could apply did; ${blockedWords(new Map(Object.entries(all)))}, so this job fails`);
|
|
1235
|
+
result.exitCode = 1;
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
writeOpWaveOutcome(options, dir, result);
|
|
1239
|
+
return result;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
/** The wave engine's loop over this module's steps, from `options.wave` on, with the runs in `skip` left out of that wave. */
|
|
1243
|
+
async function runOpWaveLoop(options: RunOpWaveOptions, log: (line: string) => void, applied: string[], skip: ReadonlyMap<string, string>): Promise<RunOpWaveResult> {
|
|
1244
|
+
const { spec } = options;
|
|
1245
|
+
const last = spec.waves[spec.waves.length - 1]!;
|
|
1155
1246
|
const rest: NonNullable<RunOpWaveResult["rest"]> = [];
|
|
1156
1247
|
const result = await runWaveLoop<OpWavePlanned, OpWaveDecided, RunOpWaveResult>({
|
|
1157
1248
|
first: options.wave,
|
|
1158
|
-
plan: (at) => planOpWave(options, at),
|
|
1249
|
+
plan: (at) => planOpWave(options, at, at.k === options.wave ? skip : undefined),
|
|
1159
1250
|
// A share job applies under the digest its deciding job recorded; it does not take the set digest again.
|
|
1160
1251
|
digest: (_at, planned) => (planned.kind === "share" ? planned.decision.digest : opWaveSetDigest(spec, planned.members, planned.extras)),
|
|
1161
1252
|
decide: (at, planned, digest) => (planned.kind === "share" ? shareUnmoved(planned) : decideOpWave(options, at, planned, digest)),
|
|
@@ -1183,6 +1274,116 @@ export async function runOpWave(options: RunOpWaveOptions): Promise<RunOpWaveRes
|
|
|
1183
1274
|
return { ...result, applied, ...(rest.length > 0 ? { rest } : {}) };
|
|
1184
1275
|
}
|
|
1185
1276
|
|
|
1277
|
+
/** What the earlier outcome files hold for a job (#4322): the runs they block, or why the job does not run at all. */
|
|
1278
|
+
interface OpWaveBefore {
|
|
1279
|
+
/** Each blocked run of this wave, with the run whose failure blocked it. */
|
|
1280
|
+
blocked: Map<string, string>;
|
|
1281
|
+
/** Set when the job runs nothing: its exit code, the log line, and the outcomes it writes. */
|
|
1282
|
+
stop?: { exitCode: number; line: string; members: Record<string, WaveMemberOutcome> };
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
/**
|
|
1286
|
+
* Read the outcome files under `dir` for wave `k`'s job (#4322). A wave or
|
|
1287
|
+
* deciding job reads the earlier waves': with none at all (a pipeline
|
|
1288
|
+
* rendered before #4322, or a job run by hand) every earlier run counts as
|
|
1289
|
+
* applied, as `needs:` used to promise. An earlier run that waits at its gate
|
|
1290
|
+
* stops this wave (exit 3), and one that was refused, held, stood down or
|
|
1291
|
+
* moved, or whose share never reported, stops it too (exit 1): only a failure
|
|
1292
|
+
* lets the waves after it go on. Otherwise a run whose `dependsOn` names a
|
|
1293
|
+
* run that failed or was blocked is blocked, and so is one that depends on
|
|
1294
|
+
* it. A share job reads its deciding job's file instead: the runs it blocked
|
|
1295
|
+
* stay blocked, and a run that job failed on stops the share (exit 1), so a
|
|
1296
|
+
* decision record it left behind before failing applies nothing.
|
|
1297
|
+
*/
|
|
1298
|
+
function opWaveBefore(options: RunOpWaveOptions, dir: string): OpWaveBefore {
|
|
1299
|
+
const { spec, wave: k } = options;
|
|
1300
|
+
const wave = spec.waves[k - 1];
|
|
1301
|
+
if (!wave) return { blocked: new Map() };
|
|
1302
|
+
if (options.share !== undefined || options.group !== undefined) {
|
|
1303
|
+
const decided = readWaveOutcomeFile([dir], waveOutcomeFileName(k));
|
|
1304
|
+
if (!decided) return { blocked: new Map() };
|
|
1305
|
+
const blocked = new Map<string, string>();
|
|
1306
|
+
const held: Array<[string, WaveMemberOutcome]> = [];
|
|
1307
|
+
for (const [target, o] of Object.entries(decided.members)) {
|
|
1308
|
+
if (o.status === "blocked") blocked.set(target, o.by ?? target);
|
|
1309
|
+
// A wave that waits or was refused says so in its decision record, which the share reads as before.
|
|
1310
|
+
else if (o.status !== "decided" && o.status !== "waiting" && o.status !== "refused") held.push([target, o]);
|
|
1311
|
+
}
|
|
1312
|
+
if (held.length === 0) return { blocked };
|
|
1313
|
+
const line = `${shareLabel(options)} of wave ${k} (${wave.name}) applies nothing: its deciding job did not decide ${held.map(([t, o]) => `${t} (${o.status})`).join(", ")}`;
|
|
1314
|
+
return { blocked, stop: { exitCode: 1, line, members: { ...decided.members } } };
|
|
1315
|
+
}
|
|
1316
|
+
if (k === 1) return { blocked: new Map() };
|
|
1317
|
+
const { members } = earlierWaveOutcomes([dir], k);
|
|
1318
|
+
if (members.size === 0) return { blocked: new Map() };
|
|
1319
|
+
const held = [...members].filter(([, o]) => !passesThrough(o) && o.status !== "failed" && o.status !== "blocked");
|
|
1320
|
+
if (held.length > 0) {
|
|
1321
|
+
const waiting = held.filter(([, o]) => o.status === "waiting");
|
|
1322
|
+
const shown = (waiting.length > 0 ? waiting : held).map(([t, o]) => `${t} (wave ${o.wave}${waiting.length > 0 ? "" : `, ${o.status}`})`).join(", ");
|
|
1323
|
+
const line = waiting.length > 0
|
|
1324
|
+
? `Nothing in wave ${k} (${wave.name}) ran: ${shown} waits at its gate. Approve it and run that wave's job again, then this one.`
|
|
1325
|
+
: `Nothing in wave ${k} (${wave.name}) ran: ${shown} did not apply, and only a failure lets the waves after it go on.`;
|
|
1326
|
+
const status = waiting.length > 0 ? "waiting" : "not-applied";
|
|
1327
|
+
return { blocked: new Map(), stop: { exitCode: waiting.length > 0 ? 3 : 1, line, members: Object.fromEntries((wave.runs ?? []).map((r) => [r.target, { status }])) } };
|
|
1328
|
+
}
|
|
1329
|
+
const runs = wave.runs ?? [];
|
|
1330
|
+
const index = new Map(runs.map((r, i) => [r.target, i]));
|
|
1331
|
+
const ownBefore = (i: number, dep: string): boolean => (index.get(dep) ?? Infinity) < i;
|
|
1332
|
+
const upstreams = new Map(runs.map((r, i) => [r.target, (r.dependsOn ?? []).filter((d) => !ownBefore(i, d))]));
|
|
1333
|
+
const blocked = blockedMembers(runs.map((r) => r.target), upstreams, new Set([...upstreams.values()].flat()), members);
|
|
1334
|
+
// A run listed before this one in its own wave and blocked blocks it too, by the same failure.
|
|
1335
|
+
runs.forEach((run, i) => {
|
|
1336
|
+
if (blocked.has(run.target)) return;
|
|
1337
|
+
const dep = (run.dependsOn ?? []).filter((d) => ownBefore(i, d) && blocked.has(d)).sort()[0];
|
|
1338
|
+
if (dep !== undefined) blocked.set(run.target, blocked.get(dep)!);
|
|
1339
|
+
});
|
|
1340
|
+
return { blocked };
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
/** The runs of wave `options.wave` this job holds (#4322): its slice for a share job, every run otherwise. Empty for a discovering wave. */
|
|
1344
|
+
function jobRuns(options: RunOpWaveOptions, runs?: readonly OpWaveRun[]): string[] {
|
|
1345
|
+
const wave = options.spec.waves[options.wave - 1];
|
|
1346
|
+
if (!wave) return [];
|
|
1347
|
+
const all = runs ?? (wave.discover ? [] : wave.runs);
|
|
1348
|
+
if (options.share === undefined && options.group === undefined) return all.map((r) => r.target);
|
|
1349
|
+
const group = options.group === undefined ? undefined : wave.jobs?.find((g) => g.name === options.group);
|
|
1350
|
+
if (options.group !== undefined && !group) return [];
|
|
1351
|
+
const shares = group ? (group.shares ?? 1) : (wave.shares ?? 1);
|
|
1352
|
+
return opWaveShare(group ? opWaveGroupRuns(group, all) : all, options.share ?? 1, shares).map((r) => r.target);
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
/**
|
|
1356
|
+
* Write this job's outcome file (#4322): each of its runs' outcome, from how
|
|
1357
|
+
* the job ended. `members`, when given, is written as it is.
|
|
1358
|
+
*/
|
|
1359
|
+
function writeOpWaveOutcome(options: RunOpWaveOptions, dir: string, result: RunOpWaveResult, members?: Record<string, WaveMemberOutcome>): void {
|
|
1360
|
+
const out: Record<string, WaveMemberOutcome> = { ...(members ?? {}) };
|
|
1361
|
+
if (!members) {
|
|
1362
|
+
const found = result.decision?.discovered !== undefined ? result.decision.members.map((m) => ({ target: m.member })) : undefined;
|
|
1363
|
+
const targets = new Set([...jobRuns(options, found), ...result.applied, ...result.failed, ...result.moved, ...Object.keys(result.blocked ?? {})]);
|
|
1364
|
+
const applied = new Set(result.applied);
|
|
1365
|
+
const failed = new Set(result.failed);
|
|
1366
|
+
const moved = new Set(result.moved);
|
|
1367
|
+
const otherwise: WaveMemberOutcome["status"] =
|
|
1368
|
+
result.exitCode === 0 ? (options.decide ? "decided" : "unchanged")
|
|
1369
|
+
: result.exitCode === 3 ? "waiting"
|
|
1370
|
+
: result.exitCode === 7 || result.exitCode === 8 ? "refused"
|
|
1371
|
+
: result.exitCode >= 4 && result.exitCode <= 6 ? "not-applied"
|
|
1372
|
+
: "failed";
|
|
1373
|
+
for (const t of targets) {
|
|
1374
|
+
const by = result.blocked?.[t];
|
|
1375
|
+
out[t] = by !== undefined ? { status: "blocked", by } : applied.has(t) ? { status: "applied" } : failed.has(t) ? { status: "failed" } : moved.has(t) ? { status: "not-applied" } : { status: otherwise };
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
const part = { ...(options.group !== undefined ? { group: options.group } : {}), ...(options.share !== undefined ? { share: options.share } : {}) };
|
|
1379
|
+
try {
|
|
1380
|
+
mkdirSync(dir, { recursive: true });
|
|
1381
|
+
writeWaveOutcomeFile(dir, options.wave, part, out, options.now ?? new Date().toISOString());
|
|
1382
|
+
} catch (err) {
|
|
1383
|
+
(options.log ?? ((line: string) => console.error(line)))(`wave ${options.wave}: could not write its outcome file in ${dir}: ${err instanceof Error ? err.message : String(err)}`);
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1186
1387
|
/** What a share or job group's job calls itself in the log: `share 2`, `job group "prod"`, `share 2 of job group "prod"`. */
|
|
1187
1388
|
function shareLabel(options: Pick<RunOpWaveOptions, "share" | "group">): string {
|
|
1188
1389
|
if (options.group === undefined) return `share ${options.share}`;
|
|
@@ -1240,7 +1441,7 @@ interface OpWaveDecided {
|
|
|
1240
1441
|
* a hook fails or holds it on another gate, or a share's decision waits or
|
|
1241
1442
|
* was refused.
|
|
1242
1443
|
*/
|
|
1243
|
-
async function planOpWave(options: RunOpWaveOptions, { k, pass }: WaveAttempt<RunOpWaveResult>): Promise<WaveStep<OpWavePlanned, RunOpWaveResult>> {
|
|
1444
|
+
async function planOpWave(options: RunOpWaveOptions, { k, pass }: WaveAttempt<RunOpWaveResult>, skip?: ReadonlyMap<string, string>): Promise<WaveStep<OpWavePlanned, RunOpWaveResult>> {
|
|
1244
1445
|
const { spec } = options;
|
|
1245
1446
|
const cwd = options.cwd ?? process.cwd();
|
|
1246
1447
|
const exec = options.exec ?? spawnExec;
|
|
@@ -1287,11 +1488,14 @@ async function planOpWave(options: RunOpWaveOptions, { k, pass }: WaveAttempt<Ru
|
|
|
1287
1488
|
wave = { ...wave, runs: decision.members.map((m) => ({ target: m.member, ...(m.op !== spec.op ? { op: m.op } : {}) })) };
|
|
1288
1489
|
ctx.wave = wave;
|
|
1289
1490
|
}
|
|
1290
|
-
const
|
|
1291
|
-
if (group &&
|
|
1491
|
+
const whole = opWaveShare(group ? opWaveGroupRuns(group, wave.runs) : wave.runs, options.share ?? 1, shares);
|
|
1492
|
+
if (group && whole.length === 0) {
|
|
1292
1493
|
log(`${part} of wave ${k} (${wave.name}) holds none of the wave's runs; nothing to apply`);
|
|
1293
1494
|
return { end: result };
|
|
1294
1495
|
}
|
|
1496
|
+
// #4322: the runs its deciding job blocked are neither planned nor applied here.
|
|
1497
|
+
const slice = whole.filter((r) => !skip?.has(r.target));
|
|
1498
|
+
if (slice.length === 0) return { end: result };
|
|
1295
1499
|
const before = await runBeforePlanHooks(ctx, decision.hooks, slice);
|
|
1296
1500
|
if (before.failed) return { end: failed(ctx, `a hook before the plan failed, so nothing in ${part} of wave ${k} was planned or applied`) };
|
|
1297
1501
|
if (before.waitingOn) return { end: await waitOnOther(ctx, decision, before.waitingOn) };
|
|
@@ -1347,6 +1551,11 @@ async function planOpWave(options: RunOpWaveOptions, { k, pass }: WaveAttempt<Ru
|
|
|
1347
1551
|
...(neverOverMcp ? { neverOverMcp: true as const } : {}),
|
|
1348
1552
|
...(rules.point ? { point: { ...rules.point } } : {}),
|
|
1349
1553
|
};
|
|
1554
|
+
if (skip?.size && !wave.discover) {
|
|
1555
|
+
// #4322: a run a failure blocked is neither planned nor in the set digest.
|
|
1556
|
+
wave = { ...wave, runs: wave.runs.filter((r) => !skip.has(r.target)) };
|
|
1557
|
+
ctx.wave = wave;
|
|
1558
|
+
}
|
|
1350
1559
|
const before = await runBeforePlanHooks(ctx, rules.hooks, wave.runs);
|
|
1351
1560
|
if (before.failed) return { end: failed(ctx, `a hook before the plan failed, so nothing in wave ${k} was planned or applied`) };
|
|
1352
1561
|
if (before.waitingOn) return { end: await decided(ctx, decision, recordPath, before.waitingOn) };
|
|
@@ -1423,7 +1632,11 @@ async function decideOpWave(
|
|
|
1423
1632
|
decision.members = members;
|
|
1424
1633
|
// #4290: the rules at base whose targets glob matches one of the wave's runs.
|
|
1425
1634
|
const takes = planned.rules.quorum ? quorumRulesFor(planned.rules.quorum, members.map((m) => m.member)) : [];
|
|
1426
|
-
if (takes.length > 0)
|
|
1635
|
+
if (takes.length > 0) {
|
|
1636
|
+
decision.quorum = takes;
|
|
1637
|
+
if (planned.rules.reviewLedger) decision.reviewLedger = planned.rules.reviewLedger;
|
|
1638
|
+
if (planned.rules.involved) decision.involved = planned.rules.involved;
|
|
1639
|
+
}
|
|
1427
1640
|
if (extras) decision.extras = extras;
|
|
1428
1641
|
if (pending) decision.pending = pending;
|
|
1429
1642
|
const after = await runHooks(ctx, "after-plan", planned.rules.hooks["after-plan"], wave.runs, planned.planned, digest);
|
|
@@ -1741,6 +1954,16 @@ async function settleGate(options: RunOpWaveOptions, ctx: WaveContext, decision:
|
|
|
1741
1954
|
decision.approve = approveCommand(spec.name, gate, undefined, digest, approval === "sealed");
|
|
1742
1955
|
}
|
|
1743
1956
|
|
|
1957
|
+
/** The commits after `base` up to `head`, merge commits left out, for the `Requested-by:` trailers on them (#4333). */
|
|
1958
|
+
const gitCommitsBetween = (cwd: string) => (base: string, head: string): { sha: string; message: string }[] => {
|
|
1959
|
+
try {
|
|
1960
|
+
const out = execFileSync("git", ["log", "--no-merges", "--format=%H%x00%B%x01", `${base}..${head}`], { cwd, encoding: "utf-8" });
|
|
1961
|
+
return out.split("\x01").map((c) => c.replace(/^\n/, "")).filter((c) => c.includes("\x00")).map((c) => ({ sha: c.slice(0, c.indexOf("\x00")), message: c.slice(c.indexOf("\x00") + 1) }));
|
|
1962
|
+
} catch {
|
|
1963
|
+
return [];
|
|
1964
|
+
}
|
|
1965
|
+
};
|
|
1966
|
+
|
|
1744
1967
|
/**
|
|
1745
1968
|
* Decide a gate under approval rules (#4290): the rules at base the wave's
|
|
1746
1969
|
* targets take, each met by distinct human approvers of the digest. Roles
|
|
@@ -1764,7 +1987,7 @@ async function settleQuorumGate(options: RunOpWaveOptions, ctx: WaveContext, dec
|
|
|
1764
1987
|
// The merged pull request: its author for notAuthor, and its review under pr-review.
|
|
1765
1988
|
let merged: MergedReview | null = null;
|
|
1766
1989
|
let unknown: string | undefined;
|
|
1767
|
-
const asks = approval === "pr-review" || rules.some((r) => r.notAuthor);
|
|
1990
|
+
const asks = approval === "pr-review" || rules.some((r) => r.notAuthor) || decision.involved !== undefined;
|
|
1768
1991
|
const head = asks ? (options.head ?? execFileSync("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf-8" }).trim()) : "";
|
|
1769
1992
|
if (asks) {
|
|
1770
1993
|
try {
|
|
@@ -1809,12 +2032,54 @@ async function settleQuorumGate(options: RunOpWaveOptions, ctx: WaveContext, dec
|
|
|
1809
2032
|
}
|
|
1810
2033
|
}
|
|
1811
2034
|
|
|
1812
|
-
|
|
2035
|
+
// #4333: reviews a product recorded itself, on the ledger the spec at base names. The ledger is
|
|
2036
|
+
// the lifecycle branch's, never the change's, and proves a reviewer only under `pr-review`.
|
|
2037
|
+
const principal = review.forgePrincipalFromEnv();
|
|
2038
|
+
let recorded: { head: string; approvers: string[] }[] = [];
|
|
2039
|
+
if (decision.reviewLedger && approval === "pr-review") {
|
|
2040
|
+
const lines = (await ledger.read(decision.reviewLedger)).resolutions.filter((r) => r.gate === gate && samePlanDigest(r.planDigest, digest));
|
|
2041
|
+
const read = recordedReviewApprovals(lines, principal);
|
|
2042
|
+
recorded = read.reviews.filter((x) => !(spent !== undefined && isApprovalSpent(spent, { gate, planDigest: digest, review: { head: x.head } })));
|
|
2043
|
+
const had = (await ledger.read(spec.name)).resolutions.filter((r) => r.gate === gate && samePlanDigest(r.planDigest, digest));
|
|
2044
|
+
for (const rec of read.records) {
|
|
2045
|
+
if (!rec.review || !recorded.some((x) => x.head === rec.review!.head) || had.some((r) => r.review?.head === rec.review!.head && samePrincipal(r.resolvedBy, rec.resolvedBy))) continue;
|
|
2046
|
+
await ledger.appendResolution?.({
|
|
2047
|
+
...rec,
|
|
2048
|
+
op: spec.name,
|
|
2049
|
+
gate,
|
|
2050
|
+
timestamp: now,
|
|
2051
|
+
planDigest: digest,
|
|
2052
|
+
note: `approved by a review ${decision.reviewLedger} recorded for ${rec.review.head.slice(0, 12)}: ${rec.review.approvers.join(", ")}`,
|
|
2053
|
+
});
|
|
2054
|
+
}
|
|
2055
|
+
if (recorded.length > 0) log(`${label}: ${decision.reviewLedger} recorded a review of ${digest} by ${[...new Set(recorded.flatMap((x) => x.approvers))].join(", ")}`);
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
// #4333: everyone involved in the change, from the commits after base and the agents' accounts at base.
|
|
2059
|
+
const involved = decision.involved || merged ? changeInvolvement({
|
|
2060
|
+
...(merged ? { author: merged.author } : {}),
|
|
2061
|
+
commits: decision.involved ? (options.commits ?? gitCommitsBetween(cwd))(base, head) : [],
|
|
2062
|
+
...(decision.involved?.agents ? { agents: decision.involved.agents.map(principal) } : {}),
|
|
2063
|
+
principal,
|
|
2064
|
+
}) : [];
|
|
2065
|
+
const said = new Set<string>();
|
|
2066
|
+
const sayExcluded = (j: QuorumJudgement): QuorumJudgement => {
|
|
2067
|
+
if (j.excluded !== undefined && !said.has(j.excluded)) {
|
|
2068
|
+
said.add(j.excluded);
|
|
2069
|
+
log(`${label}: ${j.excluded}`);
|
|
2070
|
+
}
|
|
2071
|
+
return j;
|
|
2072
|
+
};
|
|
2073
|
+
const judgeBase = trustQuorumJudge({
|
|
1813
2074
|
signers: trust,
|
|
1814
2075
|
roles: trust.roles,
|
|
1815
2076
|
...(merged ? { authors: [merged.author] } : {}),
|
|
2077
|
+
...(involved.length > 0 ? { involved } : {}),
|
|
2078
|
+
...(decision.involved?.exclude ? { excludeInvolved: true } : {}),
|
|
1816
2079
|
...(reviewed ? { review: reviewed } : {}),
|
|
2080
|
+
...(recorded.length > 0 ? { recorded } : {}),
|
|
1817
2081
|
});
|
|
2082
|
+
const judge: GateQuorumJudge = (r) => sayExcluded(judgeBase(r));
|
|
1818
2083
|
const held = decision.heldBy?.length ? `, held by ${decision.heldBy.join(", ")}` : "";
|
|
1819
2084
|
const check = await decideWaveGate(port, {
|
|
1820
2085
|
op: spec.name,
|
|
@@ -2124,7 +2389,16 @@ async function applyStage(
|
|
|
2124
2389
|
result.failed.push(...runs.map((r) => r.target));
|
|
2125
2390
|
}
|
|
2126
2391
|
} else {
|
|
2127
|
-
|
|
2392
|
+
const order = new Map(runs.map((r, i) => [r.target, i]));
|
|
2393
|
+
for (const [i, run] of runs.entries()) {
|
|
2394
|
+
// #4322: a run listed before this one that failed, or was blocked, blocks it.
|
|
2395
|
+
const dep = (run.dependsOn ?? []).filter((d) => (order.get(d) ?? Infinity) < i && (result.failed.includes(d) || result.blocked?.[d] !== undefined)).sort()[0];
|
|
2396
|
+
if (dep !== undefined) {
|
|
2397
|
+
const by = result.blocked?.[dep] ?? dep;
|
|
2398
|
+
result.blocked = { ...result.blocked, [run.target]: by };
|
|
2399
|
+
log(`${run.target}: blocked by ${by}, so not applied`);
|
|
2400
|
+
continue;
|
|
2401
|
+
}
|
|
2128
2402
|
const key = run.target.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
2129
2403
|
// Under runBy "apply" each run's apply runs its own apply-stage hooks, over a runs file of that run alone.
|
|
2130
2404
|
const runsPath = byApply ? writeRunsFile(ctx, [run], planned, decision.digest, `.chant/op-waves/${spec.name}/wave-${k}/${key}.runs.json`) : opWaveRunsPath(spec, k);
|