@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
|
@@ -24,13 +24,14 @@
|
|
|
24
24
|
* (`changes-cli.ts`, #2773), which prints a document of its own.
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
|
-
import { realpathSync } from "node:fs";
|
|
27
|
+
import { readFileSync, realpathSync } from "node:fs";
|
|
28
28
|
import { join, relative, resolve, sep } from "node:path";
|
|
29
29
|
import { formatError, formatSuccess } from "../cli/format";
|
|
30
30
|
import type { CommandContext } from "../cli/registry";
|
|
31
31
|
import type { LintDiagnostic, LintRule } from "../lint/rule";
|
|
32
32
|
import { findWorkspaceRoot } from "../project-root";
|
|
33
33
|
import type { DeclarationCheckReport } from "./checks";
|
|
34
|
+
import type { ForgeRepoList } from "./checks/org";
|
|
34
35
|
import type { RecordFacts } from "./checks/records";
|
|
35
36
|
import { LOCK_FILE, LockError, parseLock, readLock } from "./lineage-lock";
|
|
36
37
|
import type { ReasonCode } from "./reason-codes";
|
|
@@ -91,7 +92,7 @@ export function findingKey(f: CheckFinding): string {
|
|
|
91
92
|
}
|
|
92
93
|
|
|
93
94
|
const USAGE =
|
|
94
|
-
"chant workspace check [--at <rev>] [--json] [--format stylish|json|sarif] [--generated] [--kind <kind file>] [--live --env <env>]\n chant workspace check --changes <base>..<head> [--work <id>] [--severity off|warn|fail] [--kind <kind file>...] [--json]";
|
|
95
|
+
"chant workspace check [--at <rev>] [--json] [--format stylish|json|sarif] [--generated] [--kind <kind file>] [--live --env <env>] [--forge-repos <file>]\n chant workspace check --changes <base>..<head> [--work <id>] [--severity off|warn|fail] [--kind <kind file>...] [--json]";
|
|
95
96
|
const FORMATS = ["stylish", "json", "sarif"] as const;
|
|
96
97
|
|
|
97
98
|
/** A lock finding as a lint diagnostic, for `--format json` and `--format sarif`. */
|
|
@@ -141,7 +142,7 @@ export type CheckDocument =
|
|
|
141
142
|
chant: string;
|
|
142
143
|
at: string | null;
|
|
143
144
|
/** The declaration's workspace, or null when there is none; `name` is null when it can't be read. */
|
|
144
|
-
workspace: { name: string | null; root: string } | null;
|
|
145
|
+
workspace: { name: string | null; root: string; repo: string | null } | null;
|
|
145
146
|
declaration?: DeclarationCheckReport;
|
|
146
147
|
})
|
|
147
148
|
| { $schema: string; contract: number; chant: string; error: { code: CheckErrorCode; message: string; location: null } };
|
|
@@ -152,7 +153,11 @@ export type CheckDocument =
|
|
|
152
153
|
* to `cwd`. `runGenerators` is `--generated`; with `at` it does nothing,
|
|
153
154
|
* since the member facts describe the working tree, not the revision.
|
|
154
155
|
*/
|
|
155
|
-
export async function runChecks(
|
|
156
|
+
export async function runChecks(
|
|
157
|
+
cwd: string,
|
|
158
|
+
at?: string,
|
|
159
|
+
options: { runGenerators?: boolean; kind?: string; live?: { env: string; onStderr?: (text: string) => void }; forgeRepos?: ForgeRepoList } = {},
|
|
160
|
+
): Promise<CheckDocument> {
|
|
156
161
|
// Loaded here, not at the top: `workspace upgrade` imports this module for checkLineage alone.
|
|
157
162
|
const [{ findDeclarationDir, readDeclaration, readerVersion }, { gitTop, gitTree, resolveCommit, workingTree }] = await Promise.all([
|
|
158
163
|
import("./declaration"),
|
|
@@ -190,7 +195,7 @@ export async function runChecks(cwd: string, at?: string, options: { runGenerato
|
|
|
190
195
|
}
|
|
191
196
|
|
|
192
197
|
let declaration: DeclarationCheckReport | undefined;
|
|
193
|
-
let workspace: { name: string | null; root: string } | null = null;
|
|
198
|
+
let workspace: { name: string | null; root: string; repo: string | null } | null = null;
|
|
194
199
|
if (found) {
|
|
195
200
|
const { runDeclarationChecks } = await import("./checks");
|
|
196
201
|
const { dir, tree } = found;
|
|
@@ -200,6 +205,7 @@ export async function runChecks(cwd: string, at?: string, options: { runGenerato
|
|
|
200
205
|
...(commit !== null ? { tree } : {}),
|
|
201
206
|
...(records ? { records } : {}),
|
|
202
207
|
...(options.live ? { live: options.live } : {}),
|
|
208
|
+
...(options.forgeRepos ? { forgeRepos: options.forgeRepos } : {}),
|
|
203
209
|
});
|
|
204
210
|
let name: string | null = null;
|
|
205
211
|
try {
|
|
@@ -207,7 +213,8 @@ export async function runChecks(cwd: string, at?: string, options: { runGenerato
|
|
|
207
213
|
} catch {
|
|
208
214
|
// The WSP001 finding already says why.
|
|
209
215
|
}
|
|
210
|
-
|
|
216
|
+
const { repoIdentity } = await import("./repo-ref");
|
|
217
|
+
workspace = { name, root: found.root, repo: repoIdentity(dir) };
|
|
211
218
|
}
|
|
212
219
|
const ok = report.ok && (declaration?.ok ?? true);
|
|
213
220
|
return { ...head, at: commit, workspace, ...report, ok, ...(declaration ? { declaration } : {}) };
|
|
@@ -267,7 +274,23 @@ export async function runWorkspaceCheck(ctx: CommandContext): Promise<number> {
|
|
|
267
274
|
const handed = await handToRootChant(root, ctx.args.at);
|
|
268
275
|
if (handed !== undefined) return handed;
|
|
269
276
|
}
|
|
270
|
-
|
|
277
|
+
// The forge's repository list (#3168) is input a warden writes; chant never asks the forge itself.
|
|
278
|
+
let forgeRepos: ForgeRepoList | undefined;
|
|
279
|
+
if (ctx.args.forgeRepos !== undefined) {
|
|
280
|
+
const { parseForgeRepos } = await import("./checks/org");
|
|
281
|
+
try {
|
|
282
|
+
forgeRepos = parseForgeRepos(readFileSync(resolve(ctx.args.forgeRepos), "utf-8"), ctx.args.forgeRepos);
|
|
283
|
+
} catch (err) {
|
|
284
|
+
console.error(formatError({ message: `--forge-repos: ${(err as Error).message}`, hint: USAGE }));
|
|
285
|
+
return 1;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
const doc = await runChecks(root, ctx.args.at, {
|
|
289
|
+
runGenerators: ctx.args.generated === true,
|
|
290
|
+
...(ctx.args.kind !== undefined ? { kind: ctx.args.kind } : {}),
|
|
291
|
+
...(ctx.args.live && ctx.args.env ? { live: { env: ctx.args.env, onStderr: (text: string) => process.stderr.write(text) } } : {}),
|
|
292
|
+
...(forgeRepos ? { forgeRepos } : {}),
|
|
293
|
+
});
|
|
271
294
|
if ("error" in doc) {
|
|
272
295
|
if (ctx.args.json || format === "json") console.log(JSON.stringify(doc, null, 2));
|
|
273
296
|
else console.error(formatError({ message: `${doc.error.code}: ${doc.error.message}`, hint: USAGE }));
|
package/src/workspace/links.ts
CHANGED
|
@@ -195,10 +195,11 @@ function nearNames(name: string, outputs: JoinHandle[]): string[] {
|
|
|
195
195
|
*/
|
|
196
196
|
export function resolveLinks(
|
|
197
197
|
declaration: Declaration,
|
|
198
|
-
|
|
198
|
+
sourceHandles: ReadonlyMap<string, MemberHandles>,
|
|
199
199
|
telemetry?: TelemetryTargets,
|
|
200
200
|
readLinks?: ReadonlyMap<string, KindLinkRead>,
|
|
201
201
|
): LinkTableRow[] {
|
|
202
|
+
const handles = withReaderOutputs(sourceHandles, readLinks);
|
|
202
203
|
const rows: LinkTableRow[] = [];
|
|
203
204
|
const declaredTargets = new Map<string, Set<string>>();
|
|
204
205
|
|
|
@@ -311,6 +312,28 @@ export function resolveLinks(
|
|
|
311
312
|
return [...rows, ...inferred];
|
|
312
313
|
}
|
|
313
314
|
|
|
315
|
+
/**
|
|
316
|
+
* `handles` with the outputs each member's kind reader found in its files
|
|
317
|
+
* (#3935) added to the member's own. The member stays complete unless a gap
|
|
318
|
+
* the reader flagged `outputs` left a name out. A member with no handles
|
|
319
|
+
* (its directory is missing, or its kind unknown) gets none.
|
|
320
|
+
*/
|
|
321
|
+
export function withReaderOutputs(handles: ReadonlyMap<string, MemberHandles>, reads: ReadonlyMap<string, KindLinkRead> | undefined): ReadonlyMap<string, MemberHandles> {
|
|
322
|
+
if (!reads) return handles;
|
|
323
|
+
let out: Map<string, MemberHandles> | undefined;
|
|
324
|
+
for (const [member, read] of reads) {
|
|
325
|
+
const base = handles.get(member);
|
|
326
|
+
const gaps = read.gaps.filter((g) => g.outputs);
|
|
327
|
+
if (!base || (!read.outputs?.length && gaps.length === 0)) continue;
|
|
328
|
+
const have = new Set(base.outputs.map((o) => o.name));
|
|
329
|
+
const added = (read.outputs ?? []).filter((o) => !have.has(o.name) && have.add(o.name)).map((o) => ({ name: o.name }));
|
|
330
|
+
const complete = base.complete && gaps.length === 0;
|
|
331
|
+
const why = base.why ?? (gaps.length === 0 ? null : gaps.length === 1 ? gaps[0].message : `${gaps[0].message}, and ${gaps.length - 1} more`);
|
|
332
|
+
(out ??= new Map(handles)).set(member, { ...base, outputs: [...base.outputs, ...added], complete, why: complete ? base.why : why, exposesNone: false });
|
|
333
|
+
}
|
|
334
|
+
return out ?? handles;
|
|
335
|
+
}
|
|
336
|
+
|
|
314
337
|
/** Match a declared or reader's output row against its producer's handles, setting its status and reason. */
|
|
315
338
|
function resolveOutput(row: LinkRow, handles: ReadonlyMap<string, MemberHandles>): void {
|
|
316
339
|
const producer = handles.get(row.producer);
|
|
@@ -129,7 +129,7 @@ describe("chant workspace ls on built workspaces", () => {
|
|
|
129
129
|
["tools", false, "kind-probe-failed"],
|
|
130
130
|
["vendor", true, null],
|
|
131
131
|
]);
|
|
132
|
-
expect(doc.members[2].reason?.message).toMatch(/known kinds: chant, design, other, workspace/);
|
|
132
|
+
expect(doc.members[2].reason?.message).toMatch(/known kinds: chant, design, other, repo, workspace/);
|
|
133
133
|
expect(doc.members[0].roles).toEqual([{ name: "frontend", path: "src" }]);
|
|
134
134
|
expect(doc.groups[0].reason?.code).toBe("no-matches");
|
|
135
135
|
expect(doc.summary).toEqual({ members: 5, unreadable: 3, groups: 1, matches: 0 });
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"required": ["name", "root", "file", "schema", "minReader", "pins"],
|
|
52
52
|
"properties": {
|
|
53
53
|
"name": { "type": "string", "description": "The declared name. With the revision, it identifies the workspace." },
|
|
54
|
+
"repo": { "type": ["string", "null"], "description": "Added in contract 1 by #3168. The repository the document came from: the URL of the remote origin of the git repository that holds the workspace, with any user name or password removed, or null when there is no origin or the workspace is outside git. With name, root and the revision, it says which repository's workspace a document describes, so a reader that gathers several repositories' documents, such as an org workspace's repo members, tells them apart." },
|
|
54
55
|
"root": {
|
|
55
56
|
"type": "string",
|
|
56
57
|
"description": "The workspace root relative to the git root, with / separators, \".\" for the git root itself. An absolute path outside a git repository."
|
|
@@ -158,6 +159,12 @@
|
|
|
158
159
|
"type": "array",
|
|
159
160
|
"items": { "$ref": "#/$defs/generatedFile" }
|
|
160
161
|
},
|
|
162
|
+
"repo": {
|
|
163
|
+
"description": "Added in contract 1 by #3168. For a member of kind repo, the other repository's workspace it names: url, the pinned rev and the workspace root inside that repository. Absent for every other kind. A repo member's dir is @repo/<name>, a marker that names no directory of this repository.",
|
|
164
|
+
"type": "object",
|
|
165
|
+
"required": ["url", "rev", "workspace"],
|
|
166
|
+
"properties": { "url": { "type": "string" }, "rev": { "type": "string" }, "workspace": { "type": "string" } }
|
|
167
|
+
},
|
|
161
168
|
"agents": {
|
|
162
169
|
"description": "Added in contract 1 by #3615. The names of the agent sessions the declaration binds to the member (agents[].member or agents[].members), in declaration order, read where workspace.agentsFrom says. Empty when none is. A session bound to several members is listed on each.",
|
|
163
170
|
"type": "array",
|
package/src/workspace/ls.ts
CHANGED
|
@@ -39,7 +39,8 @@ import {
|
|
|
39
39
|
} from "./declaration";
|
|
40
40
|
import type { ReasonCode } from "./reason-codes";
|
|
41
41
|
import { memberGenerated, type LsGenerated } from "./ls-generated";
|
|
42
|
-
import {
|
|
42
|
+
import { repoIdentity } from "./repo-ref";
|
|
43
|
+
import { loadKindRegistry, probeKind, REPO_KIND, type KindRegistry } from "./kinds";
|
|
43
44
|
import type { WorkspaceTree } from "./tree";
|
|
44
45
|
import { handToRootChant, locateWorkspace } from "./which-chant";
|
|
45
46
|
import { declaredSessions } from "./write-scope";
|
|
@@ -117,6 +118,8 @@ export interface LsMember {
|
|
|
117
118
|
generated: LsGenerated[];
|
|
118
119
|
/** The agent sessions bound to the member, in declaration order (#3615); empty when none is. */
|
|
119
120
|
agents: string[];
|
|
121
|
+
/** For a member of kind repo, the other repository's workspace it names (#3168). Absent for every other kind. */
|
|
122
|
+
repo?: { url: string; rev: string; workspace: string };
|
|
120
123
|
}
|
|
121
124
|
|
|
122
125
|
/**
|
|
@@ -168,6 +171,8 @@ export type LsDocument =
|
|
|
168
171
|
at: string | null;
|
|
169
172
|
workspace: {
|
|
170
173
|
name: string;
|
|
174
|
+
/** The repository the document came from (#3168): its origin URL, redacted, or null. */
|
|
175
|
+
repo: string | null;
|
|
171
176
|
/** The workspace root relative to the git root, `"."` for the git root itself. Absolute outside git. */
|
|
172
177
|
root: string;
|
|
173
178
|
file: string;
|
|
@@ -211,6 +216,8 @@ export interface LsQuery {
|
|
|
211
216
|
|
|
212
217
|
/** A member's reason code, or null when its kind can read it. */
|
|
213
218
|
export function memberReason(member: Member, tree: WorkspaceTree, kinds: KindRegistry): LsMember["reason"] {
|
|
219
|
+
// A repo member has no directory here (#3168); it is read from its own repository.
|
|
220
|
+
if (member.kind === REPO_KIND) return null;
|
|
214
221
|
if (tree.stat(member.dir === "." ? "" : member.dir) !== "dir") {
|
|
215
222
|
return { code: "dir-missing", message: `${member.dir} is not a directory${tree.label}` };
|
|
216
223
|
}
|
|
@@ -283,6 +290,7 @@ function readListing(query: LsQuery): { doc: LsDocument; declaration?: Declarati
|
|
|
283
290
|
records: unloaded(m.records),
|
|
284
291
|
generated: memberGenerated(m, tree, repoPrefix),
|
|
285
292
|
agents: sessions.agents.filter((a) => a.members.includes(m.name)).map((a) => a.name),
|
|
293
|
+
...(m.repo ? { repo: { ...m.repo } } : {}),
|
|
286
294
|
// The member's x- keys, as declared (#3595).
|
|
287
295
|
...extensionsAt(declaration, m.pointer),
|
|
288
296
|
};
|
|
@@ -311,6 +319,7 @@ function readListing(query: LsQuery): { doc: LsDocument; declaration?: Declarati
|
|
|
311
319
|
at,
|
|
312
320
|
workspace: {
|
|
313
321
|
name: declaration.name,
|
|
322
|
+
repo: repoIdentity(rootOnDisk),
|
|
314
323
|
root: located.root,
|
|
315
324
|
file: declaration.file,
|
|
316
325
|
schema: declaration.schema,
|
|
@@ -12,7 +12,10 @@
|
|
|
12
12
|
* - For `graph` only, members of a pinned package's kind whose kinds file
|
|
13
13
|
* says how to read them (#2874, a `graph` block): each runs `chant graph`
|
|
14
14
|
* in a reader project chant writes for it (`kind-readers.ts`). Other
|
|
15
|
-
* package kinds are `kind-not-run`, as before.
|
|
15
|
+
* package kinds are `kind-not-run`, as before. A kind no built-in or
|
|
16
|
+
* pinned package supplies, such as `terraform` when the pinned lexicon is
|
|
17
|
+
* missing or at another version, is `unknown-kind` and fails the read,
|
|
18
|
+
* with the pin's problem in the message (#4380).
|
|
16
19
|
* - For `build` and `lint` only, every project an example group matches
|
|
17
20
|
* (ws-051): groups are built and linted, and have no ledger, audit or place
|
|
18
21
|
* in the graph. On a large repository this is most of the run, so
|
|
@@ -155,6 +158,12 @@ export interface PlanOptions {
|
|
|
155
158
|
reader?: Toolchain;
|
|
156
159
|
/** The files to plan from, such as a revision's (`--at`); the working tree under `root` by default. */
|
|
157
160
|
tree?: WorkspaceTree;
|
|
161
|
+
/**
|
|
162
|
+
* Why a pinned package's kinds couldn't be loaded (`loadKindRegistry`'s
|
|
163
|
+
* problems), such as a pin at one version with another installed. A graph
|
|
164
|
+
* read names them on a member whose kind is unknown (#4380).
|
|
165
|
+
*/
|
|
166
|
+
kindProblems?: readonly string[];
|
|
158
167
|
}
|
|
159
168
|
|
|
160
169
|
/** Work out which projects run and under which chant. Throws a {@link WorkspaceReadError} for an unreadable declaration or an unknown `--member` name. */
|
|
@@ -218,10 +227,22 @@ export function planMembers(verb: WorkspaceVerb, root: string, options: PlanOpti
|
|
|
218
227
|
});
|
|
219
228
|
continue;
|
|
220
229
|
}
|
|
230
|
+
// A kind no built-in or pinned package supplies is unknown, not a kind
|
|
231
|
+
// the read leaves out (#4380): a terraform member whose pinned lexicon is
|
|
232
|
+
// missing or at another version said kind-not-run before, as if the graph
|
|
233
|
+
// never read its kind. Say why, the pin's problem included.
|
|
234
|
+
if (verb === "graph" && !kinds.get(entry.kind)) {
|
|
235
|
+
const reason = memberReason(entry, tree, kinds) ?? { code: "unknown-kind", message: `no built-in kind or pinned package supplies kind ${entry.kind}` };
|
|
236
|
+
const problems = reason.code === "unknown-kind" ? (options.kindProblems ?? []) : [];
|
|
237
|
+
unreadable.push({ name: entry.name, dir: entry.dir, kind: entry.kind, reason: problems.length ? { ...reason, message: `${reason.message}; ${problems.join("; ")}` } : reason });
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
221
240
|
if (entry.kind !== "chant") {
|
|
222
241
|
const why =
|
|
223
242
|
entry.kind === "workspace"
|
|
224
243
|
? "a nested workspace runs its own chant workspace commands"
|
|
244
|
+
: entry.kind === "repo"
|
|
245
|
+
? "a repo member is another repository's workspace, which runs its own chant workspace commands; chant workspace graph reads it at its pinned revision"
|
|
225
246
|
: entry.kind === "design"
|
|
226
247
|
? "a design member is data: chant reads its files for record pins and builds nothing"
|
|
227
248
|
: `chant workspace ${verb} runs members of kind chant, and this one is kind ${entry.kind}`;
|
|
@@ -308,6 +329,8 @@ export function memberArgv(verb: WorkspaceVerb, unit: RunUnit, args: ParsedArgs)
|
|
|
308
329
|
// The detail tier too, so `workspace graph --detail 1` composes collapsed
|
|
309
330
|
// composites with their rolled-up status (#4228).
|
|
310
331
|
if (args.detail !== undefined) argv.push("--detail", String(args.detail));
|
|
332
|
+
// Each member's chant maps its own capability view (#4378).
|
|
333
|
+
if (args.capabilityView) argv.push("--capability-view");
|
|
311
334
|
}
|
|
312
335
|
return argv;
|
|
313
336
|
}
|
|
@@ -535,13 +558,17 @@ export async function runWorkspaceMembers(ctx: CommandContext, verb: WorkspaceVe
|
|
|
535
558
|
}
|
|
536
559
|
|
|
537
560
|
const results = await executePlan(plan, args);
|
|
538
|
-
|
|
561
|
+
// #2549: the disagreement lint, over every member's graph, when asked for.
|
|
562
|
+
const cross = verb === "lint" && args.crossRoot ? await runCrossRoot(found.dir, args) : undefined;
|
|
563
|
+
const anyFailed = results.some((r) => r.exitCode !== 0) || plan.unreadable.length > 0 || cross?.failed === true;
|
|
539
564
|
const workspace = { name: plan.workspace.name, root: plan.workspace.root };
|
|
540
565
|
|
|
541
566
|
if (verb === "lint" && args.format === "sarif") {
|
|
542
567
|
for (const r of results) if (r.stderr.trim()) process.stderr.write(r.stderr.endsWith("\n") ? r.stderr : `${r.stderr}\n`);
|
|
543
568
|
const unreadable: MemberOutput[] = plan.unreadable.map((s) => ({ id: s.name, member: s.name, dir: s.dir ?? ".", exitCode: 1, stdout: "", stderr: `${s.reason.code}: ${s.reason.message}` }));
|
|
544
|
-
|
|
569
|
+
const sarif = mergeSarif([...results, ...unreadable], plan.workspace.root) as { runs?: unknown[] };
|
|
570
|
+
if (cross) (sarif.runs ??= []).push(crossRootSarifRun(cross));
|
|
571
|
+
emitDocument(sarif, args.output);
|
|
545
572
|
console.error(summaryLine(plan, results));
|
|
546
573
|
return anyFailed ? 1 : 0;
|
|
547
574
|
}
|
|
@@ -577,6 +604,7 @@ export async function runWorkspaceMembers(ctx: CommandContext, verb: WorkspaceVe
|
|
|
577
604
|
...plan.unreadable.map((s) => ({ member: s.name, dir: s.dir, exitCode: 1, diagnostics: null, reason: s.reason })),
|
|
578
605
|
],
|
|
579
606
|
skipped: plan.skipped,
|
|
607
|
+
...(cross ? { crossRoot: crossRootJson(cross) } : {}),
|
|
580
608
|
};
|
|
581
609
|
}
|
|
582
610
|
emitDocument(doc, args.output);
|
|
@@ -587,5 +615,56 @@ export async function runWorkspaceMembers(ctx: CommandContext, verb: WorkspaceVe
|
|
|
587
615
|
// Text: each member's own output under a heading. A build without -o prints
|
|
588
616
|
// no templates, since several members' templates can't share one stdout.
|
|
589
617
|
printSections(plan, results, verb !== "build" || args.output !== undefined);
|
|
618
|
+
if (cross) printCrossRoot(cross);
|
|
590
619
|
return anyFailed ? 1 : 0;
|
|
591
620
|
}
|
|
621
|
+
|
|
622
|
+
// ── The disagreement lint (#2549) ────────────────────────────────────────────
|
|
623
|
+
|
|
624
|
+
interface CrossRootRun {
|
|
625
|
+
result?: import("./cross-root-lint").CrossRootLintResult;
|
|
626
|
+
/** Why the members' graphs could not be read. */
|
|
627
|
+
error?: string;
|
|
628
|
+
/** An error finding, or a graph that could not be read. */
|
|
629
|
+
failed: boolean;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
async function runCrossRoot(root: string, args: ParsedArgs): Promise<CrossRootRun> {
|
|
633
|
+
const { workspaceGraph } = await import("./graph-cli");
|
|
634
|
+
const { crossRootLint } = await import("./cross-root-lint");
|
|
635
|
+
const { doc, failed } = await workspaceGraph({ cwd: root, ...(args.members?.length ? { members: args.members } : {}), onStderr: (t) => process.stderr.write(t) });
|
|
636
|
+
if ("error" in doc) return { error: `${doc.error.code}: ${doc.error.message}`, failed: true };
|
|
637
|
+
const result = await crossRootLint(doc, args.env ? { env: args.env } : {});
|
|
638
|
+
return { result, failed: failed || result.findings.some((f) => f.severity === "error") };
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
function crossRootJson(cross: CrossRootRun): unknown {
|
|
642
|
+
return cross.result ? { findings: cross.result.findings, checks: cross.result.checks, unloaded: cross.result.unloaded } : { error: cross.error };
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
function crossRootSarifRun(cross: CrossRootRun): unknown {
|
|
646
|
+
const findings = cross.result?.findings ?? [];
|
|
647
|
+
return {
|
|
648
|
+
tool: { driver: { name: "chant", rules: [...new Set(findings.map((f) => f.checkId))].sort().map((id) => ({ id })) } },
|
|
649
|
+
automationDetails: { id: "cross-root/" },
|
|
650
|
+
properties: { crossRoot: true, checks: cross.result?.checks ?? [], unloaded: cross.result?.unloaded ?? [] },
|
|
651
|
+
results: findings.map((f) => ({
|
|
652
|
+
ruleId: f.checkId,
|
|
653
|
+
level: f.severity === "error" ? "error" : f.severity === "warning" ? "warning" : "note",
|
|
654
|
+
message: { text: f.message },
|
|
655
|
+
...(f.root ? { properties: { member: f.root } } : {}),
|
|
656
|
+
})),
|
|
657
|
+
...(cross.error ? { invocations: [{ executionSuccessful: false, toolExecutionNotifications: [{ message: { text: cross.error } }] }] } : {}),
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
function printCrossRoot(cross: CrossRootRun): void {
|
|
662
|
+
if (!cross.result) {
|
|
663
|
+
console.log(`── cross-root (the members' graphs could not be read: ${cross.error})`);
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
const { findings, checks, unloaded } = cross.result;
|
|
667
|
+
console.log(`── cross-root (${checks.join(", ")}; ${findings.length} finding${findings.length === 1 ? "" : "s"})`);
|
|
668
|
+
for (const f of findings) console.log(` ${f.severity.padEnd(7)} ${f.checkId}${f.root ? ` [${f.root}]` : ""} ${f.message}`);
|
|
669
|
+
for (const u of unloaded) console.log(` (lexicon ${u.lexicon}: its cross-root checks could not be loaded: ${u.reason})`);
|
|
670
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A member kind names a JSON Schema its member's file must pass (#3672): the
|
|
3
|
+
* kinds file's memberFile block, the schema read as data from the package,
|
|
4
|
+
* and WSP012 from `chant workspace check`.
|
|
5
|
+
*/
|
|
6
|
+
import { execFileSync } from "node:child_process";
|
|
7
|
+
import { mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
8
|
+
import { tmpdir } from "node:os";
|
|
9
|
+
import { dirname, join } from "node:path";
|
|
10
|
+
import { afterAll, describe, expect, test } from "vitest";
|
|
11
|
+
import { runDeclarationChecks } from "./checks";
|
|
12
|
+
import { checkMemberFile, parseKindData, readPackageKinds } from "./kinds";
|
|
13
|
+
|
|
14
|
+
const scratch: string[] = [];
|
|
15
|
+
afterAll(() => {
|
|
16
|
+
for (const d of scratch) rmSync(d, { recursive: true, force: true });
|
|
17
|
+
});
|
|
18
|
+
function repo(files: Record<string, string>): string {
|
|
19
|
+
const root = realpathSync(mkdtempSync(join(tmpdir(), "chant-3672-")));
|
|
20
|
+
scratch.push(root);
|
|
21
|
+
execFileSync("git", ["init", "-q"], { cwd: root });
|
|
22
|
+
for (const [path, text] of Object.entries(files)) {
|
|
23
|
+
mkdirSync(dirname(join(root, path)), { recursive: true });
|
|
24
|
+
writeFileSync(join(root, path), text);
|
|
25
|
+
}
|
|
26
|
+
return root;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const controlSchema = {
|
|
30
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
31
|
+
type: "object",
|
|
32
|
+
required: ["estates"],
|
|
33
|
+
properties: { estates: { type: "array", items: { type: "string" } } },
|
|
34
|
+
additionalProperties: false,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const controlKind = (memberFile: unknown = { path: "terragucci.yml", schema: "schemas/control.schema.json" }) => ({
|
|
38
|
+
name: "control",
|
|
39
|
+
description: "a terragucci control repo, with a terragucci.yml",
|
|
40
|
+
precedence: 300,
|
|
41
|
+
probe: { anyFile: ["terragucci.yml"] },
|
|
42
|
+
memberFile,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
/** A kinds-only package at kinds/control, and a workspace that pins it. */
|
|
46
|
+
function workspace(files: Record<string, string>, opts: { schema?: string | null; kind?: unknown } = {}): string {
|
|
47
|
+
const schemaText = opts.schema === undefined ? JSON.stringify(controlSchema) : opts.schema;
|
|
48
|
+
return repo({
|
|
49
|
+
"chant.workspace.json": JSON.stringify({ name: "acme", schema: 1, pins: [{ path: "kinds/control" }], members: [{ name: "ctl", dir: "ctl", kind: "control" }] }),
|
|
50
|
+
"kinds/control/package.json": JSON.stringify({ name: "control-kinds", exports: { "./workspace-kinds": "./workspace-kinds.json" } }),
|
|
51
|
+
"kinds/control/workspace-kinds.json": JSON.stringify({ schema: 1, kinds: [opts.kind ?? controlKind()] }),
|
|
52
|
+
...(schemaText === null ? {} : { "kinds/control/schemas/control.schema.json": schemaText }),
|
|
53
|
+
...files,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const wsp012 = async (root: string) =>
|
|
58
|
+
(await runDeclarationChecks(root)).diagnostics.filter((d) => d.ruleId === "WSP012" || d.ruleId === "WSP002").map((d) => `${d.ruleId}: ${d.message}`);
|
|
59
|
+
|
|
60
|
+
describe("the kinds file's memberFile block", () => {
|
|
61
|
+
test("is kind data: a path in the member and a .json schema in the package", () => {
|
|
62
|
+
const ok = parseKindData(JSON.stringify({ schema: 1, kinds: [controlKind()] }), "p");
|
|
63
|
+
expect(ok.problems).toEqual([]);
|
|
64
|
+
expect(ok.kinds[0].memberFile).toEqual({ path: "terragucci.yml", schema: "schemas/control.schema.json" });
|
|
65
|
+
for (const bad of [{ path: "../x.yml", schema: "s.json" }, { path: "x.yml", schema: "s.yaml" }, { path: "x.yml", schema: "../s.json" }, { path: "x.yml" }]) {
|
|
66
|
+
expect(parseKindData(JSON.stringify({ schema: 1, kinds: [controlKind(bad)] }), "p").problems).not.toEqual([]);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("reading the package compiles the schema as data, and reports one that is missing or not a schema", () => {
|
|
71
|
+
const good = workspace({});
|
|
72
|
+
const read = readPackageKinds(join(good, "kinds/control"));
|
|
73
|
+
expect(read.problems).toEqual([]);
|
|
74
|
+
expect(typeof read.kinds[0].memberFile?.validate).toBe("function");
|
|
75
|
+
expect(readPackageKinds(join(workspace({}, { schema: null }), "kinds/control")).problems[0]).toMatch(/does not exist/);
|
|
76
|
+
expect(readPackageKinds(join(workspace({}, { schema: "{ nope" }), "kinds/control")).problems[0]).toMatch(/is not JSON/);
|
|
77
|
+
expect(readPackageKinds(join(workspace({}, { schema: JSON.stringify({ type: 12 }) }), "kinds/control")).problems[0]).toMatch(/does not compile/);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe("checkMemberFile", () => {
|
|
82
|
+
const mf = () => readPackageKinds(join(workspace({}), "kinds/control")).kinds[0].memberFile!;
|
|
83
|
+
test("parses YAML by extension and JSON otherwise, and names each failing place", () => {
|
|
84
|
+
expect(checkMemberFile(mf(), "terragucci.yml", "estates: [a, b]\n")).toEqual([]);
|
|
85
|
+
expect(checkMemberFile(mf(), "t.json", '{"estates":["a"]}')).toEqual([]);
|
|
86
|
+
expect(checkMemberFile(mf(), "terragucci.yml", "estates: [1]\nextra: true\n").map((p) => p.message).sort()).toEqual(["/estates/0 must be string", "the file must NOT have additional properties (extra)"]);
|
|
87
|
+
expect(checkMemberFile(mf(), "t.json", "estates: []")[0].message).toMatch(/^is not JSON/);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe("WSP012: a member's file passes its kind's schema", () => {
|
|
92
|
+
test("a member whose file passes has no finding", async () => {
|
|
93
|
+
expect(await wsp012(workspace({ "ctl/terragucci.yml": "estates: [prod]\n" }))).toEqual([]);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test("a file that fails the schema fails the check, once per reason", async () => {
|
|
97
|
+
const report = await runDeclarationChecks(workspace({ "ctl/terragucci.yml": "estates: prod\n" }));
|
|
98
|
+
expect(report.ok).toBe(false);
|
|
99
|
+
const found = report.diagnostics.filter((d) => d.ruleId === "WSP012");
|
|
100
|
+
expect(found.map((d) => d.message)).toEqual(["member ctl's terragucci.yml fails kind control's schema schemas/control.schema.json: /estates must be array"]);
|
|
101
|
+
expect(found[0].file).toMatch(/ctl\/terragucci\.yml$/);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("a member without the file fails it", async () => {
|
|
105
|
+
// The probe also wants the file; the declared kind still names the schema, so WSP012 says what is missing.
|
|
106
|
+
expect(await wsp012(workspace({ "ctl/README.md": "" }))).toEqual(["WSP012: member ctl (ctl) has no terragucci.yml, which kind control requires"]);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test("a schema that doesn't load is WSP002, and its members can't pass WSP012", async () => {
|
|
110
|
+
const found = await wsp012(workspace({ "ctl/terragucci.yml": "estates: []\n" }, { schema: null }));
|
|
111
|
+
expect(found).toHaveLength(2);
|
|
112
|
+
expect(found[0]).toMatch(/^WSP002: .*kind control names member-file schema schemas\/control.schema.json, which does not exist/);
|
|
113
|
+
expect(found[1]).toMatch(/^WSP012: .*did not load/);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test("the declaration can turn it down", async () => {
|
|
117
|
+
const root = workspace({ "ctl/terragucci.yml": "nope: 1\n" });
|
|
118
|
+
const decl = JSON.parse(execFileSync("cat", [join(root, "chant.workspace.json")], { encoding: "utf-8" }));
|
|
119
|
+
writeFileSync(join(root, "chant.workspace.json"), JSON.stringify({ ...decl, checks: { WSP012: "warning" } }));
|
|
120
|
+
const report = await runDeclarationChecks(root);
|
|
121
|
+
expect(report.ok).toBe(true);
|
|
122
|
+
expect(report.diagnostics.filter((d) => d.ruleId === "WSP012").every((d) => d.severity === "warning")).toBe(true);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The links `chant migrate` writes into a workspace declaration (#4399):
|
|
3
|
+
* which members are the producer and the consumer, that the edit touches only
|
|
4
|
+
* the consumer's `links`, that a second run adds nothing, and that every case
|
|
5
|
+
* with nothing to link says why.
|
|
6
|
+
*/
|
|
7
|
+
import { afterAll, describe, expect, test } from "vitest";
|
|
8
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
9
|
+
import { tmpdir } from "node:os";
|
|
10
|
+
import { dirname, join } from "node:path";
|
|
11
|
+
import { parseDeclaration } from "./declaration";
|
|
12
|
+
import { planMigrateLinks } from "./migrate-links";
|
|
13
|
+
|
|
14
|
+
const scratch: string[] = [];
|
|
15
|
+
afterAll(() => {
|
|
16
|
+
for (const d of scratch) rmSync(d, { recursive: true, force: true });
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
function repo(declaration: string, file = "chant.workspace.json"): string {
|
|
20
|
+
const root = mkdtempSync(join(tmpdir(), "chant-migrate-links-"));
|
|
21
|
+
scratch.push(root);
|
|
22
|
+
for (const [path, text] of Object.entries({ [file]: declaration, "db/schema.sql": "", "mirror/mirrors.ts": "", "other/x.ts": "" })) {
|
|
23
|
+
mkdirSync(dirname(join(root, path)), { recursive: true });
|
|
24
|
+
writeFileSync(join(root, path), text);
|
|
25
|
+
}
|
|
26
|
+
return root;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const decl = (members: unknown[]) => `${JSON.stringify({ name: "shop", schema: 1, members }, null, 2)}\n`;
|
|
30
|
+
const MEMBERS = [
|
|
31
|
+
{ name: "db", dir: "db", kind: "chant" },
|
|
32
|
+
{ name: "mirror", dir: "mirror", kind: "chant" },
|
|
33
|
+
];
|
|
34
|
+
const outputs = ["public.users.id", "public.users.email"];
|
|
35
|
+
|
|
36
|
+
describe("planMigrateLinks", () => {
|
|
37
|
+
test("adds one link per output to the member holding the output file, and changes nothing else", () => {
|
|
38
|
+
const root = repo(decl(MEMBERS));
|
|
39
|
+
const r = planMigrateLinks({ sourcePath: join(root, "db/schema.sql"), outputPath: join(root, "mirror/mirrors.ts"), outputs });
|
|
40
|
+
if (!r || !("plan" in r)) throw new Error(JSON.stringify(r));
|
|
41
|
+
expect(r.plan).toMatchObject({ producer: "db", consumer: "mirror", added: outputs });
|
|
42
|
+
const members = parseDeclaration(r.plan.text, "chant.workspace.json").members;
|
|
43
|
+
expect(members.find((m) => m.name === "mirror")!.links.map((l) => `${l.member} ${l.output}`)).toEqual(outputs.map((o) => `db ${o}`));
|
|
44
|
+
expect(members.find((m) => m.name === "db")!.links).toEqual([]);
|
|
45
|
+
expect(r.plan.text.startsWith('{\n "name": "shop"')).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("keeps the links already there and adds only the new ones; a second plan adds nothing", () => {
|
|
49
|
+
const root = repo(decl([MEMBERS[0], { ...MEMBERS[1], links: [{ member: "db", output: "public.users.id" }, { member: "other", output: "x" }] }, { name: "other", dir: "other", kind: "chant" }]));
|
|
50
|
+
const r = planMigrateLinks({ sourcePath: join(root, "db"), outputPath: join(root, "mirror/mirrors.ts"), outputs });
|
|
51
|
+
if (!r || !("plan" in r)) throw new Error(JSON.stringify(r));
|
|
52
|
+
expect(r.plan.added).toEqual(["public.users.email"]);
|
|
53
|
+
const links = parseDeclaration(r.plan.text, "x.json").members.find((m) => m.name === "mirror")!.links;
|
|
54
|
+
expect(links.map((l) => `${l.member} ${l.output}`)).toEqual(["db public.users.id", "other x", "db public.users.email"]);
|
|
55
|
+
writeFileSync(join(root, "chant.workspace.json"), r.plan.text);
|
|
56
|
+
const again = planMigrateLinks({ sourcePath: join(root, "db"), outputPath: join(root, "mirror/mirrors.ts"), outputs });
|
|
57
|
+
expect(again).toMatchObject({ plan: { added: [] } });
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("reads a jsonc declaration and keeps its comments", () => {
|
|
61
|
+
const text = `{\n // the shop\n "name": "shop", "schema": 1,\n "members": [\n { "name": "db", "dir": "db", "kind": "chant" },\n { "name": "mirror", "dir": "mirror", "kind": "chant" } // the mirror\n ]\n}\n`;
|
|
62
|
+
const root = repo(text, "chant.workspace.jsonc");
|
|
63
|
+
const r = planMigrateLinks({ sourcePath: join(root, "db/schema.sql"), outputPath: join(root, "mirror/mirrors.ts"), outputs });
|
|
64
|
+
if (!r || !("plan" in r)) throw new Error(JSON.stringify(r));
|
|
65
|
+
expect(r.plan.text).toContain("// the shop");
|
|
66
|
+
expect(r.plan.text).toContain("// the mirror");
|
|
67
|
+
expect(r.plan.added).toEqual(outputs);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("the deepest member holds a path: a nested member is not its parent's", () => {
|
|
71
|
+
const root = repo(decl([{ name: "all", dir: ".", kind: "chant" }, { name: "db", dir: "db", kind: "chant" }, { name: "mirror", dir: "mirror", kind: "chant" }]));
|
|
72
|
+
const r = planMigrateLinks({ sourcePath: join(root, "db/schema.sql"), outputPath: join(root, "mirror/mirrors.ts"), outputs });
|
|
73
|
+
expect(r).toMatchObject({ plan: { producer: "db", consumer: "mirror" } });
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("no workspace above the source is no outcome at all", () => {
|
|
77
|
+
const root = mkdtempSync(join(tmpdir(), "chant-no-workspace-"));
|
|
78
|
+
scratch.push(root);
|
|
79
|
+
writeFileSync(join(root, "schema.sql"), "");
|
|
80
|
+
expect(planMigrateLinks({ sourcePath: join(root, "schema.sql"), outputPath: join(root, "out.ts"), outputs })).toBeUndefined();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test.each([
|
|
84
|
+
["output to stdout", (root: string) => ({ sourcePath: join(root, "db/schema.sql"), outputPath: undefined }), "pass --output inside the ClickHouse member"],
|
|
85
|
+
["a source in no member", (root: string) => ({ sourcePath: join(root, "elsewhere/schema.sql"), outputPath: join(root, "mirror/mirrors.ts") }), "is in no member"],
|
|
86
|
+
["an output in no member", (root: string) => ({ sourcePath: join(root, "db/schema.sql"), outputPath: join(root, "elsewhere/out.ts") }), "is in no member"],
|
|
87
|
+
["a source and output in one member", (root: string) => ({ sourcePath: join(root, "db/schema.sql"), outputPath: join(root, "db/out.ts") }), "does not link to itself"],
|
|
88
|
+
])("%s is skipped with a reason", (_name, paths, reason) => {
|
|
89
|
+
const root = repo(decl(MEMBERS));
|
|
90
|
+
const r = planMigrateLinks({ ...paths(root), outputs });
|
|
91
|
+
expect(r && "skipped" in r ? r.skipped : r).toContain(reason);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test("a declaration that does not read is skipped with its error, never rewritten", () => {
|
|
95
|
+
const root = repo("{ not json");
|
|
96
|
+
const r = planMigrateLinks({ sourcePath: join(root, "db/schema.sql"), outputPath: join(root, "mirror/mirrors.ts"), outputs });
|
|
97
|
+
expect(r && "skipped" in r ? r.skipped : r).toContain("does not read, so no link was written");
|
|
98
|
+
});
|
|
99
|
+
});
|