@intentius/chant 0.124.45 → 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/capabilities/aws.paths +148 -0
- package/dist/capabilities/base-mappings.json +122 -0
- package/dist/capabilities/catalog.d.ts +89 -0
- package/dist/capabilities/catalog.d.ts.map +1 -0
- package/dist/capabilities/catalog.js +204 -0
- package/dist/capabilities/language.d.ts +103 -0
- package/dist/capabilities/language.d.ts.map +1 -0
- package/dist/capabilities/language.js +335 -0
- package/dist/capabilities/matcher.d.ts +65 -0
- package/dist/capabilities/matcher.d.ts.map +1 -0
- package/dist/capabilities/matcher.js +299 -0
- package/dist/capabilities/view.d.ts +207 -0
- package/dist/capabilities/view.d.ts.map +1 -0
- package/dist/capabilities/view.js +484 -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/lint.d.ts.map +1 -1
- package/dist/cli/commands/lint.js +1 -0
- 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/declared-graph.d.ts +44 -0
- package/dist/cli/handlers/declared-graph.d.ts.map +1 -0
- package/dist/cli/handlers/declared-graph.js +87 -0
- package/dist/cli/handlers/graph.d.ts +25 -0
- package/dist/cli/handlers/graph.d.ts.map +1 -1
- package/dist/cli/handlers/graph.js +93 -87
- 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.d.ts.map +1 -1
- package/dist/cli/handlers/pr-env.js +4 -3
- 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-count.d.ts +89 -0
- package/dist/cli/handlers/search-count.d.ts.map +1 -0
- package/dist/cli/handlers/search-count.js +132 -0
- package/dist/cli/handlers/search.d.ts +356 -6
- package/dist/cli/handlers/search.d.ts.map +1 -1
- package/dist/cli/handlers/search.js +1039 -155
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +88 -17
- package/dist/cli/mcp/server.d.ts.map +1 -1
- package/dist/cli/mcp/server.js +3 -0
- package/dist/cli/mcp/tools/capabilities.d.ts +7 -0
- package/dist/cli/mcp/tools/capabilities.d.ts.map +1 -0
- package/dist/cli/mcp/tools/capabilities.js +27 -0
- package/dist/cli/mcp/workspace-tools.d.ts +3 -1
- package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
- package/dist/cli/mcp/workspace-tools.js +47 -2
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +100 -19
- package/dist/cli/registry.d.ts +36 -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-env-ports.d.ts +29 -0
- package/dist/components/pr-env-ports.d.ts.map +1 -0
- package/dist/components/pr-env-ports.js +77 -0
- package/dist/components/pr-env-run.d.ts +5 -21
- package/dist/components/pr-env-run.d.ts.map +1 -1
- package/dist/components/pr-env-run.js +6 -70
- package/dist/components/pr-environment.d.ts +2 -1
- package/dist/components/pr-environment.d.ts.map +1 -1
- package/dist/components/pr-environment.js +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 +112 -0
- package/dist/config-environments.d.ts.map +1 -0
- package/dist/config-environments.js +114 -0
- package/dist/config.d.ts +32 -84
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +13 -96
- 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-detail.d.ts.map +1 -1
- package/dist/graph-detail.js +15 -3
- package/dist/graph-effective.d.ts +33 -2
- package/dist/graph-effective.d.ts.map +1 -1
- package/dist/graph-effective.js +215 -68
- package/dist/graph-ir.d.ts +48 -0
- package/dist/graph-ir.d.ts.map +1 -1
- package/dist/graph-ir.js +130 -0
- package/dist/graph-sub-template.d.ts +11 -0
- package/dist/graph-sub-template.d.ts.map +1 -0
- package/dist/graph-sub-template.js +19 -0
- 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 +80 -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/observe.d.ts +28 -0
- package/dist/lifecycle/observe.d.ts.map +1 -1
- package/dist/lifecycle/observe.js +23 -1
- 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/rule.d.ts +6 -0
- package/dist/lint/rule.d.ts.map +1 -1
- 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/live-endpoint.d.ts +1 -1
- package/dist/live-endpoint.d.ts.map +1 -1
- package/dist/live-endpoint.js +1 -1
- package/dist/observation.d.ts +48 -1
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +21 -5
- 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.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 +266 -256
- package/dist/workspace/capabilities-contract.d.ts +66 -0
- package/dist/workspace/capabilities-contract.d.ts.map +1 -0
- package/dist/workspace/capabilities-contract.js +107 -0
- package/dist/workspace/capabilities.schema.json +229 -0
- 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 +23 -0
- package/dist/workspace/compose-graph.d.ts.map +1 -1
- package/dist/workspace/compose-graph.js +3 -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/conformance/index.d.ts +1 -1
- package/dist/workspace/conformance/index.d.ts.map +1 -1
- package/dist/workspace/conformance/index.js +39 -2
- 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-cache.d.ts +8 -0
- package/dist/workspace/graph-cache.d.ts.map +1 -1
- package/dist/workspace/graph-cache.js +27 -3
- package/dist/workspace/graph-cli.d.ts +39 -2
- package/dist/workspace/graph-cli.d.ts.map +1 -1
- package/dist/workspace/graph-cli.js +92 -32
- package/dist/workspace/graph.schema.json +182 -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/kind-readers.d.ts +3 -0
- package/dist/workspace/kind-readers.d.ts.map +1 -1
- package/dist/workspace/kind-readers.js +7 -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 +10 -1
- package/dist/workspace/member-commands.d.ts.map +1 -1
- package/dist/workspace/member-commands.js +71 -6
- 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/nested-graph.d.ts +2 -0
- package/dist/workspace/nested-graph.d.ts.map +1 -1
- package/dist/workspace/nested-graph.js +32 -1
- package/dist/workspace/reason-codes.d.ts +18 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +23 -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-cli.d.ts +204 -0
- package/dist/workspace/search-cli.d.ts.map +1 -0
- package/dist/workspace/search-cli.js +466 -0
- package/dist/workspace/search-contract.d.ts +56 -0
- package/dist/workspace/search-contract.d.ts.map +1 -0
- package/dist/workspace/search-contract.js +70 -0
- package/dist/workspace/search.schema.json +822 -0
- 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/__snapshots__/okf.test.ts.snap +10 -0
- package/src/action-pins.test.ts +78 -0
- package/src/action-pins.ts +92 -0
- package/src/capabilities/aws.paths +148 -0
- package/src/capabilities/base-mappings.json +122 -0
- package/src/capabilities/catalog.ts +230 -0
- package/src/capabilities/language.test.ts +191 -0
- package/src/capabilities/language.ts +373 -0
- package/src/capabilities/matcher.ts +315 -0
- package/src/capabilities/view-compose.test.ts +76 -0
- package/src/capabilities/view.ts +631 -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/lint.ts +1 -0
- 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/declared-graph.ts +99 -0
- package/src/cli/handlers/graph.test.ts +94 -3
- package/src/cli/handlers/graph.ts +123 -96
- 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 +3 -4
- 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-build-roots.test.ts +144 -0
- package/src/cli/handlers/search-count.test.ts +191 -0
- package/src/cli/handlers/search-count.ts +165 -0
- package/src/cli/handlers/search-json.test.ts +333 -0
- package/src/cli/handlers/search-live.test.ts +387 -0
- package/src/cli/handlers/search-paths.test.ts +235 -0
- package/src/cli/handlers/search.ts +1291 -166
- package/src/cli/main.test.ts +43 -3
- package/src/cli/main.ts +88 -17
- package/src/cli/mcp/server.test.ts +3 -3
- package/src/cli/mcp/server.ts +3 -0
- package/src/cli/mcp/tools/capabilities.ts +32 -0
- package/src/cli/mcp/workspace-tools.e2e.test.ts +21 -1
- package/src/cli/mcp/workspace-tools.ts +47 -2
- package/src/cli/parse-args.ts +79 -15
- package/src/cli/registry.ts +36 -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-ports.ts +89 -0
- package/src/components/pr-env-run-bundle.test.ts +54 -0
- package/src/components/pr-env-run.ts +5 -76
- package/src/components/pr-environment.ts +2 -1
- 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 +160 -0
- package/src/config.ts +44 -124
- 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-detail.ts +15 -3
- package/src/graph-effective.ts +226 -75
- package/src/graph-ir.test.ts +163 -0
- package/src/graph-ir.ts +174 -0
- package/src/graph-sub-template.ts +22 -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 +84 -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/observe.test.ts +27 -1
- package/src/lifecycle/observe.ts +43 -1
- 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/rule.ts +6 -0
- package/src/lint/rules/op/index.ts +2 -0
- package/src/lint/rules/op/ops019-workspace-op-target.ts +89 -0
- package/src/live-endpoint.ts +1 -1
- package/src/observation.test.ts +25 -0
- package/src/observation.ts +69 -5
- 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/capabilities-contract.test.ts +88 -0
- package/src/workspace/capabilities-contract.ts +132 -0
- package/src/workspace/capabilities.schema.json +229 -0
- 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 +19 -3
- 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/conformance/conformance.e2e.test.ts +14 -1
- package/src/workspace/conformance/index.ts +31 -2
- 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-cache.ts +27 -3
- package/src/workspace/graph-cli.ts +119 -32
- package/src/workspace/graph-contract.test.ts +4 -2
- package/src/workspace/graph.schema.json +182 -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/kind-readers.e2e.test.ts +28 -0
- package/src/workspace/kind-readers.test.ts +1 -1
- package/src/workspace/kind-readers.ts +7 -1
- 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 +82 -3
- 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/nested-graph.ts +32 -1
- package/src/workspace/org-scope.test.ts +238 -0
- package/src/workspace/reason-codes.test.ts +13 -1
- package/src/workspace/reason-codes.ts +23 -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/search-cli.e2e.test.ts +305 -0
- package/src/workspace/search-cli.ts +591 -0
- package/src/workspace/search-contract.ts +95 -0
- package/src/workspace/search.schema.json +822 -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
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
import { spawn } from "node:child_process";
|
|
24
24
|
import type { ParsedArgs } from "../cli/registry";
|
|
25
|
+
import { isViewDocument, prefixView, VIEW_DOCUMENT_VERSION } from "../capabilities/view";
|
|
25
26
|
import { danglingKey, SCOPED_GROUPS, type ComposedMember, type ComposedNode, type WorkspaceGraph } from "./compose-graph";
|
|
26
27
|
|
|
27
28
|
export type { NestedWorkspace } from "./compose-graph";
|
|
@@ -45,6 +46,7 @@ export function nestedArgv(dir: string, args: Partial<ParsedArgs>, at: string |
|
|
|
45
46
|
...(args.traffic !== undefined ? ["--traffic", String(args.traffic)] : []),
|
|
46
47
|
...(args.detail !== undefined ? ["--detail", String(args.detail)] : []),
|
|
47
48
|
...(args.noCache ? ["--no-cache"] : []),
|
|
49
|
+
...(args.capabilityView ? ["--capability-view"] : []),
|
|
48
50
|
];
|
|
49
51
|
}
|
|
50
52
|
|
|
@@ -97,10 +99,21 @@ export async function readNested(
|
|
|
97
99
|
contract: number,
|
|
98
100
|
toolchain: Toolchain | undefined = undefined,
|
|
99
101
|
): Promise<NestedRead & { stderr: string }> {
|
|
100
|
-
const
|
|
102
|
+
const command = (toolchain ?? readerToolchain()).command;
|
|
103
|
+
let r = await spawnRead(command, nestedArgv(abs, args, at), abs);
|
|
104
|
+
// A nested chant from before #4378 has no --capability-view: read it
|
|
105
|
+
// without, and its members carry no view.
|
|
106
|
+
if (args.capabilityView && r.exitCode !== 0 && refusedCapabilityView(r.stderr)) {
|
|
107
|
+
r = await spawnRead(command, nestedArgv(abs, { ...args, capabilityView: false }, at), abs);
|
|
108
|
+
}
|
|
101
109
|
return { ...readNestedDocument(r.stdout, r.exitCode, r.stderr, schemaId, contract), stderr: r.stderr };
|
|
102
110
|
}
|
|
103
111
|
|
|
112
|
+
/** Whether a chant refused `--capability-view` as a flag it doesn't know (#4378): one from before it. */
|
|
113
|
+
export function refusedCapabilityView(stderr: string): boolean {
|
|
114
|
+
return /Unknown flag:?\s*--capability-view/i.test(stderr);
|
|
115
|
+
}
|
|
116
|
+
|
|
104
117
|
const prefixed = (outer: string, id: string): string => `${outer}/${id}`;
|
|
105
118
|
|
|
106
119
|
function prefixRefs(value: unknown, outer: string): unknown {
|
|
@@ -141,6 +154,24 @@ export function foldNested(graph: WorkspaceGraph, member: ComposedMember, inner:
|
|
|
141
154
|
for (const e of inner.exports ?? []) graph.exports.push({ ...e, ...(e.node ? { node: prefixed(outer, e.node) } : {}), member: outer });
|
|
142
155
|
for (const i of inner.imports ?? []) graph.imports.push({ ...i, node: prefixed(outer, i.node), member: outer });
|
|
143
156
|
graph.groups.byMember[outer] = ids.sort();
|
|
157
|
+
// The capability view (#4378): each nested member's, under the outer id. A
|
|
158
|
+
// nested member that read without one leaves the outer member without one.
|
|
159
|
+
const composedInner = inner.members.filter((m) => m.status === "composed");
|
|
160
|
+
if (composedInner.some((m) => m.capabilityView !== undefined)) {
|
|
161
|
+
const views = composedInner.map((m) => m.capabilityView);
|
|
162
|
+
if (views.every(isViewDocument)) {
|
|
163
|
+
const ps = views.map((v) => prefixView(v, `${outer}/`));
|
|
164
|
+
member.capabilityView = {
|
|
165
|
+
version: VIEW_DOCUMENT_VERSION,
|
|
166
|
+
lexicons: [...new Set(ps.flatMap((v) => v.lexicons))].sort(),
|
|
167
|
+
nodes: ps.flatMap((v) => v.nodes),
|
|
168
|
+
edges: ps.flatMap((v) => v.edges),
|
|
169
|
+
unresolved: ps.flatMap((v) => v.unresolved),
|
|
170
|
+
};
|
|
171
|
+
} else {
|
|
172
|
+
member.capabilityView = null;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
144
175
|
const groups = graph.groups as unknown as Record<string, Record<string, string[]> | undefined>;
|
|
145
176
|
const innerGroups = inner.groups as unknown as Record<string, Record<string, string[]> | undefined>;
|
|
146
177
|
for (const key of ["byLexicon", "byComposite"] as const) {
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Org scope (#3168): a member of kind repo names another repository's
|
|
3
|
+
* workspace by URL and pinned revision, read read-only through that
|
|
4
|
+
* repository's own read contract; an org workspace holds only such members;
|
|
5
|
+
* `chant workspace check --forge-repos` compares them with the forge's list;
|
|
6
|
+
* and the read contract's identity names the repository a document came
|
|
7
|
+
* from. Every remote here is a local bare repository: nothing reaches a forge.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { execFileSync } from "node:child_process";
|
|
11
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { tmpdir } from "node:os";
|
|
13
|
+
import { dirname, join } from "node:path";
|
|
14
|
+
import { afterAll, describe, expect, test } from "vitest";
|
|
15
|
+
import { runDeclarationChecks } from "./checks";
|
|
16
|
+
import { parseForgeRepos, repoKey, urlCredential } from "./checks/org";
|
|
17
|
+
import { readDeclaration, repoMemberDir } from "./declaration";
|
|
18
|
+
import { workspaceGraph } from "./graph-cli";
|
|
19
|
+
import { listWorkspace } from "./ls";
|
|
20
|
+
import { fetchRepoAt, redactUrl, repoIdentity } from "./repo-ref";
|
|
21
|
+
import { workingTree } from "./tree";
|
|
22
|
+
|
|
23
|
+
const scratch: string[] = [];
|
|
24
|
+
afterAll(() => {
|
|
25
|
+
for (const d of scratch) rmSync(d, { recursive: true, force: true });
|
|
26
|
+
});
|
|
27
|
+
function tmp(prefix = "chant-3168-"): string {
|
|
28
|
+
const d = realpathSync(mkdtempSync(join(tmpdir(), prefix)));
|
|
29
|
+
scratch.push(d);
|
|
30
|
+
return d;
|
|
31
|
+
}
|
|
32
|
+
const git = (cwd: string, ...args: string[]) =>
|
|
33
|
+
execFileSync("git", ["-c", "user.email=t@example.com", "-c", "user.name=t", "-c", "commit.gpgsign=false", ...args], { cwd, encoding: "utf-8" }).trim();
|
|
34
|
+
function write(root: string, files: Record<string, string>): void {
|
|
35
|
+
for (const [path, text] of Object.entries(files)) {
|
|
36
|
+
mkdirSync(dirname(join(root, path)), { recursive: true });
|
|
37
|
+
writeFileSync(join(root, path), text);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** A repository with a workspace, pushed to a local bare remote. Returns the bare URL and the commit. */
|
|
42
|
+
function remoteWorkspace(name: string): { url: string; rev: string } {
|
|
43
|
+
const work = tmp();
|
|
44
|
+
git(work, "init", "-q", "-b", "main");
|
|
45
|
+
write(work, { "chant.workspace.json": JSON.stringify({ name, schema: 1, members: [{ name: "docs", dir: "docs", kind: "other", because: "prose" }] }), "docs/README.md": "" });
|
|
46
|
+
git(work, "add", "-A");
|
|
47
|
+
git(work, "commit", "-q", "-m", "init");
|
|
48
|
+
const bare = join(tmp(), `${name}.git`);
|
|
49
|
+
git(work, "clone", "-q", "--bare", work, bare);
|
|
50
|
+
return { url: bare, rev: git(work, "rev-parse", "HEAD") };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** An org workspace in a git repository of its own, with origin set. */
|
|
54
|
+
function orgWorkspace(members: unknown[], extra: Record<string, unknown> = {}): string {
|
|
55
|
+
const root = tmp();
|
|
56
|
+
git(root, "init", "-q");
|
|
57
|
+
git(root, "remote", "add", "origin", "https://bot:secret@forge.example/acme/org.git");
|
|
58
|
+
write(root, { "chant.workspace.json": JSON.stringify({ name: "acme", schema: 1, scope: "org", members, ...extra }) });
|
|
59
|
+
return root;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const SHA = "0123456789abcdef0123456789abcdef01234567";
|
|
63
|
+
const repoMember = (name: string, url: string, rev = SHA) => ({ name, kind: "repo", repo: { url, rev } });
|
|
64
|
+
|
|
65
|
+
describe("the declaration: repo members and scope", () => {
|
|
66
|
+
test("a repo member has repo and no dir, and reads with a marker dir", () => {
|
|
67
|
+
const root = orgWorkspace([repoMember("chant", "https://github.com/INTENTIUS/chant"), { ...repoMember("ops", "git@github.com:INTENTIUS/ops.git"), repo: { url: "git@github.com:INTENTIUS/ops.git", rev: SHA, workspace: "infra" } }]);
|
|
68
|
+
const d = readDeclaration(workingTree(root));
|
|
69
|
+
expect(d.scope).toBe("org");
|
|
70
|
+
expect(d.members.map((m) => [m.dir, m.repo])).toEqual([
|
|
71
|
+
[repoMemberDir("chant"), { url: "https://github.com/INTENTIUS/chant", rev: SHA, workspace: "." }],
|
|
72
|
+
[repoMemberDir("ops"), { url: "git@github.com:INTENTIUS/ops.git", rev: SHA, workspace: "infra" }],
|
|
73
|
+
]);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("refuses a repo member with a dir, another kind with repo, and a revision that isn't a full commit id", () => {
|
|
77
|
+
const read = (members: unknown[]) => () => readDeclaration(workingTree(orgWorkspace(members)));
|
|
78
|
+
expect(read([{ ...repoMember("a", "x"), dir: "a" }])).toThrow(/a member of kind repo has no dir/);
|
|
79
|
+
expect(read([{ name: "a", dir: "a", kind: "other", because: "x", repo: { url: "x", rev: SHA } }])).toThrow(/only a member of kind repo has repo/);
|
|
80
|
+
expect(read([repoMember("a", "x", "main")])).toThrow(/"main" is not allowed here/);
|
|
81
|
+
expect(read([{ name: "a", kind: "repo" }])).toThrow(/needs "repo"/);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe("repoKey and credentials", () => {
|
|
86
|
+
test("https, ssh and scp-style URLs of one repository compare equal", () => {
|
|
87
|
+
const keys = ["https://github.com/INTENTIUS/Chant.git", "https://github.com/intentius/chant/", "git@github.com:INTENTIUS/chant.git", "ssh://git@github.com/INTENTIUS/chant"].map((u) => repoKey(u));
|
|
88
|
+
expect(new Set(keys)).toEqual(new Set(["github.com/intentius/chant"]));
|
|
89
|
+
expect(repoKey("./x.git", "/base")).toBe("/base/x");
|
|
90
|
+
expect(repoKey("file:///srv/x.git")).toBe("/srv/x");
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test("a password, or a user on https, is a credential; ssh's git user is not", () => {
|
|
94
|
+
expect(urlCredential("https://bot:tok@forge.example/a/b")).toBe(true);
|
|
95
|
+
expect(urlCredential("https://tok@forge.example/a/b")).toBe(true);
|
|
96
|
+
expect(urlCredential("ssh://git@forge.example/a/b")).toBe(false);
|
|
97
|
+
expect(urlCredential("git@forge.example:a/b")).toBe(false);
|
|
98
|
+
expect(redactUrl("https://bot:tok@forge.example/a/b")).toBe("https://forge.example/a/b");
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
describe("parseForgeRepos", () => {
|
|
103
|
+
test("reads an object with repos, a bare array, strings and objects", () => {
|
|
104
|
+
expect(parseForgeRepos(JSON.stringify({ forge: "github", org: "acme", repos: ["https://f/a/x", { url: "https://f/a/y", archived: true }] }), "f.json").repos).toEqual([
|
|
105
|
+
{ url: "https://f/a/x", archived: false },
|
|
106
|
+
{ url: "https://f/a/y", archived: true },
|
|
107
|
+
]);
|
|
108
|
+
expect(parseForgeRepos(JSON.stringify(["https://f/a/x"]), "f.json").repos).toHaveLength(1);
|
|
109
|
+
expect(() => parseForgeRepos("{}", "f.json")).toThrow(/repos array/);
|
|
110
|
+
expect(() => parseForgeRepos("[1]", "f.json")).toThrow(/repos\[0\]/);
|
|
111
|
+
expect(() => parseForgeRepos("nope", "f.json")).toThrow(/not JSON/);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe("chant workspace check on an org workspace", () => {
|
|
116
|
+
const ids = async (root: string, forge?: unknown) =>
|
|
117
|
+
(await runDeclarationChecks(root, (f) => f, forge ? { forgeRepos: parseForgeRepos(JSON.stringify(forge), "forge.json") } : {})).diagnostics
|
|
118
|
+
.filter((d) => /^WSP0(0[1-9]|1[0-6])$/.test(d.ruleId))
|
|
119
|
+
.map((d) => `${d.ruleId}:${d.entity ?? ""}`);
|
|
120
|
+
|
|
121
|
+
test("repo members need no directory: no WSP004, and nothing else fires", async () => {
|
|
122
|
+
expect(await ids(orgWorkspace([repoMember("a", "https://forge.example/acme/a")]))).toEqual([]);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test("WSP013: an org workspace holds only repo members", async () => {
|
|
126
|
+
const root = orgWorkspace([repoMember("a", "https://forge.example/acme/a"), { name: "docs", dir: "docs", kind: "other", because: "x" }]);
|
|
127
|
+
mkdirSync(join(root, "docs"));
|
|
128
|
+
expect(await ids(root)).toContain("WSP013:docs");
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test("WSP014 names a repository the forge has and the declaration lacks; WSP015 one the forge dropped; archived ones need not be declared", async () => {
|
|
132
|
+
const root = orgWorkspace([repoMember("a", "git@forge.example:acme/a.git"), repoMember("gone", "https://forge.example/acme/gone")]);
|
|
133
|
+
const forge = { repos: ["https://forge.example/acme/a", "https://forge.example/acme/new", { url: "https://forge.example/acme/old", archived: true }] };
|
|
134
|
+
const report = await runDeclarationChecks(root, (f) => f, { forgeRepos: parseForgeRepos(JSON.stringify(forge), "forge.json") });
|
|
135
|
+
const found = report.diagnostics.filter((d) => d.ruleId === "WSP014" || d.ruleId === "WSP015").map((d) => `${d.ruleId}: ${d.message}`);
|
|
136
|
+
expect(found).toEqual([
|
|
137
|
+
expect.stringMatching(/^WSP014: the forge lists https:\/\/forge.example\/acme\/new \(forge.json\), and no repo member names it/),
|
|
138
|
+
expect.stringMatching(/^WSP015: member gone names https:\/\/forge.example\/acme\/gone, which the forge no longer lists/),
|
|
139
|
+
]);
|
|
140
|
+
expect(report.ok).toBe(false);
|
|
141
|
+
// Without the list, neither runs: check never asks the forge.
|
|
142
|
+
expect(await ids(root)).toEqual([]);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test("WSP016: a repo url never carries a credential", async () => {
|
|
146
|
+
expect(await ids(orgWorkspace([repoMember("a", "https://bot:tok@forge.example/acme/a")]))).toEqual(["WSP016:a"]);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
describe("the read contract's identity names the repository", () => {
|
|
151
|
+
test("ls prints workspace.repo, redacted, and each repo member's reference", () => {
|
|
152
|
+
const root = orgWorkspace([repoMember("a", "https://forge.example/acme/a")]);
|
|
153
|
+
const doc = listWorkspace({ cwd: root });
|
|
154
|
+
if ("error" in doc) throw new Error(doc.error.message);
|
|
155
|
+
expect(doc.workspace.repo).toBe("https://forge.example/acme/org.git");
|
|
156
|
+
expect(doc.members[0]).toMatchObject({ name: "a", kind: "repo", readable: true, reason: null, repo: { url: "https://forge.example/acme/a", rev: SHA, workspace: "." } });
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test("is null without an origin, or outside git", () => {
|
|
160
|
+
const plain = tmp();
|
|
161
|
+
git(plain, "init", "-q");
|
|
162
|
+
expect(repoIdentity(plain)).toBeNull();
|
|
163
|
+
expect(repoIdentity(tmp())).toBeNull();
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
describe("fetching a repo member's revision into the cache", () => {
|
|
168
|
+
test("fetches the pinned commit from a local bare remote into the user cache, once, and reports a commit it lacks", () => {
|
|
169
|
+
const remote = remoteWorkspace("payments");
|
|
170
|
+
const cache = tmp("chant-3168-cache-");
|
|
171
|
+
const env = { ...process.env, CHANT_CACHE_DIR: cache };
|
|
172
|
+
const first = fetchRepoAt({ url: remote.url, rev: remote.rev, workspace: "." }, "/", env);
|
|
173
|
+
expect(first.ok).toBe(true);
|
|
174
|
+
if (!first.ok) return;
|
|
175
|
+
expect(first.dir.startsWith(join(cache, "repos"))).toBe(true);
|
|
176
|
+
expect(JSON.parse(readFileSync(join(first.dir, "chant.workspace.json"), "utf-8")).name).toBe("payments");
|
|
177
|
+
expect(git(first.dir, "rev-parse", "HEAD")).toBe(remote.rev);
|
|
178
|
+
expect(fetchRepoAt({ url: remote.url, rev: remote.rev, workspace: "." }, "/", env)).toEqual(first);
|
|
179
|
+
const missing = fetchRepoAt({ url: remote.url, rev: SHA, workspace: "." }, "/", env);
|
|
180
|
+
expect(missing).toMatchObject({ ok: false, message: expect.stringContaining(SHA) });
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
describe("chant workspace graph reads a repo member through its own read contract", () => {
|
|
185
|
+
test("runs the other repository's workspace graph at the pinned revision and folds it in, writing nothing in the workspace", async () => {
|
|
186
|
+
const remote = remoteWorkspace("payments");
|
|
187
|
+
const root = orgWorkspace([repoMember("payments", remote.url, remote.rev)]);
|
|
188
|
+
// A stand-in for the other repository's chant: it prints a graph document of the contract, with its argv and identity.
|
|
189
|
+
const bin = join(tmp(), "fake-chant.mjs");
|
|
190
|
+
writeFileSync(
|
|
191
|
+
bin,
|
|
192
|
+
`import { execFileSync } from "node:child_process";
|
|
193
|
+
const argv = process.argv.slice(2);
|
|
194
|
+
const at = argv[argv.indexOf("--at") + 1];
|
|
195
|
+
const repo = execFileSync("git", ["config", "--get", "remote.origin.url"], { encoding: "utf-8" }).trim();
|
|
196
|
+
const member = { name: "docs", dir: "docs", kind: "other", status: "composed", reason: null, chant: "9.9.9", irVersion: 1, live: false };
|
|
197
|
+
console.log(JSON.stringify({ $schema: "https://intentius.io/chant/schemas/workspace/graph/v1/graph.schema.json", contract: 1, chant: "9.9.9", at, version: 1,
|
|
198
|
+
workspace: { name: "payments", root: ".", repo }, members: [member],
|
|
199
|
+
nodes: [{ id: "docs/Page", kind: "Page", lexicon: "x", attrs: {}, member: "docs" }], edges: [], groups: { byMember: { docs: ["docs/Page"] } },
|
|
200
|
+
exports: [], imports: [], links: [], collectors: [], records: [] }));
|
|
201
|
+
`,
|
|
202
|
+
);
|
|
203
|
+
const cache = tmp("chant-3168-cache-");
|
|
204
|
+
const before = process.env.CHANT_CACHE_DIR;
|
|
205
|
+
process.env.CHANT_CACHE_DIR = cache;
|
|
206
|
+
try {
|
|
207
|
+
const { doc } = await workspaceGraph({ cwd: root, reader: { command: [process.execPath, bin], identity: bin, source: "path" } as never });
|
|
208
|
+
if ("error" in doc) throw new Error(doc.error.message);
|
|
209
|
+
expect(doc.workspace).toMatchObject({ name: "acme", repo: "https://forge.example/acme/org.git" });
|
|
210
|
+
const m = doc.members.find((x) => x.name === "payments")!;
|
|
211
|
+
expect(m).toMatchObject({ kind: "repo", status: "composed", repo: { url: remote.url, rev: remote.rev, workspace: ".", read: remote.url } });
|
|
212
|
+
expect(m.nested?.name).toBe("payments");
|
|
213
|
+
expect(m.nested?.members.map((x) => x.name)).toEqual(["docs"]);
|
|
214
|
+
expect(doc.nodes.map((n) => n.id)).toEqual(["payments/docs/Page"]);
|
|
215
|
+
expect(existsSync(join(root, "@repo"))).toBe(false);
|
|
216
|
+
expect(git(root, "status", "--porcelain")).toBe("?? chant.workspace.json");
|
|
217
|
+
} finally {
|
|
218
|
+
if (before === undefined) delete process.env.CHANT_CACHE_DIR;
|
|
219
|
+
else process.env.CHANT_CACHE_DIR = before;
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
test("a revision the remote lacks fails the member with command-failed", async () => {
|
|
224
|
+
const remote = remoteWorkspace("payments");
|
|
225
|
+
const root = orgWorkspace([repoMember("payments", remote.url, SHA)]);
|
|
226
|
+
const before = process.env.CHANT_CACHE_DIR;
|
|
227
|
+
process.env.CHANT_CACHE_DIR = tmp("chant-3168-cache-");
|
|
228
|
+
try {
|
|
229
|
+
const { doc, failed } = await workspaceGraph({ cwd: root, reader: { command: ["false"], identity: "false", source: "path" } as never });
|
|
230
|
+
if ("error" in doc) throw new Error(doc.error.message);
|
|
231
|
+
expect(failed).toBe(true);
|
|
232
|
+
expect(doc.members[0]).toMatchObject({ status: "failed", reason: { code: "command-failed", message: expect.stringContaining(SHA) } });
|
|
233
|
+
} finally {
|
|
234
|
+
if (before === undefined) delete process.env.CHANT_CACHE_DIR;
|
|
235
|
+
else process.env.CHANT_CACHE_DIR = before;
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
});
|
|
@@ -11,7 +11,7 @@ import { describe, expect, test } from "vitest";
|
|
|
11
11
|
import { REPO } from "./__fixtures__/contract-repo";
|
|
12
12
|
import { CHANGES_ERROR_CODES, CHANGES_FINDING_CODES, COMMIT_LINK_FINDING_CODES } from "./changes";
|
|
13
13
|
import { MEMBER_RUN_REASON_CODES } from "./compose-graph";
|
|
14
|
-
import { COMPOSITES_ENVIRONMENT_REASON_CODES, COMPOSITES_ERROR_CODES, COMPOSITES_REASON_CODES, COMPOSITES_RUNTIME_REASON_CODES } from "./composites";
|
|
14
|
+
import { COMPOSITES_ENVIRONMENT_REASON_CODES, COMPOSITES_ERROR_CODES, COMPOSITES_EXECUTOR_REASON_CODES, COMPOSITES_REASON_CODES, COMPOSITES_RUNTIME_REASON_CODES } from "./composites";
|
|
15
15
|
import { WORKSPACE_ERROR_CODES } from "./declaration";
|
|
16
16
|
import { GRAPH_ERROR_CODES } from "./graph-cli";
|
|
17
17
|
import { INTENT_ERROR_CODES, INTENT_FINDING_CODES, INTENT_REASON_CODES, INTENT_WHY_CODES } from "./intent";
|
|
@@ -30,9 +30,11 @@ import { BOX_FINDING_CODES } from "./checks/boxes";
|
|
|
30
30
|
import { DIAGRAM_FINDING_CODES } from "./checks/diagrams";
|
|
31
31
|
import { SECURITY_FINDING_CODES } from "./checks/security";
|
|
32
32
|
import { CI_WORKFLOW_FINDING_CODES } from "./ci-workflow";
|
|
33
|
+
import { CI_BRANCH_FINDING_CODES } from "./checks/ci-branch";
|
|
33
34
|
import { WORK_ERROR_CODES, WORK_HISTORY_ERROR_CODES, WORK_LEASE_REFUSALS } from "./work-cli";
|
|
34
35
|
import { RUN_STATEMENT_ERROR_CODES, RUNS_ERROR_CODES, RUNS_REASON_CODES, RUNS_WRITE_ERROR_CODES } from "./runs-cli";
|
|
35
36
|
import { RUN_STATEMENT_FAILURE_CODES } from "./trust/run-statement";
|
|
37
|
+
import { LEDGER_READ_ERROR_CODES } from "../lifecycle/ledger-read";
|
|
36
38
|
import { WORK_EVIDENCE_ERROR_CODES } from "./work-evidence";
|
|
37
39
|
import { RECORD_FINDING_CODES } from "./checks/records";
|
|
38
40
|
import { ANSWER_WARNING_CODES } from "./points";
|
|
@@ -55,6 +57,8 @@ import { ROTATION_REFUSAL_CODES } from "./trust/rotation";
|
|
|
55
57
|
import { SIGNERS_ERROR_CODES } from "./trust/signers-cli";
|
|
56
58
|
import { EVIDENCE_ERROR_CODES } from "./trust/evidence";
|
|
57
59
|
import { METRICS_ERROR_CODES, METRICS_REASON_CODES } from "./delivery-metrics";
|
|
60
|
+
import { SEARCH_ERROR_CODES, SEARCH_MEMBER_REASON_CODES, WORKSPACE_SEARCH_ERROR_CODES } from "./search-contract";
|
|
61
|
+
import { CAPABILITIES_ERROR_CODES, CAPABILITY_SUPPORT_CODES } from "./capabilities-contract";
|
|
58
62
|
|
|
59
63
|
const HERE = import.meta.dirname;
|
|
60
64
|
|
|
@@ -70,6 +74,7 @@ const PER_COMMAND: Record<string, readonly string[]> = {
|
|
|
70
74
|
DIAGRAM_FINDING_CODES,
|
|
71
75
|
SECURITY_FINDING_CODES,
|
|
72
76
|
CI_WORKFLOW_FINDING_CODES,
|
|
77
|
+
CI_BRANCH_FINDING_CODES,
|
|
73
78
|
STATUS_REASON_CODES,
|
|
74
79
|
STATUS_ERROR_CODES,
|
|
75
80
|
STATUS_GATE_REASON_CODES,
|
|
@@ -98,6 +103,7 @@ const PER_COMMAND: Record<string, readonly string[]> = {
|
|
|
98
103
|
COMPOSITES_REASON_CODES,
|
|
99
104
|
COMPOSITES_RUNTIME_REASON_CODES,
|
|
100
105
|
COMPOSITES_ENVIRONMENT_REASON_CODES,
|
|
106
|
+
COMPOSITES_EXECUTOR_REASON_CODES,
|
|
101
107
|
WORK_ERROR_CODES,
|
|
102
108
|
WORK_HISTORY_ERROR_CODES,
|
|
103
109
|
WORK_LEASE_REFUSALS,
|
|
@@ -106,6 +112,7 @@ const PER_COMMAND: Record<string, readonly string[]> = {
|
|
|
106
112
|
RUNS_WRITE_ERROR_CODES,
|
|
107
113
|
RUN_STATEMENT_ERROR_CODES,
|
|
108
114
|
RUN_STATEMENT_FAILURE_CODES,
|
|
115
|
+
LEDGER_READ_ERROR_CODES,
|
|
109
116
|
WORK_EVIDENCE_ERROR_CODES,
|
|
110
117
|
RECORD_FINDING_CODES,
|
|
111
118
|
FLAG_WARNING_CODES,
|
|
@@ -132,6 +139,11 @@ const PER_COMMAND: Record<string, readonly string[]> = {
|
|
|
132
139
|
EVIDENCE_ERROR_CODES,
|
|
133
140
|
METRICS_ERROR_CODES,
|
|
134
141
|
METRICS_REASON_CODES,
|
|
142
|
+
SEARCH_ERROR_CODES,
|
|
143
|
+
WORKSPACE_SEARCH_ERROR_CODES,
|
|
144
|
+
SEARCH_MEMBER_REASON_CODES,
|
|
145
|
+
CAPABILITIES_ERROR_CODES,
|
|
146
|
+
CAPABILITY_SUPPORT_CODES,
|
|
135
147
|
};
|
|
136
148
|
|
|
137
149
|
/** Every string in an `enum` under a property named `code`, anywhere in a schema. */
|
|
@@ -51,9 +51,24 @@ export const REASONS = {
|
|
|
51
51
|
"command-failed": "The member's own command exited with a failure, or the lexicon that reads the member through its kind's graph block isn't installed where the workspace resolves its pin.",
|
|
52
52
|
"output-unreadable": "The member's command printed something that isn't the document asked for.",
|
|
53
53
|
"ir-version-unsupported": "The member's IR has a version this chant can't read.",
|
|
54
|
+
// search and workspace search (#4374): why no answer was printed, and why a member has none.
|
|
55
|
+
"query-invalid": "search was given no query, a term its grammar can't parse, or a --count-by that is not a grouping.",
|
|
56
|
+
"usage-invalid": "search was given a flag that needs another one it lacks, or two that don't go together, such as --check-live without --snapshot.",
|
|
57
|
+
"environment-unknown": "--env names an environment the project's chant config does not declare.",
|
|
58
|
+
"snapshot-unavailable": "--snapshot names a snapshot chant can't replay: none is recorded for the environment, or the ref is one replay does not take.",
|
|
59
|
+
"build-failed": "The project's build, or one of its build roots, failed, so the graph search would answer over is incomplete.",
|
|
60
|
+
"snapshot-at-revision": "workspace search was given --snapshot and --at: a snapshot replays the estate as recorded over the source in the working tree, not at a revision.",
|
|
61
|
+
"member-chant-too-old": "The member's chant predates the document asked for: it has no such command, or prints it without the read contract.",
|
|
62
|
+
// the capabilities catalog (#4375): why a lexicon can't supply a capability.
|
|
63
|
+
"lexicon-has-no-mapping": "The lexicon ships no capability mapping, so no capability rule can read its resources.",
|
|
64
|
+
"capability-not-derivable": "The lexicon's capability mapping labels none of the kinds the capability's rule needs.",
|
|
65
|
+
"lexicon-not-loaded": "The lexicon isn't installed where the chant that wrote the catalog runs, so its mapping wasn't read.",
|
|
54
66
|
// A ledger status can't fully read.
|
|
55
67
|
"ledger-unreadable": "Reading the ledger failed, so nothing from it is listed.",
|
|
56
68
|
"ledger-malformed": "Some lines of the ledger aren't release records; the rest are listed.",
|
|
69
|
+
// chant ledger (#4363): a read that can't start.
|
|
70
|
+
"filter-invalid": "A --where or --since names a field the read doesn't have, an operator its type doesn't take, or a value not of its type; nothing was read.",
|
|
71
|
+
"table-unknown": "chant ledger was given a table that is not one of resources, snapshots, runs, gates, deploys, releases or cuts.",
|
|
57
72
|
// A member's gates status can't list (status, #2674).
|
|
58
73
|
"gates-no-ledger": "The checkout has no chant/lifecycle branch, so there is no gate ledger to read.",
|
|
59
74
|
"gates-no-gate-ledger": "The branch has no gate ledger for the member: no run of it has reached a gate.",
|
|
@@ -225,6 +240,9 @@ export const REASONS = {
|
|
|
225
240
|
"environments-ledger-undeclared": "The member's ledger has releases in an environment its config's environments don't cover, so chant run --env would refuse it and it is not listed.",
|
|
226
241
|
"environments-ledger-unreadable": "The chant/lifecycle branch exists and the member's ledger environments could not be listed.",
|
|
227
242
|
"environments-component-undeclared": "A component declares an environment its member's chant.config.ts environments don't cover, so chant run --env would refuse it and it is not listed (#3153).",
|
|
243
|
+
// The forge workflow that deploys an environment (graph --composites, #4402): an environment row's executor.reason.
|
|
244
|
+
"executor-none-declared": "The member's chant.config.ts declares no executor for the environment, so nothing names the forge workflow that deploys it.",
|
|
245
|
+
"executor-config-unreadable": "The member's chant.config.ts could not be read, so whether a forge workflow deploys the environment is unknown.",
|
|
228
246
|
// A declared diagram's source or render (check, #2764). Each is also a WSP finding.
|
|
229
247
|
"diagram-source-missing": "A declared diagram's source file does not exist in the tree read.",
|
|
230
248
|
"diagram-render-missing": "A declared diagram's render file does not exist in the tree read.",
|
|
@@ -257,6 +275,7 @@ export const REASONS = {
|
|
|
257
275
|
"ci-workflow-pipeline-missing": "Under ci.workflow, no pipeline file runs the plan job, the merge job or chant ci tick.",
|
|
258
276
|
"ci-workflow-pipeline-differs": "Under ci.workflow, the pipeline does not match the workflow: it applies on merge under trunk-curated, records under trunk-curated+apply-on-merge, or applies before merge, or fails to, against apply-before-merge.",
|
|
259
277
|
"ci-workflow-publish-missing": "Under ci.workflow, no pipeline file runs chant release publish.",
|
|
278
|
+
"ci-branch-route-differs": "A member's generated pull-request pipeline targets a branch other than the one ci.branches routes the member to.",
|
|
260
279
|
// A box that holds a credential (check, #2726). Each is also a WSP finding.
|
|
261
280
|
"box-credential-declared": "A file in a box member's directory carries a literal secret: a credential's shape, or a literal where a credential goes. A variable or secret-manager reference is not one.",
|
|
262
281
|
"box-capability-unbrokered": "A capability in a member's box block names no broker, so the box would hold its credential.",
|
|
@@ -279,6 +298,10 @@ export const REASONS = {
|
|
|
279
298
|
"lease-held": "Someone holds a live lease on the work item: another worker, or, for a claim, the same one.",
|
|
280
299
|
"lease-not-held": "Nobody holds a live lease on the work item: it expired, was released or was never claimed.",
|
|
281
300
|
"lease-token-mismatch": "The live lease on the work item carries another fencing token than the one given.",
|
|
301
|
+
// Evidence that cites an ops result (work evidence, #3171): why the citation was refused. Nothing is written.
|
|
302
|
+
"work-evidence-ops-missing": "Work evidence cites a run, deploy, gate answer or release plan the local chant/lifecycle branch does not hold.",
|
|
303
|
+
"work-evidence-ops-mismatch": "Work evidence cites an ops record that does not hash to the sha256 given, or a run whose outcome disagrees with the evidence's result.",
|
|
304
|
+
"work-evidence-ops-unfinished": "Work evidence cites a run that is still gated or waiting, so it has no outcome to show.",
|
|
282
305
|
"lease-race": "Another writer changed the lease between this command's read and its write.",
|
|
283
306
|
"lease-push-rejected": "The remote refused the lease push: another clone claimed the item first, or the remote could not be reached.",
|
|
284
307
|
// The agent run record (chant workspace runs, #3033): why a write was refused, and what a read could not see. Nothing is written on a refusal.
|
|
@@ -56,6 +56,7 @@ import {
|
|
|
56
56
|
} from "./records";
|
|
57
57
|
import { readCheckoutHead, worktreeStates, type CheckoutView, type WorktreeState } from "./records-checkout";
|
|
58
58
|
import { lastWriteReader, type LastWrite } from "./write-lock";
|
|
59
|
+
import { FilterError, matchesWhere, parseWhere, type FilterFields, type WhereClause } from "../read-filter";
|
|
59
60
|
|
|
60
61
|
function readTextOrNull(file: string): string | null {
|
|
61
62
|
try {
|
|
@@ -78,7 +79,7 @@ export const RECORDS_CONTRACT_VERSION = 1;
|
|
|
78
79
|
export const RECORDS_OUTPUT_SCHEMA_ID = "https://intentius.io/chant/schemas/workspace/records/v1/records.schema.json";
|
|
79
80
|
|
|
80
81
|
const USAGE =
|
|
81
|
-
"chant workspace records [--kind <kind file>] [--current] [--uncommitted | --at <rev>] [--base <rev>] [--require attested] [--json] | chant workspace records [--kind <kind file>] --since <rev|session id> [--at <rev>] [--json] | chant workspace records pin <path> [--kind <kind file>] | chant workspace records new|amend|review|close (#2670, #2693)";
|
|
82
|
+
"chant workspace records [--kind <kind file>] [--current] [--uncommitted | --at <rev>] [--base <rev>] [--require attested] [--where <field><op><value>]... [--json] | chant workspace records [--kind <kind file>] --since <rev|session id> [--at <rev>] [--json] | chant workspace records pin <path> [--kind <kind file>] | chant workspace records new|amend|review|close (#2670, #2693)";
|
|
82
83
|
|
|
83
84
|
/** Exit code when the read worked and a record falls below `--require`. */
|
|
84
85
|
export const EXIT_BELOW_REQUIRED = 2;
|
|
@@ -196,6 +197,8 @@ export type RecordsDocument =
|
|
|
196
197
|
summary: { total: number; valid: number; invalid: number; superseded: number };
|
|
197
198
|
/** For a work kind (#2683): each decision its decision kind reads, with the work records implementing it. */
|
|
198
199
|
decisions?: DecisionWork[];
|
|
200
|
+
/** The `--where` clauses the records were filtered with (#4363); absent without one. `summary` then counts the records listed. */
|
|
201
|
+
where?: string[];
|
|
199
202
|
}
|
|
200
203
|
| { $schema: string; contract: number; error: { code: ReadErrorCode; message: string } };
|
|
201
204
|
|
|
@@ -697,7 +700,12 @@ export async function runWorkspaceRecords(ctx: CommandContext): Promise<number>
|
|
|
697
700
|
console.error(formatError({ message: pairing, hint: USAGE }));
|
|
698
701
|
return 1;
|
|
699
702
|
}
|
|
700
|
-
|
|
703
|
+
const filter = recordsWhere(args);
|
|
704
|
+
if ("error" in filter) {
|
|
705
|
+
console.error(formatError({ message: filter.error, hint: USAGE }));
|
|
706
|
+
return 1;
|
|
707
|
+
}
|
|
708
|
+
if (!args.kind) return runDeclaredRecords(args, filter.clauses);
|
|
701
709
|
if (args.require !== undefined && args.require !== "attested") {
|
|
702
710
|
console.error(formatError({ message: `--require takes one level, attested, not ${JSON.stringify(args.require)}`, hint: USAGE }));
|
|
703
711
|
return 1;
|
|
@@ -715,7 +723,7 @@ export async function runWorkspaceRecords(ctx: CommandContext): Promise<number>
|
|
|
715
723
|
else console.log(formatSince(since));
|
|
716
724
|
return "error" in since ? 1 : 0;
|
|
717
725
|
}
|
|
718
|
-
const doc = await queryRecords({ kind: args.kind, current: args.current, uncommitted: args.uncommitted, at: args.at, base: args.base, cwd: process.cwd(), fetchLedger: true });
|
|
726
|
+
const doc = filterRecordsDocument(await queryRecords({ kind: args.kind, current: args.current, uncommitted: args.uncommitted, at: args.at, base: args.base, cwd: process.cwd(), fetchLedger: true }), filter.clauses, args.where ?? []);
|
|
719
727
|
if (args.json) {
|
|
720
728
|
console.log(JSON.stringify(doc, null, 2));
|
|
721
729
|
} else if ("error" in doc) {
|
|
@@ -756,7 +764,7 @@ export async function runWorkspaceRecords(ctx: CommandContext): Promise<number>
|
|
|
756
764
|
* declaration-level code the schema doesn't carry (`declaration-invalid` and
|
|
757
765
|
* the rest of `WorkspaceErrorCode`) still prints text on stderr only.
|
|
758
766
|
*/
|
|
759
|
-
async function runDeclaredRecords(args: CommandContext["args"]): Promise<number> {
|
|
767
|
+
async function runDeclaredRecords(args: CommandContext["args"], clauses: readonly WhereClause[] = []): Promise<number> {
|
|
760
768
|
if (args.require !== undefined && args.require !== "attested") {
|
|
761
769
|
console.error(formatError({ message: `--require takes one level, attested, not ${JSON.stringify(args.require)}`, hint: USAGE }));
|
|
762
770
|
return 1;
|
|
@@ -779,7 +787,9 @@ async function runDeclaredRecords(args: CommandContext["args"]): Promise<number>
|
|
|
779
787
|
return 1;
|
|
780
788
|
}
|
|
781
789
|
if (args.since !== undefined) return runDeclaredSince(declared, args);
|
|
782
|
-
const
|
|
790
|
+
const read = await queryDeclaredRecords(declared, { current: args.current, uncommitted: args.uncommitted, at: args.at, base: args.base, cwd: process.cwd(), fetchLedger: true });
|
|
791
|
+
// The spec stays the whole current spec; --where narrows only the records each kind lists.
|
|
792
|
+
const set = { ...read, kinds: read.kinds.map((k) => filterRecordsDocument(k, clauses, args.where ?? [])) };
|
|
783
793
|
if (args.json) console.log(JSON.stringify(set, null, 2));
|
|
784
794
|
for (const doc of args.json ? [] : set.kinds) {
|
|
785
795
|
if ("error" in doc) {
|
|
@@ -854,6 +864,49 @@ export function belowRequired(records: RecordView[], required: ProvenanceLevel):
|
|
|
854
864
|
}
|
|
855
865
|
|
|
856
866
|
/** Why `--uncommitted` can't be given with the other flags given, or undefined when it can (#3160). */
|
|
867
|
+
/**
|
|
868
|
+
* The fields `records --where` filters on (#4363). `data` is the record's
|
|
869
|
+
* own fields, so `data.<key>` names any of them.
|
|
870
|
+
*/
|
|
871
|
+
export const RECORD_FILTER_FIELDS: FilterFields = {
|
|
872
|
+
id: "text",
|
|
873
|
+
path: "text",
|
|
874
|
+
state: "text",
|
|
875
|
+
valid: "boolean",
|
|
876
|
+
supersededBy: "text",
|
|
877
|
+
digest: "text",
|
|
878
|
+
ready: "boolean",
|
|
879
|
+
attested: "boolean",
|
|
880
|
+
worktree: "text",
|
|
881
|
+
ledger: "text",
|
|
882
|
+
"provenance.level": "text",
|
|
883
|
+
data: "json",
|
|
884
|
+
};
|
|
885
|
+
|
|
886
|
+
/** Keep the records every clause matches, counting `summary` over the records listed. A failure is left as it is. */
|
|
887
|
+
export function filterRecordsDocument<D extends RecordsDocument>(doc: D, clauses: readonly WhereClause[], where: readonly string[]): D {
|
|
888
|
+
if (where.length === 0 || "error" in doc) return doc;
|
|
889
|
+
const records = doc.records.filter((r) => matchesWhere(r, clauses));
|
|
890
|
+
return {
|
|
891
|
+
...doc,
|
|
892
|
+
records,
|
|
893
|
+
summary: { ...doc.summary, total: records.length, valid: records.filter((r) => r.valid).length, invalid: records.filter((r) => !r.valid).length },
|
|
894
|
+
where: [...where],
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
/** The `--where` clauses, or a message for a person. */
|
|
899
|
+
function recordsWhere(args: CommandContext["args"]): { clauses: WhereClause[] } | { error: string } {
|
|
900
|
+
const where = args.where ?? [];
|
|
901
|
+
if (where.length > 0 && args.since !== undefined) return { error: "--where filters a records read and takes no --since: --since compares two revisions" };
|
|
902
|
+
try {
|
|
903
|
+
return { clauses: parseWhere(where, RECORD_FILTER_FIELDS) };
|
|
904
|
+
} catch (err) {
|
|
905
|
+
if (err instanceof FilterError) return { error: err.message };
|
|
906
|
+
throw err;
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
|
|
857
910
|
function uncommittedPairing(args: CommandContext["args"]): string | undefined {
|
|
858
911
|
if (!args.uncommitted) return undefined;
|
|
859
912
|
if (args.at !== undefined) return "--uncommitted reads the working tree against HEAD, and takes no --at";
|
|
@@ -152,6 +152,11 @@
|
|
|
152
152
|
"description": "Added in contract 1 by #2683, for a work kind only. Every decision the kind file named in the work kind's work.decisions reads at the same revision, whether or not a work record names it, each with the work records implementing it. A decision with an empty implementedBy has no work item yet.",
|
|
153
153
|
"type": "array",
|
|
154
154
|
"items": { "$ref": "#/$defs/decisionWork" }
|
|
155
|
+
},
|
|
156
|
+
"where": {
|
|
157
|
+
"description": "Added in contract 1 by #4363. Each --where clause, <field><op><value>, as given; every one held for each record listed, and summary's total, valid and invalid count the records listed. Absent without --where.",
|
|
158
|
+
"type": "array",
|
|
159
|
+
"items": { "type": "string" }
|
|
155
160
|
}
|
|
156
161
|
},
|
|
157
162
|
"allOf": [
|
|
@@ -39,7 +39,7 @@ import { latestPerComponent, readReleaseLedger } from "../lifecycle/release-ledg
|
|
|
39
39
|
import { readAllReleases, readCuts } from "../lifecycle/release-store";
|
|
40
40
|
import { resolveMemberLedger } from "../lifecycle/member-ledger";
|
|
41
41
|
import { readBlobFromPath } from "../lifecycle/git";
|
|
42
|
-
import { readerVersion } from "./declaration";
|
|
42
|
+
import { greenBranches, readerVersion } from "./declaration";
|
|
43
43
|
|
|
44
44
|
export const RELEASE_CANDIDATES_CONTRACT_VERSION = 1;
|
|
45
45
|
export const RELEASE_CANDIDATES_SCHEMA_ID = "https://intentius.io/chant/schemas/workspace/release-candidates/v1/release-candidates.schema.json";
|
|
@@ -145,6 +145,8 @@ export interface ReleaseCandidatesQuery {
|
|
|
145
145
|
/** Only this environment's view: the walk stops at what it runs, and `newFor` names only it. */
|
|
146
146
|
env?: string;
|
|
147
147
|
limit?: number;
|
|
148
|
+
/** Walk this branch of `ci.green.branch` (#4325) instead of the first. */
|
|
149
|
+
branch?: string;
|
|
148
150
|
}
|
|
149
151
|
|
|
150
152
|
function git(top: string, args: string[]): string {
|
|
@@ -218,7 +220,10 @@ export async function releaseCandidatesDocument(query: ReleaseCandidatesQuery):
|
|
|
218
220
|
const { commitDetails } = await import("./intent");
|
|
219
221
|
const source = scopeSource(cwd);
|
|
220
222
|
const green = source.declaration?.ci?.green ?? null;
|
|
221
|
-
|
|
223
|
+
if (query.branch !== undefined && !(green && greenBranches(green).includes(query.branch))) {
|
|
224
|
+
throw new Error(`--branch ${query.branch} is not a branch ci.green judges${green ? ` (${greenBranches(green).join(", ")})` : ", and the declaration has no ci.green"}`);
|
|
225
|
+
}
|
|
226
|
+
const trunk = resolveTrunk(top, query.branch ?? green?.branch ?? null);
|
|
222
227
|
const tip =
|
|
223
228
|
tryGit(top, ["rev-parse", "--verify", "--quiet", `refs/remotes/${trunk.remote}/${trunk.branch}^{commit}`]) ??
|
|
224
229
|
tryGit(top, ["rev-parse", "--verify", "--quiet", `refs/heads/${trunk.branch}^{commit}`]);
|