@intentius/chant 0.124.26 → 0.124.28
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/README.md +1 -1
- package/dist/__golden__/wave-loop/fan-out-gated.json +8 -0
- package/dist/__golden__/wave-loop/fan-out-no-members.json +4 -0
- package/dist/__golden__/wave-loop/fan-out-only.json +6 -0
- package/dist/__golden__/wave-loop/op-by-apply-hold.json +2 -0
- package/dist/__golden__/wave-loop/op-cost-member.json +3 -0
- package/dist/__golden__/wave-loop/op-held-on-before-apply.json +1 -0
- package/dist/__golden__/wave-loop/op-held-on.json +2 -0
- package/dist/__golden__/wave-loop/op-hooks-held.json +2 -0
- package/dist/__golden__/wave-loop/op-hooks-hold-before-apply.json +2 -0
- package/dist/__golden__/wave-loop/op-hooks-refused-at-base.json +3 -0
- package/dist/__golden__/wave-loop/op-hooks-share.json +3 -0
- package/dist/__golden__/wave-loop/op-per-run.json +7 -0
- package/dist/__golden__/wave-loop/op-pr-review.json +7 -0
- package/dist/__golden__/wave-loop/op-sealed.json +3 -0
- package/dist/__golden__/wave-loop/op-spend.json +3 -0
- package/dist/__golden__/wave-loop/op-wave-commands.json +7 -0
- package/dist/__golden__/wave-loop/op-wide-waiting.json +4 -0
- package/dist/change-set-graph.d.ts +56 -0
- package/dist/change-set-graph.d.ts.map +1 -0
- package/dist/change-set-graph.js +128 -0
- package/dist/change-set.d.ts +52 -3
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +35 -4
- package/dist/chant-version.d.ts +9 -0
- package/dist/chant-version.d.ts.map +1 -0
- package/dist/chant-version.js +16 -0
- package/dist/cli/commands/build.d.ts +8 -0
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/build.js +9 -8
- package/dist/cli/commands/check-lexicon-docs.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon-docs.js +30 -2
- package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon.js +13 -2
- package/dist/cli/commands/init-lexicon/templates/docs.d.ts +4 -1
- package/dist/cli/commands/init-lexicon/templates/docs.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon/templates/docs.js +6 -6
- package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon.js +17 -8
- package/dist/cli/handlers/approve.d.ts.map +1 -1
- package/dist/cli/handlers/approve.js +19 -4
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/build.js +28 -0
- package/dist/cli/handlers/change-set.d.ts +10 -0
- package/dist/cli/handlers/change-set.d.ts.map +1 -1
- package/dist/cli/handlers/change-set.js +51 -1
- package/dist/cli/handlers/fan-out.d.ts +1 -1
- package/dist/cli/handlers/fan-out.d.ts.map +1 -1
- package/dist/cli/handlers/fan-out.js +14 -3
- package/dist/cli/handlers/pr.d.ts +8 -2
- package/dist/cli/handlers/pr.d.ts.map +1 -1
- package/dist/cli/handlers/pr.js +148 -24
- package/dist/cli/handlers/promote.d.ts.map +1 -1
- package/dist/cli/handlers/promote.js +256 -21
- package/dist/cli/handlers/release.d.ts +34 -0
- package/dist/cli/handlers/release.d.ts.map +1 -0
- package/dist/cli/handlers/release.js +203 -0
- package/dist/cli/handlers/run.d.ts +28 -2
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/handlers/run.js +170 -13
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +88 -13
- package/dist/cli/mcp/workspace-tools.js +1 -1
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +49 -3
- package/dist/cli/registry.d.ts +29 -3
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/cli/run-events.d.ts +29 -0
- package/dist/cli/run-events.d.ts.map +1 -0
- package/dist/cli/run-events.js +47 -0
- package/dist/cli/version.d.ts +3 -5
- package/dist/cli/version.d.ts.map +1 -1
- package/dist/cli/version.js +3 -13
- package/dist/codegen/docs-in-site.d.ts +71 -0
- package/dist/codegen/docs-in-site.d.ts.map +1 -0
- package/dist/codegen/docs-in-site.js +177 -0
- package/dist/codegen/docs-types.d.ts +14 -1
- package/dist/codegen/docs-types.d.ts.map +1 -1
- package/dist/codegen/docs.d.ts +18 -1
- package/dist/codegen/docs.d.ts.map +1 -1
- package/dist/codegen/docs.js +40 -7
- package/dist/codegen/rehype-base-url.mjs +15 -9
- package/dist/components/auto-release.d.ts +4 -1
- package/dist/components/auto-release.d.ts.map +1 -1
- package/dist/components/auto-release.js +2 -0
- package/dist/components/cli-support.d.ts +6 -0
- package/dist/components/cli-support.d.ts.map +1 -1
- package/dist/components/cli-support.js +10 -9
- package/dist/components/driver.d.ts +42 -9
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/driver.js +81 -54
- package/dist/components/fan-out-run.d.ts +7 -0
- package/dist/components/fan-out-run.d.ts.map +1 -1
- package/dist/components/fan-out-run.js +35 -26
- package/dist/components/pr-run.d.ts +11 -0
- package/dist/components/pr-run.d.ts.map +1 -1
- package/dist/components/pr-run.js +20 -1
- package/dist/components/promote-order.d.ts +38 -0
- package/dist/components/promote-order.d.ts.map +1 -0
- package/dist/components/promote-order.js +62 -0
- package/dist/components/promote.d.ts +15 -2
- package/dist/components/promote.d.ts.map +1 -1
- package/dist/components/promote.js +17 -0
- package/dist/components/release-compile.d.ts +133 -0
- package/dist/components/release-compile.d.ts.map +1 -0
- package/dist/components/release-compile.js +376 -0
- package/dist/components/release-gate.d.ts +125 -0
- package/dist/components/release-gate.d.ts.map +1 -0
- package/dist/components/release-gate.js +282 -0
- package/dist/components/release-promote.d.ts +96 -0
- package/dist/components/release-promote.d.ts.map +1 -0
- package/dist/components/release-promote.js +204 -0
- package/dist/components/run-progress.d.ts +7 -0
- package/dist/components/run-progress.d.ts.map +1 -1
- package/dist/components/wave-plan.d.ts +3 -1
- package/dist/components/wave-plan.d.ts.map +1 -1
- package/dist/components/wave-plan.js +1 -1
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/lifecycle/change-set-store.d.ts +67 -0
- package/dist/lifecycle/change-set-store.d.ts.map +1 -0
- package/dist/lifecycle/change-set-store.js +96 -0
- package/dist/lifecycle/commit-sha.d.ts +13 -0
- package/dist/lifecycle/commit-sha.d.ts.map +1 -0
- package/dist/lifecycle/commit-sha.js +21 -0
- package/dist/lifecycle/gate-change-set.d.ts +69 -0
- package/dist/lifecycle/gate-change-set.d.ts.map +1 -0
- package/dist/lifecycle/gate-change-set.js +106 -0
- package/dist/lifecycle/gate-ledger.d.ts +49 -1
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.js +18 -0
- package/dist/lifecycle/release-cut.d.ts +107 -0
- package/dist/lifecycle/release-cut.d.ts.map +1 -0
- package/dist/lifecycle/release-cut.js +273 -0
- package/dist/lifecycle/release-ledger.d.ts +54 -0
- package/dist/lifecycle/release-ledger.d.ts.map +1 -1
- package/dist/lifecycle/release-ledger.js +53 -20
- package/dist/lifecycle/release-store.d.ts +190 -0
- package/dist/lifecycle/release-store.d.ts.map +1 -0
- package/dist/lifecycle/release-store.js +318 -0
- package/dist/lifecycle/run-ledger.d.ts +4 -0
- package/dist/lifecycle/run-ledger.d.ts.map +1 -1
- package/dist/lifecycle/run-ledger.js +2 -0
- package/dist/op/activities/change-coverage.d.ts.map +1 -1
- package/dist/op/activities/change-coverage.js +4 -2
- package/dist/op/activities/source-release.d.ts.map +1 -1
- package/dist/op/activities/source-release.js +7 -3
- package/dist/op/activities/source-rollback.d.ts.map +1 -1
- package/dist/op/activities/source-rollback.js +7 -3
- package/dist/op/activity-registry.d.ts +6 -3
- package/dist/op/activity-registry.d.ts.map +1 -1
- package/dist/op/activity-registry.js +7 -5
- package/dist/op/discover.d.ts.map +1 -1
- package/dist/op/discover.js +14 -7
- package/dist/op/gate-name.d.ts +11 -2
- package/dist/op/gate-name.d.ts.map +1 -1
- package/dist/op/gate-name.js +12 -3
- package/dist/op/gate-run-locator.d.ts +22 -0
- package/dist/op/gate-run-locator.d.ts.map +1 -1
- package/dist/op/gate-run-locator.js +31 -0
- package/dist/op/gate.d.ts +27 -3
- package/dist/op/gate.d.ts.map +1 -1
- package/dist/op/gate.js +57 -3
- package/dist/op/local-executor.d.ts +36 -1
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/local-executor.js +158 -52
- package/dist/op/op-waves-run.d.ts.map +1 -1
- package/dist/op/op-waves-run.js +4 -0
- package/dist/op/run-live.d.ts +2 -0
- package/dist/op/run-live.d.ts.map +1 -1
- package/dist/op/run-live.js +1 -1
- package/dist/op/runtime.d.ts +46 -0
- package/dist/op/runtime.d.ts.map +1 -1
- package/dist/op/runtimes/local.d.ts.map +1 -1
- package/dist/op/runtimes/local.js +12 -2
- package/dist/point-decision.d.ts +2 -0
- package/dist/point-decision.d.ts.map +1 -1
- package/dist/point-decision.js +9 -2
- package/dist/run-event-store.d.ts +77 -0
- package/dist/run-event-store.d.ts.map +1 -0
- package/dist/run-event-store.js +204 -0
- package/dist/run-event-stream.d.ts +132 -0
- package/dist/run-event-stream.d.ts.map +1 -0
- package/dist/run-event-stream.js +238 -0
- package/dist/run-event.d.ts +267 -0
- package/dist/run-event.d.ts.map +1 -0
- package/dist/run-event.js +207 -0
- package/dist/wave-runtime.mjs +225 -242
- package/dist/workspace/__fixtures__/run-event-check.d.ts +19 -0
- package/dist/workspace/__fixtures__/run-event-check.d.ts.map +1 -0
- package/dist/workspace/__fixtures__/run-event-check.js +59 -0
- package/dist/workspace/change-set-show.d.ts +56 -0
- package/dist/workspace/change-set-show.d.ts.map +1 -0
- package/dist/workspace/change-set-show.js +54 -0
- package/dist/workspace/change-set-show.schema.json +102 -0
- package/dist/workspace/change-set.schema.json +28 -1
- package/dist/workspace/changes-cli.d.ts.map +1 -1
- package/dist/workspace/changes-cli.js +10 -1
- package/dist/workspace/changes.d.ts +37 -0
- package/dist/workspace/changes.d.ts.map +1 -1
- package/dist/workspace/changes.js +49 -2
- package/dist/workspace/changes.schema.json +135 -0
- package/dist/workspace/ci-green-cli.d.ts +19 -4
- package/dist/workspace/ci-green-cli.d.ts.map +1 -1
- package/dist/workspace/ci-green-cli.js +75 -12
- package/dist/workspace/ci-green-forge.d.ts +20 -3
- package/dist/workspace/ci-green-forge.d.ts.map +1 -1
- package/dist/workspace/ci-green-forge.js +6 -4
- package/dist/workspace/ci-green-workflow.d.ts +11 -0
- package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
- package/dist/workspace/ci-green-workflow.js +6 -0
- package/dist/workspace/ci-green.d.ts +273 -13
- package/dist/workspace/ci-green.d.ts.map +1 -1
- package/dist/workspace/ci-green.js +449 -38
- package/dist/workspace/ci-last-green.schema.json +32 -2
- package/dist/workspace/ci-list.schema.json +525 -0
- package/dist/workspace/commit-links.d.ts +85 -0
- package/dist/workspace/commit-links.d.ts.map +1 -0
- package/dist/workspace/commit-links.js +163 -0
- package/dist/workspace/declaration.d.ts +19 -0
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.js +1 -1
- package/dist/workspace/declaration.schema.json +12 -0
- package/dist/workspace/identity-gate-rule.d.ts +37 -0
- package/dist/workspace/identity-gate-rule.d.ts.map +1 -1
- package/dist/workspace/identity-gate-rule.js +72 -7
- package/dist/workspace/identity.d.ts +12 -0
- package/dist/workspace/identity.d.ts.map +1 -1
- package/dist/workspace/identity.js +13 -1
- package/dist/workspace/intent.d.ts +6 -1
- package/dist/workspace/intent.d.ts.map +1 -1
- package/dist/workspace/intent.js +51 -1
- package/dist/workspace/ls.d.ts +4 -0
- package/dist/workspace/ls.d.ts.map +1 -1
- package/dist/workspace/ls.js +2 -0
- package/dist/workspace/ls.schema.json +3 -1
- package/dist/workspace/member-pipeline.d.ts +6 -0
- package/dist/workspace/member-pipeline.d.ts.map +1 -1
- package/dist/workspace/member-pipeline.js +6 -0
- package/dist/workspace/promotion-order.d.ts +41 -0
- package/dist/workspace/promotion-order.d.ts.map +1 -0
- package/dist/workspace/promotion-order.js +95 -0
- package/dist/workspace/reason-codes.d.ts +2 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +4 -1
- package/dist/workspace/releases.d.ts +72 -0
- package/dist/workspace/releases.d.ts.map +1 -0
- package/dist/workspace/releases.js +94 -0
- package/dist/workspace/releases.schema.json +391 -0
- package/dist/workspace/run-event.schema.json +288 -0
- package/dist/workspace/status-gates.d.ts +26 -1
- package/dist/workspace/status-gates.d.ts.map +1 -1
- package/dist/workspace/status-gates.js +31 -2
- package/dist/workspace/status-stewards.d.ts +4 -0
- package/dist/workspace/status-stewards.d.ts.map +1 -1
- package/dist/workspace/status-stewards.js +2 -0
- package/dist/workspace/status.d.ts +39 -0
- package/dist/workspace/status.d.ts.map +1 -1
- package/dist/workspace/status.js +48 -1
- package/dist/workspace/status.schema.json +70 -1
- package/dist/workspace/trust/ci-tag-statement.d.ts +102 -0
- package/dist/workspace/trust/ci-tag-statement.d.ts.map +1 -0
- package/dist/workspace/trust/ci-tag-statement.js +123 -0
- package/dist/workspace/trust/op-run-statement.d.ts +91 -0
- package/dist/workspace/trust/op-run-statement.d.ts.map +1 -0
- package/dist/workspace/trust/op-run-statement.js +143 -0
- package/dist/workspace/trust/rotation.d.ts +18 -2
- package/dist/workspace/trust/rotation.d.ts.map +1 -1
- package/dist/workspace/trust/rotation.js +65 -16
- package/dist/workspace/trust/seal.d.ts +11 -0
- package/dist/workspace/trust/seal.d.ts.map +1 -1
- package/dist/workspace/trust/seal.js +9 -0
- package/dist/workspace/trust/ssh-commit.d.ts.map +1 -1
- package/dist/workspace/trust/ssh-commit.js +10 -10
- package/package.json +1 -1
- package/src/__golden__/wave-loop/fan-out-gated.json +8 -0
- package/src/__golden__/wave-loop/fan-out-no-members.json +4 -0
- package/src/__golden__/wave-loop/fan-out-only.json +6 -0
- package/src/__golden__/wave-loop/op-by-apply-hold.json +2 -0
- package/src/__golden__/wave-loop/op-cost-member.json +3 -0
- package/src/__golden__/wave-loop/op-held-on-before-apply.json +1 -0
- package/src/__golden__/wave-loop/op-held-on.json +2 -0
- package/src/__golden__/wave-loop/op-hooks-held.json +2 -0
- package/src/__golden__/wave-loop/op-hooks-hold-before-apply.json +2 -0
- package/src/__golden__/wave-loop/op-hooks-refused-at-base.json +3 -0
- package/src/__golden__/wave-loop/op-hooks-share.json +3 -0
- package/src/__golden__/wave-loop/op-per-run.json +7 -0
- package/src/__golden__/wave-loop/op-pr-review.json +7 -0
- package/src/__golden__/wave-loop/op-sealed.json +3 -0
- package/src/__golden__/wave-loop/op-spend.json +3 -0
- package/src/__golden__/wave-loop/op-wave-commands.json +7 -0
- package/src/__golden__/wave-loop/op-wide-waiting.json +4 -0
- package/src/change-set-graph.test.ts +72 -0
- package/src/change-set-graph.ts +133 -0
- package/src/change-set.ts +76 -6
- package/src/chant-version.ts +16 -0
- package/src/cli/commands/build.ts +19 -8
- package/src/cli/commands/check-lexicon-docs.test.ts +51 -0
- package/src/cli/commands/check-lexicon-docs.ts +39 -2
- package/src/cli/commands/check-lexicon.ts +14 -2
- package/src/cli/commands/init-lexicon/templates/docs.ts +7 -6
- package/src/cli/commands/init-lexicon.test.ts +25 -0
- package/src/cli/commands/init-lexicon.ts +18 -8
- package/src/cli/compiled-cli.e2e.test.ts +31 -6
- package/src/cli/handlers/approve-release.test.ts +80 -0
- package/src/cli/handlers/approve.ts +18 -2
- package/src/cli/handlers/build.test.ts +52 -0
- package/src/cli/handlers/build.ts +29 -0
- package/src/cli/handlers/change-set.ts +49 -1
- package/src/cli/handlers/fan-out.test.ts +48 -0
- package/src/cli/handlers/fan-out.ts +15 -3
- package/src/cli/handlers/operator.test.ts +37 -0
- package/src/cli/handlers/pr.test.ts +194 -0
- package/src/cli/handlers/pr.ts +168 -34
- package/src/cli/handlers/promote.test.ts +389 -5
- package/src/cli/handlers/promote.ts +279 -20
- package/src/cli/handlers/release-implicit.e2e.test.ts +153 -0
- package/src/cli/handlers/release.e2e.test.ts +85 -0
- package/src/cli/handlers/release.ts +206 -0
- package/src/cli/handlers/run-auto-release.test.ts +71 -0
- package/src/cli/handlers/run-events-cmd.test.ts +92 -0
- package/src/cli/handlers/run.test.ts +30 -0
- package/src/cli/handlers/run.ts +176 -15
- package/src/cli/main.test.ts +7 -0
- package/src/cli/main.ts +88 -13
- package/src/cli/mcp/never-over-mcp.test.ts +2 -0
- package/src/cli/mcp/workspace-tools.ts +1 -1
- package/src/cli/parse-args.ts +37 -3
- package/src/cli/registry.ts +29 -3
- package/src/cli/run-events.ts +54 -0
- package/src/cli/version.ts +3 -13
- package/src/codegen/docs-in-site.test.ts +166 -0
- package/src/codegen/docs-in-site.ts +182 -0
- package/src/codegen/docs-site/AgentPrompt.astro +26 -1
- package/src/codegen/docs-types.ts +14 -1
- package/src/codegen/docs.ts +60 -7
- package/src/codegen/rehype-base-url.d.mts +3 -1
- package/src/codegen/rehype-base-url.mjs +15 -9
- package/src/codegen/rehype-base-url.test.ts +34 -0
- package/src/components/auto-release.test.ts +21 -0
- package/src/components/auto-release.ts +6 -1
- package/src/components/cli-support.test.ts +82 -0
- package/src/components/cli-support.ts +16 -9
- package/src/components/driver.ts +129 -56
- package/src/components/fan-out-run.ts +56 -35
- package/src/components/pr-run.ts +30 -1
- package/src/components/promote-order.test.ts +90 -0
- package/src/components/promote-order.ts +75 -0
- package/src/components/promote.test.ts +10 -1
- package/src/components/promote.ts +26 -1
- package/src/components/release-compile.test.ts +147 -0
- package/src/components/release-compile.ts +445 -0
- package/src/components/release-gate.test.ts +215 -0
- package/src/components/release-gate.ts +341 -0
- package/src/components/release-promote.test.ts +159 -0
- package/src/components/release-promote.ts +232 -0
- package/src/components/run-progress.ts +7 -0
- package/src/components/wave-plan.ts +1 -1
- package/src/config.ts +7 -1
- package/src/index.ts +2 -0
- package/src/lifecycle/change-set-store.test.ts +217 -0
- package/src/lifecycle/change-set-store.ts +112 -0
- package/src/lifecycle/commit-sha.ts +23 -0
- package/src/lifecycle/gate-change-set.e2e.test.ts +122 -0
- package/src/lifecycle/gate-change-set.ts +133 -0
- package/src/lifecycle/gate-ledger.test.ts +33 -0
- package/src/lifecycle/gate-ledger.ts +66 -1
- package/src/lifecycle/release-cut-signed.test.ts +180 -0
- package/src/lifecycle/release-cut.test.ts +411 -0
- package/src/lifecycle/release-cut.ts +367 -0
- package/src/lifecycle/release-ledger.test.ts +14 -0
- package/src/lifecycle/release-ledger.ts +85 -17
- package/src/lifecycle/release-store.ts +423 -0
- package/src/lifecycle/run-ledger.test.ts +10 -0
- package/src/lifecycle/run-ledger.ts +6 -0
- package/src/op/activities/change-coverage.ts +4 -1
- package/src/op/activities/source-release.ts +8 -3
- package/src/op/activities/source-rollback.ts +8 -4
- package/src/op/activity-registry.ts +7 -5
- package/src/op/commit-run-gate-deploy-join.test.ts +117 -0
- package/src/op/discover-root.test.ts +39 -0
- package/src/op/discover.ts +15 -8
- package/src/op/gate-name.ts +13 -3
- package/src/op/gate-release.test.ts +126 -0
- package/src/op/gate-run-locator.test.ts +110 -0
- package/src/op/gate-run-locator.ts +35 -0
- package/src/op/gate.ts +88 -6
- package/src/op/local-executor.ts +207 -52
- package/src/op/op-waves-run.ts +4 -0
- package/src/op/run-events.test.ts +166 -0
- package/src/op/run-live.ts +1 -1
- package/src/op/runtime.ts +39 -0
- package/src/op/runtimes/local.test.ts +16 -0
- package/src/op/runtimes/local.ts +13 -2
- package/src/point-decision.ts +12 -2
- package/src/run-event-store.test.ts +144 -0
- package/src/run-event-store.ts +213 -0
- package/src/run-event-stream.test.ts +175 -0
- package/src/run-event-stream.ts +306 -0
- package/src/run-event.test.ts +277 -0
- package/src/run-event.ts +451 -0
- package/src/wave-loop-golden.test.ts +9 -0
- package/src/workspace/__fixtures__/run-event-check.ts +58 -0
- package/src/workspace/ancestry-index.test.ts +93 -0
- package/src/workspace/change-set-show.schema.json +102 -0
- package/src/workspace/change-set-show.ts +72 -0
- package/src/workspace/change-set.schema.json +28 -1
- package/src/workspace/changes-cli.ts +10 -1
- package/src/workspace/changes.schema.json +135 -0
- package/src/workspace/changes.test.ts +1 -1
- package/src/workspace/changes.ts +84 -2
- package/src/workspace/ci-green-cli.ts +75 -13
- package/src/workspace/ci-green-forge.ts +24 -4
- package/src/workspace/ci-green-runs.test.ts +242 -0
- package/src/workspace/ci-green-signed.test.ts +302 -0
- package/src/workspace/ci-green-workflow.test.ts +16 -0
- package/src/workspace/ci-green-workflow.ts +12 -0
- package/src/workspace/ci-green.test.ts +131 -2
- package/src/workspace/ci-green.ts +624 -42
- package/src/workspace/ci-last-green.schema.json +32 -2
- package/src/workspace/ci-list.schema.json +525 -0
- package/src/workspace/commit-links.test.ts +279 -0
- package/src/workspace/commit-links.ts +183 -0
- package/src/workspace/declaration.schema.json +12 -0
- package/src/workspace/declaration.ts +22 -2
- package/src/workspace/identity-gate-rule.ts +91 -7
- package/src/workspace/identity.ts +14 -1
- package/src/workspace/intent.ts +48 -1
- package/src/workspace/ls.schema.json +3 -1
- package/src/workspace/ls.ts +6 -0
- package/src/workspace/member-pipeline.test.ts +17 -0
- package/src/workspace/member-pipeline.ts +9 -0
- package/src/workspace/promotion-order.ts +97 -0
- package/src/workspace/read-contract.e2e.test.ts +4 -1
- package/src/workspace/reason-codes.test.ts +2 -1
- package/src/workspace/reason-codes.ts +4 -1
- package/src/workspace/releases.schema.json +391 -0
- package/src/workspace/releases.test.ts +108 -0
- package/src/workspace/releases.ts +122 -0
- package/src/workspace/run-event.schema.json +288 -0
- package/src/workspace/status-contract.test.ts +52 -1
- package/src/workspace/status-gates.ts +56 -1
- package/src/workspace/status-stewards.ts +6 -0
- package/src/workspace/status.schema.json +70 -1
- package/src/workspace/status.ts +80 -1
- package/src/workspace/trust/ci-tag-statement.ts +151 -0
- package/src/workspace/trust/op-run-statement.ts +148 -0
- package/src/workspace/trust/rotation.ts +61 -14
- package/src/workspace/trust/seal.ts +10 -0
- package/src/workspace/trust/ssh-commit.ts +10 -9
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/astro.config.mjs +0 -14
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/package.json +0 -16
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/src/content/docs/index.mdx +0 -8
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/src/content.config.ts +0 -15
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/tsconfig.json +0 -10
package/src/cli/registry.ts
CHANGED
|
@@ -72,6 +72,16 @@ export interface ParsedArgs {
|
|
|
72
72
|
* unchanged; omitted (undefined, not false) when the flag isn't passed.
|
|
73
73
|
*/
|
|
74
74
|
progressJson?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* `--events-json` (#4041) — stream the run's events to stdout, one
|
|
77
|
+
* `run-event.schema.json` line each (`../../run-event.ts`), on `chant run
|
|
78
|
+
* <op>`, `chant run --components`, `components promote|rollback|redeploy`,
|
|
79
|
+
* `components fan-out` and `components pr-plan|pr-apply`. Refused beside
|
|
80
|
+
* `--progress-json`, which prints the older shapes to the same stdout.
|
|
81
|
+
*/
|
|
82
|
+
eventsJson?: boolean;
|
|
83
|
+
/** `chant run events <run> --follow` (#4042) — stream the run's events as they happen, until `run-settle`. */
|
|
84
|
+
follow?: boolean;
|
|
75
85
|
live: boolean;
|
|
76
86
|
/** `chant migrate --from <name>` (default "github") */
|
|
77
87
|
migrateFrom?: string;
|
|
@@ -137,6 +147,8 @@ export interface ParsedArgs {
|
|
|
137
147
|
namespace?: string;
|
|
138
148
|
/** `chant workspace upgrade --allow-code` (#2550) — run migrations whose body is the template's own code. */
|
|
139
149
|
allowCode?: boolean;
|
|
150
|
+
/** `chant components promote --allow-skip` (#4030): promote past a step of the member's declared promotion order. */
|
|
151
|
+
allowSkip?: boolean;
|
|
140
152
|
/** `chant workspace upgrade --source <repo>[#<member>]` (#2551): move the scope to another template. */
|
|
141
153
|
source?: string;
|
|
142
154
|
/** `chant workspace adopt-lineage --tags <glob>` and `hash-index --tags` (#2551): the tags to compare. */
|
|
@@ -160,15 +172,21 @@ export interface ParsedArgs {
|
|
|
160
172
|
verbatim?: boolean;
|
|
161
173
|
/** `chant import --skip-undeclarable` — import what can be declared and warn about the live objects that cannot, instead of failing */
|
|
162
174
|
skipUndeclarable?: boolean;
|
|
163
|
-
/** `chant lifecycle … --src <dir>` — build root override for lifecycle commands */
|
|
175
|
+
/** `chant lifecycle … --src <dir>` — build root override for lifecycle commands. Also `chant release cut --src <dir>` (#4046): the build root of a project with no components. */
|
|
164
176
|
src?: string;
|
|
165
177
|
/** `--env <name>` — active environment: sets CHANT_ENV so env-aware source
|
|
166
178
|
* re-evaluates for that environment (`build` + `graph`), and drives policy. */
|
|
167
179
|
env?: string;
|
|
168
180
|
/** `chant emulator up --port <container-port>=<host-port>`, repeatable (#3673); a bare `<host-port>` when one emulator is selected. */
|
|
169
181
|
port?: string[];
|
|
170
|
-
/**
|
|
182
|
+
/**
|
|
183
|
+
* `chant emulator up --image <ref>` (#3952): the image to start, when one
|
|
184
|
+
* emulator is selected. `chant build --components --generate --image <ref>`
|
|
185
|
+
* (#4002): the image every generated job runs in.
|
|
186
|
+
*/
|
|
171
187
|
image?: string;
|
|
188
|
+
/** `chant build --components --generate --before-script <line>`, repeatable (#4002): shell lines every generated job runs before its command. */
|
|
189
|
+
beforeScript?: string[];
|
|
172
190
|
/** `chant emulator up --network <name>` (#3952): the Docker network each started container joins. */
|
|
173
191
|
network?: string;
|
|
174
192
|
/** `chant emulator up --setting <KEY>=<VALUE>`, repeatable (#3952): an emulator setting such as `FLOCI_<NAME>`, passed as `-e`. */
|
|
@@ -434,6 +452,8 @@ export interface ParsedArgs {
|
|
|
434
452
|
ciAppIdVar?: string;
|
|
435
453
|
/** `chant ci workflow --app-key-secret <NAME>` (#3573): the secret holding that App's private key. */
|
|
436
454
|
ciAppKeySecret?: string;
|
|
455
|
+
/** `chant ci workflow --runner-key-secret <NAME>` (#4031): the secret holding the runner key the tick signs its tags with. */
|
|
456
|
+
ciRunnerKeySecret?: string;
|
|
437
457
|
/**
|
|
438
458
|
* `chant workspace records review <id> --by <principal>` (#2670): the
|
|
439
459
|
* reviewer, as the caller names them. Also `chant workspace records new
|
|
@@ -460,7 +480,7 @@ export interface ParsedArgs {
|
|
|
460
480
|
prefix?: string;
|
|
461
481
|
/** `chant workspace records|verify --require attested` (#2547): the provenance level a gate requires. */
|
|
462
482
|
require?: string;
|
|
463
|
-
/** `chant workspace evidence sign --key` (a runner's Ed25519 PEM) and `signers sign --key` (an ssh private key) (#2553). */
|
|
483
|
+
/** `chant workspace evidence sign --key` (a runner's Ed25519 PEM) and `signers sign --key` (an ssh private key) (#2553). Also `chant ci tick --key` (#4031): the runner key the tick signs its tags with. */
|
|
464
484
|
key?: string;
|
|
465
485
|
/** `chant workspace evidence sign --check-id <id>` (#2553): the check the evidence is for. */
|
|
466
486
|
checkId?: string;
|
|
@@ -541,6 +561,12 @@ export interface ParsedArgs {
|
|
|
541
561
|
digest?: string;
|
|
542
562
|
/** `chant components release record --release-plan <file>` (ws-055, #2733) — path to a release plan JSON file, persisted content-addressed to `_plans/<digest>.json` on chant/lifecycle and read back through the read contract (`chant workspace status --json`). The plan's own `digest` field supplies `--digest` when it is omitted, and must match it when both are given. Distinct from `--plan` (#2300, below), the Op gate-approval plan digest. */
|
|
543
563
|
releasePlanFile?: string;
|
|
564
|
+
/** `chant components promote --release <label|digest>` (#4026): deploy under that release, reading the templates its target for `--to` recorded. */
|
|
565
|
+
release?: string;
|
|
566
|
+
/** `chant release cut --build <command>` (#4026): the shell command run in the member's directory before each environment's templates are read, with `CHANT_ENV` set to the environment. */
|
|
567
|
+
buildCommand?: string;
|
|
568
|
+
/** `chant release compile --artifacts` (#4026, internal): build the artifacts of `--component` instead of compiling the environment. */
|
|
569
|
+
artifacts?: boolean;
|
|
544
570
|
/** Every `--digest` value, in order (#2602). `chant components promote --digest <component>=<sha256:...>` is repeatable, one per component; the other commands read the single {@link digest}. */
|
|
545
571
|
digests?: string[];
|
|
546
572
|
/** `chant components release record --git-sha <sha>` (#568) — git commit the deploy was built from. */
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `--events-json` (#4041): a command's run-event stream on stdout, one
|
|
3
|
+
* `run-event.schema.json` line per event, also kept on this host for replay
|
|
4
|
+
* (#4042, `../run-event-store.ts`). Shared by `chant run`, the
|
|
5
|
+
* components commands that deploy (promote, rollback, redeploy, fan-out) and
|
|
6
|
+
* the pull-request loop (pr-plan, pr-apply).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { formatError } from "./format";
|
|
10
|
+
import { openRunEventStore, teeLines } from "../run-event-store";
|
|
11
|
+
import { openRunEventStream, resolveRunEventRun, type RunEventStream } from "../run-event-stream";
|
|
12
|
+
import type { RunEventKind } from "../run-event";
|
|
13
|
+
import type { ParsedArgs } from "./registry";
|
|
14
|
+
|
|
15
|
+
/** Refuse `--events-json` beside `--progress-json`: both print to stdout. Returns true after printing why. */
|
|
16
|
+
export function refusesBothStreams(args: Pick<ParsedArgs, "eventsJson" | "progressJson">): boolean {
|
|
17
|
+
if (!args.eventsJson || !args.progressJson) return false;
|
|
18
|
+
console.error(formatError({
|
|
19
|
+
message: "--events-json and --progress-json both stream to stdout",
|
|
20
|
+
hint: "Pass one. --events-json prints the run-event stream; --progress-json prints the older progress lines.",
|
|
21
|
+
}));
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Refuse `--events-json` beside `--json` where `--json` prints a report to stdout (pr-plan, pr-apply). Returns true after printing why. */
|
|
26
|
+
export function refusesEventsWithJson(args: Pick<ParsedArgs, "eventsJson" | "json">, report: string): boolean {
|
|
27
|
+
if (!args.eventsJson || !args.json) return false;
|
|
28
|
+
console.error(formatError({
|
|
29
|
+
message: "--events-json and --json both stream to stdout",
|
|
30
|
+
hint: `Pass one. --events-json prints the run-event stream; --json prints ${report}.`,
|
|
31
|
+
}));
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Writes one line to stdout. */
|
|
36
|
+
export const stdoutLine = (line: string): void => void process.stdout.write(line);
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The run's stream on stdout when `--events-json` was passed, else
|
|
40
|
+
* undefined. The run is named by `runId` when the caller has one (so a
|
|
41
|
+
* release record and the stream name the same run), else by the CI run or a
|
|
42
|
+
* local id.
|
|
43
|
+
*/
|
|
44
|
+
export async function openCliRunEvents(
|
|
45
|
+
args: Pick<ParsedArgs, "eventsJson">,
|
|
46
|
+
run: { kind: RunEventKind; name: string; runId?: string; cwd?: string },
|
|
47
|
+
): Promise<RunEventStream | undefined> {
|
|
48
|
+
if (!args.eventsJson) return undefined;
|
|
49
|
+
const resolved = await resolveRunEventRun(run);
|
|
50
|
+
// #4042: the stream is also kept on this host, so `chant run events <run>`
|
|
51
|
+
// replays it. Only a command that was asked for a stream keeps one.
|
|
52
|
+
const store = await openRunEventStore(run.cwd ?? process.cwd(), resolved.runId);
|
|
53
|
+
return openRunEventStream(resolved, teeLines(stdoutLine, store?.write.bind(store))!);
|
|
54
|
+
}
|
package/src/cli/version.ts
CHANGED
|
@@ -1,15 +1,5 @@
|
|
|
1
|
-
import { createRequire } from "node:module";
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
|
-
* The installed chant's version
|
|
5
|
-
*
|
|
6
|
-
* `src/cli/` and `dist/cli/`, so it holds whether chant runs from source or
|
|
7
|
-
* from its build.
|
|
2
|
+
* The installed chant's version. It lives in `../chant-version.ts`, outside
|
|
3
|
+
* `cli/`, so the Op entry can name it without loading the CLI (#4041).
|
|
8
4
|
*/
|
|
9
|
-
export
|
|
10
|
-
try {
|
|
11
|
-
return (createRequire(import.meta.url)("../../package.json") as { version?: string }).version ?? "0.0.0";
|
|
12
|
-
} catch {
|
|
13
|
-
return "0.0.0";
|
|
14
|
-
}
|
|
15
|
-
})();
|
|
5
|
+
export { CHANT_VERSION } from "../chant-version";
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
2
|
+
import { tmpdir } from "os";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
|
5
|
+
|
|
6
|
+
import { docsPipeline, writeDocsSite } from "./docs";
|
|
7
|
+
import { DOCS_SITE_DEPENDENCIES, findChantDocsSite, rebaseImports, resolveDocsMode } from "./docs-in-site";
|
|
8
|
+
import type { DocsConfig } from "./docs-types";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* chant #3993: inside the chant repository a lexicon's docs are a section of
|
|
12
|
+
* the main Starlight site. These run against a fake repository (a `docs/`
|
|
13
|
+
* whose package.json is the chant docs package) with one lexicon under it.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
let repo: string;
|
|
17
|
+
let lex: string;
|
|
18
|
+
|
|
19
|
+
function config(overrides: Partial<DocsConfig> = {}): DocsConfig {
|
|
20
|
+
return {
|
|
21
|
+
name: "fixture",
|
|
22
|
+
displayName: "Fixture",
|
|
23
|
+
description: "fixture lexicon",
|
|
24
|
+
distDir: join(lex, "dist"),
|
|
25
|
+
outDir: join(lex, "docs"),
|
|
26
|
+
srcDir: join(lex, "src"),
|
|
27
|
+
basePath: "/chant/lexicons/fixture/",
|
|
28
|
+
...overrides,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function page(name: string, frontmatter: string, body = "Body.\n"): void {
|
|
33
|
+
mkdirSync(join(lex, "docs", "pages"), { recursive: true });
|
|
34
|
+
writeFileSync(join(lex, "docs", "pages", name), `---\n${frontmatter}\n---\n\n${body}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const section = () => join(repo, "docs", "src", "content", "docs", "lexicons", "fixture");
|
|
38
|
+
|
|
39
|
+
beforeEach(() => {
|
|
40
|
+
vi.stubEnv("CHANT_DOCS_MODE", "");
|
|
41
|
+
vi.stubEnv("CHANT_DOCS_SITE", "");
|
|
42
|
+
repo = mkdtempSync(join(tmpdir(), "chant-docs-in-site-"));
|
|
43
|
+
mkdirSync(join(repo, "docs"), { recursive: true });
|
|
44
|
+
writeFileSync(join(repo, "docs", "package.json"), JSON.stringify({ name: "@intentius/chant-docs" }));
|
|
45
|
+
writeFileSync(join(repo, "docs", "astro.config.mjs"), "export default {};\n");
|
|
46
|
+
lex = join(repo, "lexicons", "fixture");
|
|
47
|
+
mkdirSync(join(lex, "dist"), { recursive: true });
|
|
48
|
+
mkdirSync(join(lex, "src"), { recursive: true });
|
|
49
|
+
writeFileSync(
|
|
50
|
+
join(lex, "dist", "manifest.json"),
|
|
51
|
+
JSON.stringify({ name: "fixture", version: "0.0.0", intrinsics: [{ name: "ref", description: "a ref" }] }),
|
|
52
|
+
);
|
|
53
|
+
writeFileSync(join(lex, "dist", "meta.json"), JSON.stringify({}));
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
afterEach(() => {
|
|
57
|
+
vi.unstubAllEnvs();
|
|
58
|
+
rmSync(repo, { recursive: true, force: true });
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe("which mode writeDocsSite runs in", () => {
|
|
62
|
+
test("a lexicon inside the chant repository goes in-site", () => {
|
|
63
|
+
expect(findChantDocsSite(lex)).toBe(join(repo, "docs"));
|
|
64
|
+
expect(resolveDocsMode(config())).toEqual({ mode: "in-site", siteDir: join(repo, "docs") });
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("a docs site that is not chant's does not count", () => {
|
|
68
|
+
writeFileSync(join(repo, "docs", "package.json"), JSON.stringify({ name: "someone-elses-docs" }));
|
|
69
|
+
expect(findChantDocsSite(lex)).toBeUndefined();
|
|
70
|
+
expect(resolveDocsMode(config()).mode).toBe("standalone");
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test("config.mode and CHANT_DOCS_MODE override the detection", () => {
|
|
74
|
+
expect(resolveDocsMode(config({ mode: "standalone" })).mode).toBe("standalone");
|
|
75
|
+
vi.stubEnv("CHANT_DOCS_MODE", "standalone");
|
|
76
|
+
expect(resolveDocsMode(config()).mode).toBe("standalone");
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("in-site mode with no main site to write into is an error", () => {
|
|
80
|
+
rmSync(join(repo, "docs"), { recursive: true });
|
|
81
|
+
expect(() => resolveDocsMode(config({ mode: "in-site" }))).toThrow(/in-site mode needs the chant docs site/);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe("in-site mode", () => {
|
|
86
|
+
test("writes pages and a sidebar fragment into the main site, and no app files", () => {
|
|
87
|
+
page("start.mdx", "title: Start\ndiataxis: tutorial");
|
|
88
|
+
page("secret.mdx", "title: Secret\ndiataxis: reference\nhidden: true");
|
|
89
|
+
const cfg = config();
|
|
90
|
+
writeDocsSite(cfg, docsPipeline(cfg));
|
|
91
|
+
|
|
92
|
+
for (const f of ["index.mdx", "start.mdx", "secret.mdx", "intrinsics.mdx", "serialization.mdx"]) {
|
|
93
|
+
expect(existsSync(join(section(), f)), f).toBe(true);
|
|
94
|
+
}
|
|
95
|
+
for (const f of ["package.json", "astro.config.mjs", "tsconfig.json", "src"]) {
|
|
96
|
+
expect(existsSync(join(lex, "docs", f)), f).toBe(false);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const fragment = JSON.parse(readFileSync(join(section(), "_sidebar.json"), "utf-8"));
|
|
100
|
+
expect(fragment.hidden).toEqual(["lexicons/fixture/secret"]);
|
|
101
|
+
expect(fragment.group.label).toBe("Fixture");
|
|
102
|
+
expect(fragment.group.collapsed).toBe(true);
|
|
103
|
+
expect(fragment.group.items.map((i: { label: string }) => i.label)).toEqual(["Overview", "Tutorials", "Reference"]);
|
|
104
|
+
expect(fragment.group.items[0]).toEqual({ label: "Overview", slug: "lexicons/fixture" });
|
|
105
|
+
expect(fragment.group.items[1]).toEqual({
|
|
106
|
+
label: "Tutorials",
|
|
107
|
+
collapsed: true,
|
|
108
|
+
items: [{ label: "Start", slug: "lexicons/fixture/start" }],
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test("generated reference tables get the diataxis field their sidebar group names", () => {
|
|
113
|
+
const cfg = config();
|
|
114
|
+
writeDocsSite(cfg, docsPipeline(cfg));
|
|
115
|
+
expect(readFileSync(join(section(), "intrinsics.mdx"), "utf-8")).toMatch(/^---\n[\s\S]*\ndiataxis: reference\n---/);
|
|
116
|
+
expect(readFileSync(join(section(), "index.mdx"), "utf-8")).not.toContain("diataxis:");
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test("a page the pipeline stops emitting is gone after the next run", () => {
|
|
120
|
+
page("start.mdx", "title: Start\ndiataxis: tutorial");
|
|
121
|
+
const cfg = config();
|
|
122
|
+
writeDocsSite(cfg, docsPipeline(cfg));
|
|
123
|
+
rmSync(join(lex, "docs", "pages", "start.mdx"));
|
|
124
|
+
writeDocsSite(cfg, docsPipeline(cfg));
|
|
125
|
+
expect(existsSync(join(section(), "start.mdx"))).toBe(false);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test("a page's import of the app's Diagram component points at the main site's", () => {
|
|
129
|
+
page("concepts.mdx", "title: Concepts\ndiataxis: explanation", "import Diagram from '../../components/Diagram.astro';\n\n<Diagram name=\"x\" alt=\"x\" />\n");
|
|
130
|
+
const cfg = config();
|
|
131
|
+
writeDocsSite(cfg, docsPipeline(cfg));
|
|
132
|
+
expect(readFileSync(join(section(), "concepts.mdx"), "utf-8")).toContain(
|
|
133
|
+
"import Diagram from '../../../../components/Diagram.astro';",
|
|
134
|
+
);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
describe("rebaseImports", () => {
|
|
139
|
+
test("re-points relative imports and leaves code fences and packages alone", () => {
|
|
140
|
+
const outDir = "/r/lexicons/x/docs";
|
|
141
|
+
const pageDir = "/r/docs/src/content/docs/lexicons/x";
|
|
142
|
+
const src = [
|
|
143
|
+
"import { Aside } from '@astrojs/starlight/components';",
|
|
144
|
+
"import raw from '../../../../examples/a.ts?raw';",
|
|
145
|
+
"```ts",
|
|
146
|
+
"import { y } from '../src/y';",
|
|
147
|
+
"```",
|
|
148
|
+
].join("\n");
|
|
149
|
+
expect(rebaseImports(src, { outDir, siteDir: "/r/docs", pageDir }).split("\n")).toEqual([
|
|
150
|
+
"import { Aside } from '@astrojs/starlight/components';",
|
|
151
|
+
"import raw from '../../../../../../lexicons/x/examples/a.ts?raw';",
|
|
152
|
+
"```ts",
|
|
153
|
+
"import { y } from '../src/y';",
|
|
154
|
+
"```",
|
|
155
|
+
]);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
describe("standalone docs app pins", () => {
|
|
160
|
+
test("match the main docs site's Starlight and Astro", () => {
|
|
161
|
+
const docsPkg = JSON.parse(readFileSync(join(import.meta.dirname, "..", "..", "..", "..", "docs", "package.json"), "utf-8"));
|
|
162
|
+
for (const dep of ["@astrojs/starlight", "astro", "sharp"]) {
|
|
163
|
+
expect(DOCS_SITE_DEPENDENCIES[dep], dep).toBe(docsPkg.dependencies[dep]);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
});
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The in-site mode of the lexicon docs pipeline (chant #3993).
|
|
3
|
+
*
|
|
4
|
+
* Inside the chant repository every lexicon's docs are a section of the main
|
|
5
|
+
* Starlight site in `docs/`: one Astro build, one search index, one design.
|
|
6
|
+
* `writeDocsSite` writes a lexicon's pages to
|
|
7
|
+
* `docs/src/content/docs/lexicons/<name>/` and, beside them, `_sidebar.json`,
|
|
8
|
+
* the lexicon's collapsed sidebar group with its Diátaxis subgroups. The main
|
|
9
|
+
* site's `astro.config.mjs` reads every fragment through
|
|
10
|
+
* `docs/src/lexicon-sidebar.mjs`. Nothing else is written: no package.json, no
|
|
11
|
+
* Astro config, no components.
|
|
12
|
+
*
|
|
13
|
+
* Outside the repository (a third-party lexicon, a project scaffolded by
|
|
14
|
+
* `chant init-lexicon`) the pipeline keeps writing a standalone Starlight app
|
|
15
|
+
* into the lexicon's own `docs/`, as it always has.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { existsSync, readFileSync } from "fs";
|
|
19
|
+
import { dirname, join, relative, resolve, sep } from "path";
|
|
20
|
+
|
|
21
|
+
import { QUADRANT_LABELS, QUADRANTS } from "./docs-pages";
|
|
22
|
+
import { quadrantItems } from "./docs-sidebar";
|
|
23
|
+
import type { DocsConfig, DocsResult, Quadrant, SidebarPage } from "./docs-types";
|
|
24
|
+
|
|
25
|
+
export type DocsSiteMode = "in-site" | "standalone";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The dependencies a standalone lexicon docs app installs. They match
|
|
29
|
+
* `docs/package.json`, so a lexicon built on its own renders with the same
|
|
30
|
+
* Starlight and Astro as the main site; a test holds the two together.
|
|
31
|
+
*/
|
|
32
|
+
export const DOCS_SITE_DEPENDENCIES: Readonly<Record<string, string>> = {
|
|
33
|
+
"@astrojs/starlight": "^0.37.6",
|
|
34
|
+
astro: "5.6.1",
|
|
35
|
+
sharp: "^0.34.2",
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/** Package name of the main docs site, `docs/package.json` in the chant repository. */
|
|
39
|
+
const CHANT_DOCS_PACKAGE = "@intentius/chant-docs";
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The chant repository's main docs site (`<repo>/docs`) above `start`, or
|
|
43
|
+
* undefined. A directory qualifies when its `docs/package.json` is the chant
|
|
44
|
+
* docs package and `docs/astro.config.mjs` exists beside it, so a third-party
|
|
45
|
+
* repository with a docs site of its own is never mistaken for chant.
|
|
46
|
+
*/
|
|
47
|
+
export function findChantDocsSite(start: string): string | undefined {
|
|
48
|
+
let dir = resolve(start);
|
|
49
|
+
for (;;) {
|
|
50
|
+
const docs = join(dir, "docs");
|
|
51
|
+
const pkg = join(docs, "package.json");
|
|
52
|
+
if (existsSync(pkg) && existsSync(join(docs, "astro.config.mjs"))) {
|
|
53
|
+
try {
|
|
54
|
+
if ((JSON.parse(readFileSync(pkg, "utf-8")) as { name?: unknown }).name === CHANT_DOCS_PACKAGE) return docs;
|
|
55
|
+
} catch {
|
|
56
|
+
// Not JSON: not chant's docs site. Keep walking.
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const parent = dirname(dir);
|
|
60
|
+
if (parent === dir) return undefined;
|
|
61
|
+
dir = parent;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Which mode `writeDocsSite` runs in, and the main site's directory for
|
|
67
|
+
* in-site mode. `config.mode` wins, then `CHANT_DOCS_MODE`; with neither, a
|
|
68
|
+
* lexicon inside the chant repository goes in-site and any other standalone.
|
|
69
|
+
* `config.siteDir` or `CHANT_DOCS_SITE` names the main site when the walk up
|
|
70
|
+
* from `outDir` would not find it.
|
|
71
|
+
*/
|
|
72
|
+
export function resolveDocsMode(config: DocsConfig): { mode: DocsSiteMode; siteDir?: string } {
|
|
73
|
+
const env = process.env.CHANT_DOCS_MODE;
|
|
74
|
+
const requested = config.mode ?? (env === "in-site" || env === "standalone" ? env : undefined);
|
|
75
|
+
if (requested === "standalone") return { mode: "standalone" };
|
|
76
|
+
const siteDir = config.siteDir || process.env.CHANT_DOCS_SITE || findChantDocsSite(config.outDir);
|
|
77
|
+
if (requested === "in-site") {
|
|
78
|
+
if (!siteDir) {
|
|
79
|
+
throw new Error(
|
|
80
|
+
`[docs:${config.name}] in-site mode needs the chant docs site: none above ${resolve(config.outDir)}. ` +
|
|
81
|
+
`Set siteDir or CHANT_DOCS_SITE, or use standalone mode.`,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
return { mode: "in-site", siteDir: resolve(siteDir) };
|
|
85
|
+
}
|
|
86
|
+
return siteDir ? { mode: "in-site", siteDir: resolve(siteDir) } : { mode: "standalone" };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Where a lexicon's section lives inside the main site's content collection. */
|
|
90
|
+
export function sectionContentDir(siteDir: string, name: string): string {
|
|
91
|
+
return join(siteDir, "src", "content", "docs", "lexicons", name);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* The lexicon's sidebar group for the main site: the lexicon's display name,
|
|
96
|
+
* collapsed, holding its overview and one collapsed group per non-empty
|
|
97
|
+
* Diátaxis quadrant. Slugs are prefixed with `lexicons/<name>/`.
|
|
98
|
+
*/
|
|
99
|
+
export function buildSectionGroup(config: DocsConfig, result: DocsResult): Record<string, unknown> {
|
|
100
|
+
const prefix = `lexicons/${config.name}`;
|
|
101
|
+
const byQuadrant = new Map<Quadrant, SidebarPage[]>();
|
|
102
|
+
for (const page of result.sidebarPages) {
|
|
103
|
+
if (page.hidden) continue;
|
|
104
|
+
const list = byQuadrant.get(page.quadrant) ?? [];
|
|
105
|
+
list.push({ ...page, slug: `${prefix}/${page.slug}` });
|
|
106
|
+
byQuadrant.set(page.quadrant, list);
|
|
107
|
+
}
|
|
108
|
+
const items: Array<Record<string, unknown>> = [{ label: "Overview", slug: prefix }];
|
|
109
|
+
for (const q of QUADRANTS) {
|
|
110
|
+
const pages = byQuadrant.get(q);
|
|
111
|
+
if (!pages || pages.length === 0) continue;
|
|
112
|
+
items.push({ label: QUADRANT_LABELS[q], collapsed: true, items: collapseGroups(quadrantItems(pages)) });
|
|
113
|
+
}
|
|
114
|
+
return { label: config.displayName, collapsed: true, items };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Every nested group starts collapsed, as on the rest of the main site. */
|
|
118
|
+
function collapseGroups(items: Array<Record<string, unknown>>): Array<Record<string, unknown>> {
|
|
119
|
+
return items.map((item) =>
|
|
120
|
+
Array.isArray(item.items)
|
|
121
|
+
? { label: item.label, collapsed: true, items: collapseGroups(item.items as Array<Record<string, unknown>>) }
|
|
122
|
+
: item,
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Slugs of pages written but kept out of the sidebar, prefixed for the main site. */
|
|
127
|
+
export function hiddenSectionSlugs(config: DocsConfig, result: DocsResult): string[] {
|
|
128
|
+
const listed = new Set(result.sidebarPages.map((p) => p.slug));
|
|
129
|
+
return [...result.pages.keys()]
|
|
130
|
+
.map((f) => f.replace(/\.mdx?$/, ""))
|
|
131
|
+
.filter((slug) => slug !== "index" && !listed.has(slug))
|
|
132
|
+
.sort()
|
|
133
|
+
.map((slug) => `lexicons/${config.name}/${slug}`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Give a page the `diataxis` field of the quadrant the sidebar files it under,
|
|
138
|
+
* when it has none. Authored pages always carry one; the generated reference
|
|
139
|
+
* tables do not, and the main site's Diátaxis check reads the field.
|
|
140
|
+
*/
|
|
141
|
+
export function withQuadrant(content: string, quadrant: Quadrant | undefined): string {
|
|
142
|
+
if (!quadrant || !content.startsWith("---\n")) return content;
|
|
143
|
+
const end = content.indexOf("\n---", 4);
|
|
144
|
+
if (end === -1) return content;
|
|
145
|
+
if (/^diataxis:/m.test(content.slice(4, end))) return content;
|
|
146
|
+
return `${content.slice(0, end)}\ndiataxis: ${quadrant}${content.slice(end)}`;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const IMPORT_RE = /^(\s*import\s[^'"]*?\sfrom\s+|\s*import\s+)(['"])(\.\.?\/[^'"]+)\2(.*)$/;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Re-point a page's relative ESM imports from where the standalone app kept
|
|
153
|
+
* the page (`<outDir>/src/content/docs/`) to where the main site keeps it.
|
|
154
|
+
* An import of the app's own components (`<outDir>/src/components/X`) goes to
|
|
155
|
+
* the main site's `src/components/X`, which holds the one shared copy.
|
|
156
|
+
* Fenced code blocks are left alone; their `import` lines are examples.
|
|
157
|
+
*/
|
|
158
|
+
export function rebaseImports(content: string, opts: { outDir: string; siteDir: string; pageDir: string }): string {
|
|
159
|
+
const fromDir = join(resolve(opts.outDir), "src", "content", "docs");
|
|
160
|
+
const appComponents = join(resolve(opts.outDir), "src", "components") + sep;
|
|
161
|
+
const siteComponents = join(opts.siteDir, "src", "components");
|
|
162
|
+
let fence: string | null = null;
|
|
163
|
+
return content
|
|
164
|
+
.split("\n")
|
|
165
|
+
.map((line) => {
|
|
166
|
+
const marker = line.match(/^\s*(`{3,}|~{3,})/)?.[1];
|
|
167
|
+
if (marker) {
|
|
168
|
+
if (fence === null) fence = marker[0];
|
|
169
|
+
else if (marker[0] === fence) fence = null;
|
|
170
|
+
return line;
|
|
171
|
+
}
|
|
172
|
+
if (fence !== null) return line;
|
|
173
|
+
const m = line.match(IMPORT_RE);
|
|
174
|
+
if (!m) return line;
|
|
175
|
+
let target = resolve(fromDir, m[3]);
|
|
176
|
+
if (target.startsWith(appComponents)) target = join(siteComponents, target.slice(appComponents.length));
|
|
177
|
+
let spec = relative(opts.pageDir, target).split(sep).join("/");
|
|
178
|
+
if (!spec.startsWith(".")) spec = `./${spec}`;
|
|
179
|
+
return `${m[1]}${m[2]}${spec}${m[2]}${m[4]}`;
|
|
180
|
+
})
|
|
181
|
+
.join("\n");
|
|
182
|
+
}
|
|
@@ -6,14 +6,26 @@
|
|
|
6
6
|
// render it from their PageTitle override; lexicon sites get a copy of this
|
|
7
7
|
// file from writeDocsSite (docs.ts). The content schema refuses a prompt with
|
|
8
8
|
// no "Never" line. No Starlight import here, so the file works from any site.
|
|
9
|
+
// `text`, `label` and `note` replace the page's prompt and the caption (the
|
|
10
|
+
// main site's home page passes the setup prompt); an `icon` slot goes before
|
|
11
|
+
// the label (the main site passes its logo).
|
|
9
12
|
interface Props {
|
|
10
13
|
text?: string;
|
|
14
|
+
label?: string;
|
|
15
|
+
note?: string;
|
|
11
16
|
}
|
|
17
|
+
const {
|
|
18
|
+
label = 'Optional: hand this page to your coding agent',
|
|
19
|
+
note = 'The steps work by hand too.',
|
|
20
|
+
} = Astro.props;
|
|
12
21
|
const prompt = (Astro.props.text ?? Astro.locals.starlightRoute?.entry.data.prompt)?.trim();
|
|
13
22
|
---
|
|
14
23
|
{prompt && (
|
|
15
24
|
<figure class="chant-prompt not-content" id="agent-prompt">
|
|
16
|
-
<figcaption>
|
|
25
|
+
<figcaption>
|
|
26
|
+
<span class="label"><slot name="icon" />{label}</span>
|
|
27
|
+
{note && <span class="note">{note}</span>}
|
|
28
|
+
</figcaption>
|
|
17
29
|
<details>
|
|
18
30
|
<summary>
|
|
19
31
|
<pre class="peek" aria-hidden="true">{prompt}</pre>
|
|
@@ -69,11 +81,24 @@ const prompt = (Astro.props.text ?? Astro.locals.starlightRoute?.entry.data.prom
|
|
|
69
81
|
--chant-prompt-blue: #60a5fa;
|
|
70
82
|
}
|
|
71
83
|
figcaption {
|
|
84
|
+
display: flex;
|
|
85
|
+
flex-wrap: wrap;
|
|
86
|
+
align-items: baseline;
|
|
87
|
+
gap: 0.25rem 0.75rem;
|
|
72
88
|
padding: 0.7rem 1rem 0.4rem;
|
|
89
|
+
}
|
|
90
|
+
.label {
|
|
91
|
+
display: inline-flex;
|
|
92
|
+
align-items: center;
|
|
93
|
+
gap: 0.5rem;
|
|
73
94
|
font-size: 0.85rem;
|
|
74
95
|
font-weight: 600;
|
|
75
96
|
color: var(--sl-color-white);
|
|
76
97
|
}
|
|
98
|
+
.note {
|
|
99
|
+
font-size: 0.75rem;
|
|
100
|
+
color: var(--sl-color-gray-3);
|
|
101
|
+
}
|
|
77
102
|
summary {
|
|
78
103
|
display: block;
|
|
79
104
|
list-style: none;
|
|
@@ -38,8 +38,21 @@ export interface DocsConfig {
|
|
|
38
38
|
suppressPages?: string[];
|
|
39
39
|
/** Source directory for scanning rule files (defaults to srcDir sibling of distDir) */
|
|
40
40
|
srcDir?: string;
|
|
41
|
-
/** Base path for the generated Astro site (e.g. '/lexicons/aws/') */
|
|
41
|
+
/** Base path for the generated Astro site (e.g. '/lexicons/aws/'). Standalone mode only. */
|
|
42
42
|
basePath?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Where `writeDocsSite` writes (chant #3993). `in-site`: the lexicon's pages
|
|
45
|
+
* and sidebar fragment go into the chant repository's main docs site.
|
|
46
|
+
* `standalone`: a Starlight app of its own in `outDir`. Unset, the
|
|
47
|
+
* `CHANT_DOCS_MODE` environment variable decides, and without it a lexicon
|
|
48
|
+
* inside the chant repository goes in-site and any other standalone.
|
|
49
|
+
*/
|
|
50
|
+
mode?: "in-site" | "standalone";
|
|
51
|
+
/**
|
|
52
|
+
* The main docs site (`<chant repo>/docs`) for in-site mode. Defaults to
|
|
53
|
+
* `CHANT_DOCS_SITE`, then to the first one found walking up from `outDir`.
|
|
54
|
+
*/
|
|
55
|
+
siteDir?: string;
|
|
43
56
|
/** Root directory for resolving {{file:...}} markers in extra page content */
|
|
44
57
|
examplesDir?: string;
|
|
45
58
|
/**
|