@intentius/chant 0.124.31 → 0.124.33
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/bin/chant +7 -2
- package/dist/ci-jobs.d.ts +4 -0
- package/dist/ci-jobs.d.ts.map +1 -1
- package/dist/ci-jobs.js +9 -2
- package/dist/cli/commands/check-lexicon-plugin.d.ts +7 -4
- package/dist/cli/commands/check-lexicon-plugin.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon-plugin.js +10 -7
- package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon.js +18 -12
- package/dist/cli/commands/import.d.ts +10 -0
- package/dist/cli/commands/import.d.ts.map +1 -1
- package/dist/cli/commands/import.js +37 -0
- package/dist/cli/commands/init-lexicon/templates/project.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon/templates/project.js +4 -3
- package/dist/cli/commands/onboard.d.ts.map +1 -1
- package/dist/cli/commands/onboard.js +8 -4
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +2 -1
- package/dist/cli/dependencies.d.ts +18 -0
- package/dist/cli/dependencies.d.ts.map +1 -0
- package/dist/cli/dependencies.js +120 -0
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/build.js +38 -4
- package/dist/cli/handlers/fan-out.d.ts.map +1 -1
- package/dist/cli/handlers/fan-out.js +12 -4
- package/dist/cli/handlers/graph.d.ts.map +1 -1
- package/dist/cli/handlers/graph.js +16 -6
- package/dist/cli/handlers/lifecycle-health.d.ts +16 -0
- package/dist/cli/handlers/lifecycle-health.d.ts.map +1 -0
- package/dist/cli/handlers/lifecycle-health.js +150 -0
- package/dist/cli/handlers/lifecycle.d.ts +26 -0
- package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
- package/dist/cli/handlers/lifecycle.js +1 -1
- package/dist/cli/handlers/lint.d.ts.map +1 -1
- package/dist/cli/handlers/lint.js +6 -0
- package/dist/cli/handlers/operator.d.ts +2 -2
- package/dist/cli/handlers/operator.js +3 -3
- package/dist/cli/handlers/pr.d.ts +16 -0
- package/dist/cli/handlers/pr.d.ts.map +1 -1
- package/dist/cli/handlers/pr.js +610 -32
- package/dist/cli/handlers/promote.d.ts.map +1 -1
- package/dist/cli/handlers/promote.js +19 -2
- package/dist/cli/handlers/release.d.ts +16 -1
- package/dist/cli/handlers/release.d.ts.map +1 -1
- package/dist/cli/handlers/release.js +83 -11
- package/dist/cli/handlers/run.d.ts +13 -1
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/handlers/run.js +38 -15
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +121 -33
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +37 -0
- package/dist/cli/registry.d.ts +29 -6
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/cli/registry.js +6 -2
- package/dist/codegen/generate-post-synth-barrel.js +2 -2
- package/dist/codegen/lexicon-regen.d.ts +4 -0
- package/dist/codegen/lexicon-regen.d.ts.map +1 -1
- package/dist/codegen/lexicon-regen.js +1 -1
- package/dist/codegen/pinned-upgrade.js +2 -2
- package/dist/components/capability.d.ts +44 -3
- package/dist/components/capability.d.ts.map +1 -1
- package/dist/components/capability.js +21 -0
- package/dist/components/changed-files.d.ts +7 -1
- package/dist/components/changed-files.d.ts.map +1 -1
- package/dist/components/changed-files.js +9 -1
- package/dist/components/deploy-inputs.d.ts +91 -0
- package/dist/components/deploy-inputs.d.ts.map +1 -0
- package/dist/components/deploy-inputs.js +184 -0
- package/dist/components/driver.d.ts +38 -0
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/driver.js +56 -6
- package/dist/components/fan-out-record.d.ts +6 -1
- package/dist/components/fan-out-record.d.ts.map +1 -1
- package/dist/components/fan-out-record.js +24 -0
- package/dist/components/fan-out-run.d.ts +20 -0
- package/dist/components/fan-out-run.d.ts.map +1 -1
- package/dist/components/fan-out-run.js +21 -1
- package/dist/components/gate-plan.d.ts +8 -0
- package/dist/components/gate-plan.d.ts.map +1 -1
- package/dist/components/gate-plan.js +6 -0
- package/dist/components/pr-pipeline.d.ts +98 -12
- package/dist/components/pr-pipeline.d.ts.map +1 -1
- package/dist/components/pr-pipeline.js +146 -23
- package/dist/components/pr-run.d.ts +128 -30
- package/dist/components/pr-run.d.ts.map +1 -1
- package/dist/components/pr-run.js +290 -70
- package/dist/components/release-compile.d.ts +37 -2
- package/dist/components/release-compile.d.ts.map +1 -1
- package/dist/components/release-compile.js +64 -8
- package/dist/components/release-promote.d.ts +17 -3
- package/dist/components/release-promote.d.ts.map +1 -1
- package/dist/components/release-promote.js +79 -18
- package/dist/components/verbs/bom-writer.d.ts +1 -1
- package/dist/components/verbs/bom-writer.d.ts.map +1 -1
- package/dist/components/verbs/lockfile-sbom-generator.d.ts +20 -0
- package/dist/components/verbs/lockfile-sbom-generator.d.ts.map +1 -1
- package/dist/components/verbs/lockfile-sbom-generator.js +41 -4
- package/dist/components/wave-plan.d.ts +15 -2
- package/dist/components/wave-plan.d.ts.map +1 -1
- package/dist/components/wave-plan.js +44 -5
- package/dist/discovery/fold-import.d.ts.map +1 -1
- package/dist/discovery/fold-import.js +16 -6
- package/dist/discovery/sandbox/bundle.d.ts.map +1 -1
- package/dist/discovery/sandbox/bundle.js +6 -0
- package/dist/discovery/specifier-resolve.d.ts.map +1 -1
- package/dist/discovery/specifier-resolve.js +8 -2
- package/dist/fold/fold.d.ts.map +1 -1
- package/dist/fold/fold.js +68 -1
- package/dist/fold/subset.d.ts +37 -0
- package/dist/fold/subset.d.ts.map +1 -1
- package/dist/fold/subset.js +88 -0
- package/dist/graph-detail.d.ts.map +1 -1
- package/dist/graph-detail.js +32 -7
- package/dist/health.d.ts +110 -0
- package/dist/health.d.ts.map +1 -0
- package/dist/health.js +105 -0
- package/dist/health.schema.json +191 -0
- package/dist/lexicon-module.d.ts +10 -0
- package/dist/lexicon-module.d.ts.map +1 -1
- package/dist/lexicon-module.js +53 -8
- package/dist/lexicon-plugin-helpers.d.ts.map +1 -1
- package/dist/lexicon-plugin-helpers.js +6 -4
- package/dist/lexicon.d.ts +29 -0
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/affected.d.ts.map +1 -1
- package/dist/lifecycle/affected.js +7 -1
- package/dist/lifecycle/merge-record.d.ts +104 -0
- package/dist/lifecycle/merge-record.d.ts.map +1 -0
- package/dist/lifecycle/merge-record.js +102 -0
- package/dist/lifecycle/publish-attachments.d.ts +8 -5
- package/dist/lifecycle/publish-attachments.d.ts.map +1 -1
- package/dist/lifecycle/publish-attachments.js +27 -13
- package/dist/lifecycle/publish-npm.d.ts +3 -2
- package/dist/lifecycle/publish-npm.d.ts.map +1 -1
- package/dist/lifecycle/publish-npm.js +4 -3
- package/dist/lifecycle/release-at.d.ts +40 -0
- package/dist/lifecycle/release-at.d.ts.map +1 -0
- package/dist/lifecycle/release-at.js +83 -0
- package/dist/lifecycle/release-cut.d.ts.map +1 -1
- package/dist/lifecycle/release-cut.js +23 -12
- package/dist/lifecycle/release-ledger.d.ts +21 -0
- package/dist/lifecycle/release-ledger.d.ts.map +1 -1
- package/dist/lifecycle/release-ledger.js +24 -0
- package/dist/lifecycle/release-publish.d.ts +28 -12
- package/dist/lifecycle/release-publish.d.ts.map +1 -1
- package/dist/lifecycle/release-publish.js +29 -17
- package/dist/lifecycle/release-store.d.ts +25 -2
- package/dist/lifecycle/release-store.d.ts.map +1 -1
- package/dist/lifecycle/release-store.js +40 -13
- package/dist/lifecycle/run-ledger.d.ts.map +1 -1
- package/dist/lifecycle/run-ledger.js +1 -0
- package/dist/lifecycle/work-dir.d.ts +45 -0
- package/dist/lifecycle/work-dir.d.ts.map +1 -0
- package/dist/lifecycle/work-dir.js +78 -0
- package/dist/lint/discover.d.ts +17 -9
- package/dist/lint/discover.d.ts.map +1 -1
- package/dist/lint/discover.js +62 -54
- package/dist/lint/rules/op/index.d.ts +2 -1
- package/dist/lint/rules/op/index.d.ts.map +1 -1
- package/dist/lint/rules/op/index.js +4 -2
- package/dist/lint/rules/op/ops018-shell-image-digest.d.ts +10 -0
- package/dist/lint/rules/op/ops018-shell-image-digest.d.ts.map +1 -0
- package/dist/lint/rules/op/ops018-shell-image-digest.js +38 -0
- package/dist/module-source.d.ts +57 -0
- package/dist/module-source.d.ts.map +1 -0
- package/dist/module-source.js +104 -0
- package/dist/op/activities/activity-contracts.d.ts +5 -0
- package/dist/op/activities/activity-contracts.d.ts.map +1 -1
- package/dist/op/activities/activity-contracts.js +3 -0
- package/dist/op/activities/factory.js +1 -1
- package/dist/op/activities/shell.d.ts +38 -0
- package/dist/op/activities/shell.d.ts.map +1 -1
- package/dist/op/activities/shell.js +89 -3
- package/dist/op/builders.d.ts +7 -0
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/builders.js +7 -0
- package/dist/op/discover.d.ts.map +1 -1
- package/dist/op/discover.js +13 -3
- package/dist/op/gate.d.ts.map +1 -1
- package/dist/op/gate.js +3 -0
- package/dist/op/op-waves-run.d.ts.map +1 -1
- package/dist/op/op-waves-run.js +20 -5
- package/dist/op/operator.d.ts +2 -2
- package/dist/op/operator.js +2 -2
- package/dist/op/runtime.d.ts +2 -0
- package/dist/op/runtime.d.ts.map +1 -1
- package/dist/op/steward.d.ts +6 -4
- package/dist/op/steward.d.ts.map +1 -1
- package/dist/op/steward.js +5 -3
- package/dist/op/work-lease-run.d.ts +20 -7
- package/dist/op/work-lease-run.d.ts.map +1 -1
- package/dist/op/work-lease-run.js +56 -12
- package/dist/pr-forge.d.ts +10 -0
- package/dist/pr-forge.d.ts.map +1 -1
- package/dist/pr-forge.js +39 -0
- package/dist/pr-loop.d.ts +155 -7
- package/dist/pr-loop.d.ts.map +1 -1
- package/dist/pr-loop.js +137 -11
- package/dist/pr-report-url.d.ts +4 -4
- package/dist/pr-report-url.d.ts.map +1 -1
- package/dist/pr-report-url.js +5 -5
- package/dist/runner-start.d.ts +179 -0
- package/dist/runner-start.d.ts.map +1 -0
- package/dist/runner-start.js +277 -0
- package/dist/ts-loader.d.ts +38 -4
- package/dist/ts-loader.d.ts.map +1 -1
- package/dist/ts-loader.js +190 -16
- package/dist/wave-runtime.mjs +238 -231
- package/dist/workspace/chant-migrations/fountain-retired-kinds.d.ts +34 -0
- package/dist/workspace/chant-migrations/fountain-retired-kinds.d.ts.map +1 -0
- package/dist/workspace/chant-migrations/fountain-retired-kinds.js +176 -0
- package/dist/workspace/chant-migrations.d.ts.map +1 -1
- package/dist/workspace/chant-migrations.js +2 -0
- package/dist/workspace/check.schema.json +70 -2
- package/dist/workspace/checks/boxes.d.ts +6 -6
- package/dist/workspace/checks/boxes.js +9 -9
- package/dist/workspace/checks/security.d.ts +35 -0
- package/dist/workspace/checks/security.d.ts.map +1 -0
- package/dist/workspace/checks/security.js +305 -0
- package/dist/workspace/checks.d.ts +2 -0
- package/dist/workspace/checks.d.ts.map +1 -1
- package/dist/workspace/checks.js +5 -0
- package/dist/workspace/ci-builds.d.ts +163 -0
- package/dist/workspace/ci-builds.d.ts.map +1 -0
- package/dist/workspace/ci-builds.js +315 -0
- package/dist/workspace/ci-green-cli.d.ts +2 -1
- package/dist/workspace/ci-green-cli.d.ts.map +1 -1
- package/dist/workspace/ci-green-cli.js +25 -5
- package/dist/workspace/ci-green-forge.d.ts +18 -4
- package/dist/workspace/ci-green-forge.d.ts.map +1 -1
- package/dist/workspace/ci-green-forge.js +12 -0
- package/dist/workspace/ci-green-workflow.d.ts +55 -1
- package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
- package/dist/workspace/ci-green-workflow.js +128 -1
- package/dist/workspace/ci-green.d.ts +117 -16
- package/dist/workspace/ci-green.d.ts.map +1 -1
- package/dist/workspace/ci-green.js +358 -43
- package/dist/workspace/ci-last-green.schema.json +49 -0
- package/dist/workspace/ci-list.schema.json +47 -7
- package/dist/workspace/ci-report-url.d.ts +18 -0
- package/dist/workspace/ci-report-url.d.ts.map +1 -0
- package/dist/workspace/ci-report-url.js +33 -0
- package/dist/workspace/ci-run-index.d.ts +13 -1
- package/dist/workspace/ci-run-index.d.ts.map +1 -1
- package/dist/workspace/ci-run-index.js +6 -4
- package/dist/workspace/ci-run-index.schema.json +6 -4
- package/dist/workspace/ci-run.d.ts +85 -6
- package/dist/workspace/ci-run.d.ts.map +1 -1
- package/dist/workspace/ci-run.js +262 -64
- package/dist/workspace/ci-runner-key.d.ts +16 -3
- package/dist/workspace/ci-runner-key.d.ts.map +1 -1
- package/dist/workspace/ci-runner-key.js +30 -10
- package/dist/workspace/ci-runner-start.d.ts +77 -0
- package/dist/workspace/ci-runner-start.d.ts.map +1 -0
- package/dist/workspace/ci-runner-start.js +185 -0
- package/dist/workspace/ci-serve.d.ts +130 -11
- package/dist/workspace/ci-serve.d.ts.map +1 -1
- package/dist/workspace/ci-serve.js +323 -40
- package/dist/workspace/declaration.d.ts +25 -0
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.js +14 -2
- package/dist/workspace/declaration.schema.json +30 -2
- package/dist/workspace/export.d.ts +1 -1
- package/dist/workspace/export.d.ts.map +1 -1
- package/dist/workspace/export.js +7 -3
- package/dist/workspace/ls.d.ts +8 -1
- package/dist/workspace/ls.d.ts.map +1 -1
- package/dist/workspace/ls.js +2 -1
- package/dist/workspace/ls.schema.json +9 -2
- package/dist/workspace/member-pipeline.d.ts +1 -0
- package/dist/workspace/member-pipeline.d.ts.map +1 -1
- package/dist/workspace/member-pipeline.js +2 -0
- package/dist/workspace/merge-record.schema.json +49 -0
- package/dist/workspace/pin-integrity.d.ts.map +1 -1
- package/dist/workspace/pin-integrity.js +3 -2
- package/dist/workspace/pr-report.schema.json +75 -8
- package/dist/workspace/reason-codes.d.ts +18 -1
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +20 -2
- package/dist/workspace/release-candidates.d.ts +129 -0
- package/dist/workspace/release-candidates.d.ts.map +1 -0
- package/dist/workspace/release-candidates.js +233 -0
- package/dist/workspace/release-candidates.schema.json +353 -0
- package/dist/workspace/run-event.schema.json +3 -1
- package/dist/workspace/security.d.ts +40 -0
- package/dist/workspace/security.d.ts.map +1 -0
- package/dist/workspace/security.js +99 -0
- package/dist/workspace/status.schema.json +3 -1
- package/dist/workspace/write-scope.d.ts +9 -0
- package/dist/workspace/write-scope.d.ts.map +1 -1
- package/dist/workspace/write-scope.js +11 -1
- package/package.json +8 -1
- package/src/__fixtures__/pr-loop/pr-apply-wave-waiting.note.golden.md +48 -0
- package/src/__fixtures__/pr-loop/pr-plan.note.golden.md +1 -1
- package/src/ci-jobs.ts +11 -2
- package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +3 -3
- package/src/cli/commands/audit.test.ts +2 -2
- package/src/cli/commands/check-lexicon-plugin.test.ts +9 -0
- package/src/cli/commands/check-lexicon-plugin.ts +11 -8
- package/src/cli/commands/check-lexicon.test.ts +1 -1
- package/src/cli/commands/check-lexicon.ts +16 -11
- package/src/cli/commands/import.ts +40 -0
- package/src/cli/commands/init-lexicon/templates/project.ts +4 -3
- package/src/cli/commands/init-lexicon.test.ts +8 -5
- package/src/cli/commands/onboard.test.ts +45 -0
- package/src/cli/commands/onboard.ts +8 -4
- package/src/cli/commands/update.test.ts +6 -0
- package/src/cli/commands/update.ts +4 -1
- package/src/cli/compiled-cli.e2e.test.ts +76 -11
- package/src/cli/dependencies.e2e.test.ts +101 -0
- package/src/cli/dependencies.test.ts +93 -0
- package/src/cli/dependencies.ts +122 -0
- package/src/cli/handlers/build.test.ts +105 -0
- package/src/cli/handlers/build.ts +35 -4
- package/src/cli/handlers/fan-out.test.ts +73 -0
- package/src/cli/handlers/fan-out.ts +11 -4
- package/src/cli/handlers/graph.test.ts +76 -0
- package/src/cli/handlers/graph.ts +19 -12
- package/src/cli/handlers/lifecycle-health.test.ts +123 -0
- package/src/cli/handlers/lifecycle-health.ts +157 -0
- package/src/cli/handlers/lifecycle.ts +1 -1
- package/src/cli/handlers/lint.test.ts +42 -0
- package/src/cli/handlers/lint.ts +6 -0
- package/src/cli/handlers/operator.ts +3 -3
- package/src/cli/handlers/pr-deploy-inputs.test.ts +209 -0
- package/src/cli/handlers/pr-record.test.ts +201 -0
- package/src/cli/handlers/pr-waves.test.ts +449 -0
- package/src/cli/handlers/pr.test.ts +156 -0
- package/src/cli/handlers/pr.ts +648 -33
- package/src/cli/handlers/promote.test.ts +43 -1
- package/src/cli/handlers/promote.ts +19 -3
- package/src/cli/handlers/release-cut-at.e2e.test.ts +115 -0
- package/src/cli/handlers/release-publish-targets.e2e.test.ts +2 -2
- package/src/cli/handlers/release-verify.e2e.test.ts +12 -10
- package/src/cli/handlers/release.e2e.test.ts +19 -28
- package/src/cli/handlers/release.ts +81 -11
- package/src/cli/handlers/run-components-exit.test.ts +99 -0
- package/src/cli/handlers/run-signer.test.ts +79 -0
- package/src/cli/handlers/run.ts +34 -16
- package/src/cli/main.test.ts +18 -0
- package/src/cli/main.ts +120 -33
- package/src/cli/parse-args.ts +28 -0
- package/src/cli/registry.ts +35 -8
- package/src/codegen/generate-post-synth-barrel.ts +2 -2
- package/src/codegen/lexicon-regen.ts +1 -1
- package/src/codegen/pinned-upgrade.ts +2 -2
- package/src/codegen/post-synth-barrel-guards.test.ts +6 -11
- package/src/components/capability.ts +51 -3
- package/src/components/changed-files.test.ts +16 -1
- package/src/components/changed-files.ts +9 -1
- package/src/components/deploy-inputs.test.ts +108 -0
- package/src/components/deploy-inputs.ts +225 -0
- package/src/components/driver.test.ts +36 -1
- package/src/components/driver.ts +87 -4
- package/src/components/fan-out-record.ts +29 -1
- package/src/components/fan-out-run.test.ts +35 -0
- package/src/components/fan-out-run.ts +40 -1
- package/src/components/gate-plan.ts +9 -0
- package/src/components/pr-pipeline.test.ts +100 -0
- package/src/components/pr-pipeline.ts +184 -28
- package/src/components/pr-run.test.ts +323 -18
- package/src/components/pr-run.ts +355 -76
- package/src/components/release-compile.test.ts +34 -0
- package/src/components/release-compile.ts +89 -8
- package/src/components/release-promote.test.ts +55 -2
- package/src/components/release-promote.ts +93 -23
- package/src/components/verbs/bom-writer.ts +1 -1
- package/src/components/verbs/lockfile-sbom-generator.test.ts +36 -0
- package/src/components/verbs/lockfile-sbom-generator.ts +43 -5
- package/src/components/wave-plan.ts +48 -8
- package/src/discovery/fold-host-method.test.ts +87 -0
- package/src/discovery/fold-import.ts +15 -5
- package/src/discovery/fold-package-composite.test.ts +27 -0
- package/src/discovery/fold-specifiers.test.ts +8 -0
- package/src/discovery/sandbox/bundle.ts +6 -0
- package/src/discovery/specifier-resolve.ts +8 -2
- package/src/fold/fold.test.ts +72 -0
- package/src/fold/fold.ts +71 -0
- package/src/fold/subset.test.ts +31 -0
- package/src/fold/subset.ts +99 -0
- package/src/graph-detail.test.ts +57 -0
- package/src/graph-detail.ts +33 -7
- package/src/health.schema.json +191 -0
- package/src/health.test.ts +62 -0
- package/src/health.ts +178 -0
- package/src/lexicon-dist.e2e.test.ts +254 -0
- package/src/lexicon-module.test.ts +47 -0
- package/src/lexicon-module.ts +49 -7
- package/src/lexicon-plugin-helpers.ts +6 -4
- package/src/lexicon.ts +43 -1
- package/src/lifecycle/affected.test.ts +7 -0
- package/src/lifecycle/affected.ts +6 -1
- package/src/lifecycle/merge-record.test.ts +111 -0
- package/src/lifecycle/merge-record.ts +154 -0
- package/src/lifecycle/publish-attachments.ts +25 -13
- package/src/lifecycle/publish-npm.ts +4 -3
- package/src/lifecycle/publish-targets.test.ts +34 -4
- package/src/lifecycle/release-at.test.ts +48 -0
- package/src/lifecycle/release-at.ts +100 -0
- package/src/lifecycle/release-cut.test.ts +41 -0
- package/src/lifecycle/release-cut.ts +22 -11
- package/src/lifecycle/release-ledger.ts +34 -0
- package/src/lifecycle/release-publish.test.ts +43 -13
- package/src/lifecycle/release-publish.ts +38 -18
- package/src/lifecycle/release-store.ts +57 -13
- package/src/lifecycle/run-ledger.test.ts +13 -0
- package/src/lifecycle/run-ledger.ts +1 -0
- package/src/lifecycle/work-dir.test.ts +77 -0
- package/src/lifecycle/work-dir.ts +82 -0
- package/src/lint/discover.test.ts +46 -2
- package/src/lint/discover.ts +55 -49
- package/src/lint/rules/op/index.ts +4 -2
- package/src/lint/rules/op/ops018-shell-image-digest.test.ts +60 -0
- package/src/lint/rules/op/ops018-shell-image-digest.ts +48 -0
- package/src/module-source.test.ts +85 -0
- package/src/module-source.ts +112 -0
- package/src/op/activities/activity-contracts.ts +3 -0
- package/src/op/activities/factory.ts +1 -1
- package/src/op/activities/shell-container.e2e.test.ts +67 -0
- package/src/op/activities/shell.test.ts +44 -1
- package/src/op/activities/shell.ts +110 -3
- package/src/op/builders.ts +7 -0
- package/src/op/discover-root.test.ts +31 -2
- package/src/op/discover.ts +14 -4
- package/src/op/gate.test.ts +30 -0
- package/src/op/gate.ts +3 -0
- package/src/op/op-waves-run.ts +20 -5
- package/src/op/op-waves.test.ts +49 -0
- package/src/op/operator.ts +2 -2
- package/src/op/runtime.ts +2 -0
- package/src/op/step-console.test.ts +4 -2
- package/src/op/steward.ts +6 -4
- package/src/op/work-lease-run.test.ts +88 -2
- package/src/op/work-lease-run.ts +52 -12
- package/src/pr-forge-bundle.test.ts +2 -2
- package/src/pr-forge.test.ts +42 -0
- package/src/pr-forge.ts +40 -0
- package/src/pr-loop-bundle.test.ts +2 -1
- package/src/pr-loop.test.ts +146 -1
- package/src/pr-loop.ts +278 -17
- package/src/pr-report-url.ts +7 -7
- package/src/runner-start-bundle.test.ts +29 -0
- package/src/runner-start.test.ts +179 -0
- package/src/runner-start.ts +329 -0
- package/src/terraform/__fixtures__/advise.test.ts +21 -2
- package/src/ts-loader.test.ts +89 -1
- package/src/ts-loader.ts +180 -13
- package/src/workspace/changes.test.ts +1 -1
- package/src/workspace/chant-migrations/fountain-retired-kinds.test.ts +33 -0
- package/src/workspace/chant-migrations/fountain-retired-kinds.ts +190 -0
- package/src/workspace/chant-migrations.e2e.test.ts +5 -0
- package/src/workspace/chant-migrations.ts +2 -0
- package/src/workspace/check-contract.test.ts +3 -2
- package/src/workspace/check.schema.json +70 -2
- package/src/workspace/checks/boxes.ts +9 -9
- package/src/workspace/checks/security.test.ts +138 -0
- package/src/workspace/checks/security.ts +305 -0
- package/src/workspace/checks.ts +5 -0
- package/src/workspace/ci-builds.e2e.test.ts +208 -0
- package/src/workspace/ci-builds.test.ts +174 -0
- package/src/workspace/ci-builds.ts +385 -0
- package/src/workspace/ci-green-builds.test.ts +180 -0
- package/src/workspace/ci-green-cli.test.ts +54 -0
- package/src/workspace/ci-green-cli.ts +26 -5
- package/src/workspace/ci-green-forge.ts +30 -4
- package/src/workspace/ci-green-runs.test.ts +53 -11
- package/src/workspace/ci-green-workflow.test.ts +84 -1
- package/src/workspace/ci-green-workflow.ts +139 -2
- package/src/workspace/ci-green.test.ts +6 -3
- package/src/workspace/ci-green.ts +408 -48
- package/src/workspace/ci-last-green.schema.json +49 -0
- package/src/workspace/ci-list.schema.json +47 -7
- package/src/workspace/ci-report-url.test.ts +220 -0
- package/src/workspace/ci-report-url.ts +33 -0
- package/src/workspace/ci-run-index.schema.json +6 -4
- package/src/workspace/ci-run-index.test.ts +42 -3
- package/src/workspace/ci-run-index.ts +19 -5
- package/src/workspace/ci-run.test.ts +203 -8
- package/src/workspace/ci-run.ts +295 -63
- package/src/workspace/ci-runner-key.test.ts +55 -17
- package/src/workspace/ci-runner-key.ts +36 -11
- package/src/workspace/ci-runner-start.test.ts +151 -0
- package/src/workspace/ci-runner-start.ts +193 -0
- package/src/workspace/ci-serve-builds.test.ts +86 -0
- package/src/workspace/ci-serve.test.ts +209 -6
- package/src/workspace/ci-serve.ts +341 -42
- package/src/workspace/declaration.schema.json +30 -2
- package/src/workspace/declaration.test.ts +40 -0
- package/src/workspace/declaration.ts +40 -3
- package/src/workspace/export.ts +6 -3
- package/src/workspace/ls.schema.json +9 -2
- package/src/workspace/ls.ts +10 -4
- package/src/workspace/member-pipeline.ts +2 -1
- package/src/workspace/merge-record.schema.json +49 -0
- package/src/workspace/pin-integrity.test.ts +5 -0
- package/src/workspace/pin-integrity.ts +3 -2
- package/src/workspace/pr-report.schema.json +75 -8
- package/src/workspace/reason-codes.test.ts +2 -0
- package/src/workspace/reason-codes.ts +20 -2
- package/src/workspace/release-candidates.schema.json +353 -0
- package/src/workspace/release-candidates.test.ts +106 -0
- package/src/workspace/release-candidates.ts +315 -0
- package/src/workspace/run-event.schema.json +3 -1
- package/src/workspace/security.test.ts +70 -0
- package/src/workspace/security.ts +118 -0
- package/src/workspace/status.schema.json +3 -1
- package/src/workspace/write-scope.test.ts +29 -1
- package/src/workspace/write-scope.ts +12 -1
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* _releases/<releaseDigest>.json the release, written once and never rewritten
|
|
15
15
|
* _releases/cuts.jsonl one line per cut, with the release's label
|
|
16
16
|
* _releases/templates/<digest>.txt each template's bytes, by content digest
|
|
17
|
+
* _releases/templates/<digest>.b64 a file that is not UTF-8, base64 (#4155)
|
|
17
18
|
*
|
|
18
19
|
* `:` is written as `_` in file names, as `_plans/` and `_builds/` do. A
|
|
19
20
|
* workspace member's copy sits under `_members/<member>/` through the same
|
|
@@ -24,6 +25,14 @@
|
|
|
24
25
|
* (ws-104 question 5). They are named by content digest, so a template that
|
|
25
26
|
* two environments or two releases share is stored once.
|
|
26
27
|
*
|
|
28
|
+
* Since #4155 a cut records every local file a deploy step deploys from, not
|
|
29
|
+
* only `template`, `manifest` and `values` files: a chart, a kustomize
|
|
30
|
+
* directory, a site's tree. A directory is recorded as one template per file
|
|
31
|
+
* under it, and named in the target's `trees`, so a promote deploys the
|
|
32
|
+
* recorded tree. A target with `trees` is one such cut; a target without the
|
|
33
|
+
* field was cut before #4155, and a promote of it reads directories and the
|
|
34
|
+
* other fields from the checkout, as it did then.
|
|
35
|
+
*
|
|
27
36
|
* `releaseDigest` is `computePlanDigest("release", subject)` over the member,
|
|
28
37
|
* the commit, the artifact digests and each target's env, templates and the
|
|
29
38
|
* name and value of each param. A param's `source`, the label, the actor, the
|
|
@@ -31,7 +40,7 @@
|
|
|
31
40
|
* same digest.
|
|
32
41
|
*/
|
|
33
42
|
import { sortedJsonReplacer } from "../utils.js";
|
|
34
|
-
import { contentDigest } from "../content-digest.js";
|
|
43
|
+
import { contentDigest, sha256Hex } from "../content-digest.js";
|
|
35
44
|
import { computePlanDigest } from "./plan-digest.js";
|
|
36
45
|
import { ledgerDir, listFilesInDir, readBlobBySha, readBlobFromPath, readPathSha, RefCASConflictError, writeLedgerFiles, } from "./git.js";
|
|
37
46
|
/** The directory on `chant/lifecycle` that holds releases, cuts and template bytes. */
|
|
@@ -54,9 +63,12 @@ export function normalizeRelease(release) {
|
|
|
54
63
|
.map((t) => ({
|
|
55
64
|
env: t.env,
|
|
56
65
|
templates: [...t.templates]
|
|
57
|
-
.map(({ component, path, digest }) => ({ component, path, digest }))
|
|
66
|
+
.map(({ component, path, digest, encoding }) => ({ component, path, digest, ...(encoding ? { encoding } : {}) }))
|
|
58
67
|
.sort((a, b) => byString(a.component ?? "", b.component ?? "") || byString(a.path, b.path)),
|
|
59
68
|
params: [...t.params].map(({ name, value, source }) => ({ name, value, source })).sort((a, b) => byString(a.name, b.name)),
|
|
69
|
+
...(t.trees
|
|
70
|
+
? { trees: [...t.trees].map(({ component, path }) => ({ component, path })).sort((a, b) => byString(a.component ?? "", b.component ?? "") || byString(a.path, b.path)) }
|
|
71
|
+
: {}),
|
|
60
72
|
}))
|
|
61
73
|
.sort((a, b) => byString(a.env, b.env)),
|
|
62
74
|
};
|
|
@@ -68,7 +80,12 @@ export function releaseHashInput(release) {
|
|
|
68
80
|
member: n.member,
|
|
69
81
|
commit: n.commit,
|
|
70
82
|
artifactDigests: n.artifactDigests,
|
|
71
|
-
targets: n.targets.map((t) => ({
|
|
83
|
+
targets: n.targets.map((t) => ({
|
|
84
|
+
env: t.env,
|
|
85
|
+
templates: t.templates,
|
|
86
|
+
params: t.params.map(({ name, value }) => ({ name, value })),
|
|
87
|
+
...(t.trees ? { trees: t.trees } : {}),
|
|
88
|
+
})),
|
|
72
89
|
};
|
|
73
90
|
}
|
|
74
91
|
/** `computePlanDigest("release", input)` over {@link releaseHashInput}. */
|
|
@@ -86,7 +103,11 @@ export function verifyReleaseDigest(release) {
|
|
|
86
103
|
}
|
|
87
104
|
const stem = (digest) => digest.replace(/:/g, "_");
|
|
88
105
|
const releaseFile = (digest) => `${stem(digest)}.json`;
|
|
89
|
-
const templateFile = (digest) => `${stem(digest)}
|
|
106
|
+
const templateFile = (digest, encoding) => `${stem(digest)}.${encoding === "base64" ? "b64" : "txt"}`;
|
|
107
|
+
/** The digest of a template's bytes: its text, or what its base64 decodes to. */
|
|
108
|
+
export function templateBytesDigest(content, encoding) {
|
|
109
|
+
return encoding === "base64" ? `sha256:${sha256Hex(Buffer.from(content, "base64"))}` : contentDigest(content);
|
|
110
|
+
}
|
|
90
111
|
/** A label names a release in commands such as `chant release cut <label>`, so it is one plain word. */
|
|
91
112
|
const LABEL_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
|
|
92
113
|
/** Why a label can't be used, or undefined when it can. */
|
|
@@ -113,7 +134,7 @@ export async function persistRelease(release, templates, opts) {
|
|
|
113
134
|
throw new Error(`release ${release.releaseDigest} does not hash to its own digest; refusing to store it`);
|
|
114
135
|
}
|
|
115
136
|
for (const t of templates) {
|
|
116
|
-
if (
|
|
137
|
+
if (templateBytesDigest(t.content, t.encoding) !== t.digest)
|
|
117
138
|
throw new Error(`template bytes do not hash to ${t.digest}; refusing to store them`);
|
|
118
139
|
}
|
|
119
140
|
const dir = await ledgerDir(RELEASES_DIR, opts);
|
|
@@ -124,12 +145,13 @@ export async function persistRelease(release, templates, opts) {
|
|
|
124
145
|
files.push({ path: releasePath, content: `${JSON.stringify(release, sortedJsonReplacer)}\n`, expectPriorSha: null });
|
|
125
146
|
const seen = new Set();
|
|
126
147
|
for (const t of templates) {
|
|
127
|
-
|
|
148
|
+
const file = templateFile(t.digest, t.encoding);
|
|
149
|
+
if (seen.has(file))
|
|
128
150
|
continue;
|
|
129
|
-
seen.add(
|
|
130
|
-
if ((await readPathSha(`${RELEASES_DIR}/${TEMPLATES_SUBDIR}`,
|
|
151
|
+
seen.add(file);
|
|
152
|
+
if ((await readPathSha(`${RELEASES_DIR}/${TEMPLATES_SUBDIR}`, file, opts)) !== null)
|
|
131
153
|
continue;
|
|
132
|
-
files.push({ path: `${dir}/${TEMPLATES_SUBDIR}/${
|
|
154
|
+
files.push({ path: `${dir}/${TEMPLATES_SUBDIR}/${file}`, content: t.content, expectPriorSha: null });
|
|
133
155
|
}
|
|
134
156
|
if (files.length === 0)
|
|
135
157
|
return { commit: null, written: false };
|
|
@@ -166,7 +188,12 @@ export function parseRelease(text) {
|
|
|
166
188
|
r.targets.every((t) => t &&
|
|
167
189
|
typeof t.env === "string" &&
|
|
168
190
|
Array.isArray(t.templates) &&
|
|
169
|
-
t.templates.every((x) => x &&
|
|
191
|
+
t.templates.every((x) => x &&
|
|
192
|
+
(x.component === null || typeof x.component === "string") &&
|
|
193
|
+
typeof x.path === "string" &&
|
|
194
|
+
typeof x.digest === "string" &&
|
|
195
|
+
(x.encoding === undefined || x.encoding === "base64")) &&
|
|
196
|
+
(t.trees === undefined || (Array.isArray(t.trees) && t.trees.every((x) => x && (x.component === null || typeof x.component === "string") && typeof x.path === "string"))) &&
|
|
170
197
|
Array.isArray(t.params) &&
|
|
171
198
|
t.params.every((p) => p && typeof p.name === "string" && ["string", "number", "boolean"].includes(typeof p.value) && typeof p.source === "string"));
|
|
172
199
|
return ok ? r : null;
|
|
@@ -297,9 +324,9 @@ export async function appendCut(input, opts) {
|
|
|
297
324
|
}
|
|
298
325
|
throw lastErr;
|
|
299
326
|
}
|
|
300
|
-
/** A template's bytes by digest, or null when none is stored. */
|
|
301
|
-
export async function readReleaseTemplate(digest, opts) {
|
|
302
|
-
return readBlobFromPath(`${RELEASES_DIR}/${TEMPLATES_SUBDIR}`, templateFile(digest), opts);
|
|
327
|
+
/** A template's bytes by digest, or null when none is stored. Under `base64` (#4155), the stored base64 of the bytes. */
|
|
328
|
+
export async function readReleaseTemplate(digest, opts, encoding) {
|
|
329
|
+
return readBlobFromPath(`${RELEASES_DIR}/${TEMPLATES_SUBDIR}`, templateFile(digest, encoding), opts);
|
|
303
330
|
}
|
|
304
331
|
/**
|
|
305
332
|
* Find a release by its digest or its label. Null when neither names one.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-ledger.d.ts","sourceRoot":"","sources":["../../src/lifecycle/run-ledger.ts"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAkB,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAA+C,MAAM,eAAe,CAAC;AASrI,0EAA0E;AAC1E,eAAO,MAAM,eAAe,UAAU,CAAC;AAMvC,8FAA8F;AAC9F,wBAAgB,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,MAAM,CAEjE;AAQD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAAC,EACzC,OAAO,EAAE,SAAS,UAAU,EAAE,EAC9B,KAAK,EAAE;IACL,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC9B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3B,KAAK,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,OAAO,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;IACjC,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IACrC,0EAA0E;IAC1E,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC,GACA,gBAAgB,
|
|
1
|
+
{"version":3,"file":"run-ledger.d.ts","sourceRoot":"","sources":["../../src/lifecycle/run-ledger.ts"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAkB,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAA+C,MAAM,eAAe,CAAC;AASrI,0EAA0E;AAC1E,eAAO,MAAM,eAAe,UAAU,CAAC;AAMvC,8FAA8F;AAC9F,wBAAgB,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,MAAM,CAEjE;AAQD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAAC,EACzC,OAAO,EAAE,SAAS,UAAU,EAAE,EAC9B,KAAK,EAAE;IACL,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC9B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3B,KAAK,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,OAAO,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;IACjC,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IACrC,0EAA0E;IAC1E,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC,GACA,gBAAgB,CAkDlB;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,gBAAgB,EACvB,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACtB,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,CAAC,CAsBlD;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,MAAM,EACV,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACtB,OAAO,CAAC;IAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAkCxD"}
|
|
@@ -91,6 +91,7 @@ export function buildRunRecord(config, records, times) {
|
|
|
91
91
|
...(record.point ? { point: record.point } : {}),
|
|
92
92
|
...(record.gate ? { gate: record.gate } : {}),
|
|
93
93
|
...(record.resumed ? { resumed: record.resumed } : {}),
|
|
94
|
+
...(record.fn === "shellCmd" && typeof record.args?.image === "string" ? { image: record.args.image } : {}),
|
|
94
95
|
});
|
|
95
96
|
if (record.outcome)
|
|
96
97
|
outcomes[record.outcome.name] = record.outcome.value;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where an Op that changes the checkout makes its work worktrees (#2893).
|
|
3
|
+
*
|
|
4
|
+
* A work item's worktree is `<checkout>/.chant/work/[<member>/]<item>`. It
|
|
5
|
+
* sits inside the checkout, so a coding agent whose project root is the
|
|
6
|
+
* checkout may write there, and `node_modules` above it still resolves. It
|
|
7
|
+
* used to be `<git-common-dir>/chant-work/...`, where Claude Code refuses
|
|
8
|
+
* every write. `/.chant/work/` goes in `<git-common-dir>/info/exclude`, so the
|
|
9
|
+
* checkout's `git status` never lists it, and the rest of `.chant/` (the
|
|
10
|
+
* workspace lock, the factory's check logs) stays tracked.
|
|
11
|
+
*
|
|
12
|
+
* This module imports nothing from the workspace or the Op runner, so the
|
|
13
|
+
* hand-written walkers can ask it which directory to skip.
|
|
14
|
+
*/
|
|
15
|
+
/** The work directory, relative to a checkout's top, `/`-separated. */
|
|
16
|
+
export declare const WORK_DIR = ".chant/work";
|
|
17
|
+
/** The line `<git-common-dir>/info/exclude` gets, anchored at each checkout's top. */
|
|
18
|
+
export declare const WORK_DIR_EXCLUDE = "/.chant/work/";
|
|
19
|
+
/** The directory where earlier versions made work worktrees, under the git common directory. */
|
|
20
|
+
export declare const LEGACY_WORK_DIR = "chant-work";
|
|
21
|
+
/**
|
|
22
|
+
* Whether a directory, given as a `/`-separated path relative to the root a
|
|
23
|
+
* walker started from, is a work directory: `.chant/work` at that root or at
|
|
24
|
+
* any depth below it. A walker skips it, since each worktree in it is a whole
|
|
25
|
+
* copy of the checkout.
|
|
26
|
+
*/
|
|
27
|
+
export declare function isWorkDir(rel: string): boolean;
|
|
28
|
+
/** The worktree for `id` under the checkout whose top is `top`. */
|
|
29
|
+
export declare function workWorktreePath(top: string, members: readonly string[], id: string): string;
|
|
30
|
+
/** The worktree an earlier version made for `id`, under the git common directory. */
|
|
31
|
+
export declare function legacyWorkWorktreePath(commonDir: string, members: readonly string[], id: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* Add {@link WORK_DIR_EXCLUDE} to `<commonDir>/info/exclude` unless the file
|
|
34
|
+
* already has it, or `ignored` says git already ignores the work directory
|
|
35
|
+
* (a `.gitignore` of the project's, or the global excludes file). Returns
|
|
36
|
+
* whether it wrote the line.
|
|
37
|
+
*/
|
|
38
|
+
export declare function excludeWorkDir(commonDir: string, ignored: boolean): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* After a work worktree is removed, remove the directories above it that are
|
|
41
|
+
* left empty, up to and including the checkout's `.chant`, so a run leaves
|
|
42
|
+
* nothing behind in a checkout that had no `.chant` before it.
|
|
43
|
+
*/
|
|
44
|
+
export declare function removeEmptyWorkDirs(worktree: string): void;
|
|
45
|
+
//# sourceMappingURL=work-dir.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"work-dir.d.ts","sourceRoot":"","sources":["../../src/lifecycle/work-dir.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,uEAAuE;AACvE,eAAO,MAAM,QAAQ,gBAAgB,CAAC;AAEtC,sFAAsF;AACtF,eAAO,MAAM,gBAAgB,kBAAkB,CAAC;AAEhD,gGAAgG;AAChG,eAAO,MAAM,eAAe,eAAe,CAAC;AAE5C;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED,mEAAmE;AACnE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAE5F;AAED,qFAAqF;AACrF,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAExG;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAQ3E;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAa1D"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where an Op that changes the checkout makes its work worktrees (#2893).
|
|
3
|
+
*
|
|
4
|
+
* A work item's worktree is `<checkout>/.chant/work/[<member>/]<item>`. It
|
|
5
|
+
* sits inside the checkout, so a coding agent whose project root is the
|
|
6
|
+
* checkout may write there, and `node_modules` above it still resolves. It
|
|
7
|
+
* used to be `<git-common-dir>/chant-work/...`, where Claude Code refuses
|
|
8
|
+
* every write. `/.chant/work/` goes in `<git-common-dir>/info/exclude`, so the
|
|
9
|
+
* checkout's `git status` never lists it, and the rest of `.chant/` (the
|
|
10
|
+
* workspace lock, the factory's check logs) stays tracked.
|
|
11
|
+
*
|
|
12
|
+
* This module imports nothing from the workspace or the Op runner, so the
|
|
13
|
+
* hand-written walkers can ask it which directory to skip.
|
|
14
|
+
*/
|
|
15
|
+
import { appendFileSync, existsSync, mkdirSync, readdirSync, readFileSync, rmdirSync } from "node:fs";
|
|
16
|
+
import { dirname, join, sep } from "node:path";
|
|
17
|
+
/** The work directory, relative to a checkout's top, `/`-separated. */
|
|
18
|
+
export const WORK_DIR = ".chant/work";
|
|
19
|
+
/** The line `<git-common-dir>/info/exclude` gets, anchored at each checkout's top. */
|
|
20
|
+
export const WORK_DIR_EXCLUDE = `/${WORK_DIR}/`;
|
|
21
|
+
/** The directory where earlier versions made work worktrees, under the git common directory. */
|
|
22
|
+
export const LEGACY_WORK_DIR = "chant-work";
|
|
23
|
+
/**
|
|
24
|
+
* Whether a directory, given as a `/`-separated path relative to the root a
|
|
25
|
+
* walker started from, is a work directory: `.chant/work` at that root or at
|
|
26
|
+
* any depth below it. A walker skips it, since each worktree in it is a whole
|
|
27
|
+
* copy of the checkout.
|
|
28
|
+
*/
|
|
29
|
+
export function isWorkDir(rel) {
|
|
30
|
+
return rel === WORK_DIR || rel.endsWith(`/${WORK_DIR}`);
|
|
31
|
+
}
|
|
32
|
+
/** The worktree for `id` under the checkout whose top is `top`. */
|
|
33
|
+
export function workWorktreePath(top, members, id) {
|
|
34
|
+
return join(top, ...WORK_DIR.split("/"), ...members, id);
|
|
35
|
+
}
|
|
36
|
+
/** The worktree an earlier version made for `id`, under the git common directory. */
|
|
37
|
+
export function legacyWorkWorktreePath(commonDir, members, id) {
|
|
38
|
+
return join(commonDir, LEGACY_WORK_DIR, ...members, id);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Add {@link WORK_DIR_EXCLUDE} to `<commonDir>/info/exclude` unless the file
|
|
42
|
+
* already has it, or `ignored` says git already ignores the work directory
|
|
43
|
+
* (a `.gitignore` of the project's, or the global excludes file). Returns
|
|
44
|
+
* whether it wrote the line.
|
|
45
|
+
*/
|
|
46
|
+
export function excludeWorkDir(commonDir, ignored) {
|
|
47
|
+
const file = join(commonDir, "info", "exclude");
|
|
48
|
+
const text = existsSync(file) ? readFileSync(file, "utf-8") : "";
|
|
49
|
+
if (text.split(/\r?\n/).some((l) => l.trim() === WORK_DIR_EXCLUDE))
|
|
50
|
+
return false;
|
|
51
|
+
if (ignored)
|
|
52
|
+
return false;
|
|
53
|
+
mkdirSync(join(commonDir, "info"), { recursive: true });
|
|
54
|
+
appendFileSync(file, `${text === "" || text.endsWith("\n") ? "" : "\n"}${WORK_DIR_EXCLUDE}\n`);
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* After a work worktree is removed, remove the directories above it that are
|
|
59
|
+
* left empty, up to and including the checkout's `.chant`, so a run leaves
|
|
60
|
+
* nothing behind in a checkout that had no `.chant` before it.
|
|
61
|
+
*/
|
|
62
|
+
export function removeEmptyWorkDirs(worktree) {
|
|
63
|
+
const marker = `${sep}${WORK_DIR.split("/").join(sep)}${sep}`;
|
|
64
|
+
const at = worktree.lastIndexOf(marker);
|
|
65
|
+
if (at < 0)
|
|
66
|
+
return;
|
|
67
|
+
const stop = worktree.slice(0, at);
|
|
68
|
+
for (let dir = dirname(worktree); dir.length > stop.length; dir = dirname(dir)) {
|
|
69
|
+
try {
|
|
70
|
+
if (readdirSync(dir).length > 0)
|
|
71
|
+
return;
|
|
72
|
+
rmdirSync(dir);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
package/dist/lint/discover.d.ts
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auto-discovery for lint rules and post-synth checks.
|
|
3
3
|
*
|
|
4
|
-
* Scans directories for
|
|
5
|
-
* eliminating the need to manually list every rule in plugin.ts.
|
|
4
|
+
* Scans directories for rule modules and loads exported rules/checks,
|
|
5
|
+
* eliminating the need to manually list every rule in plugin.ts. A lexicon
|
|
6
|
+
* run from source has `.ts` rule modules; one run compiled has `.js` modules
|
|
7
|
+
* beside `.d.ts` declarations (#3981). Both are found, and tsx is registered
|
|
8
|
+
* only when a module found is TypeScript.
|
|
6
9
|
*/
|
|
7
10
|
import type { LintRule } from "./rule.js";
|
|
8
11
|
import type { PostSynthCheck } from "./post-synth.js";
|
|
9
12
|
/**
|
|
10
13
|
* Discover lint rules from a directory.
|
|
11
14
|
*
|
|
12
|
-
* Scans the directory for
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
+
* Scans the directory for rule modules (see {@link listRuleFiles}), loads
|
|
16
|
+
* each one, and collects any exported objects that look like a LintRule (has
|
|
17
|
+
* `id`, `severity`, `category`, and `check` function).
|
|
15
18
|
*
|
|
16
19
|
* @param dir - Absolute path to the rules directory
|
|
17
20
|
* @param importMetaUrl - The caller's import.meta.url (for createRequire)
|
|
@@ -20,16 +23,21 @@ export declare function discoverLintRules(dir: string, importMetaUrl: string): L
|
|
|
20
23
|
/**
|
|
21
24
|
* Discover post-synth checks from a directory.
|
|
22
25
|
*
|
|
23
|
-
* Scans the directory for
|
|
24
|
-
*
|
|
25
|
-
* (has `id`, `description`, and `check` function).
|
|
26
|
+
* Scans the directory for rule modules (see {@link listRuleFiles}), loads
|
|
27
|
+
* each one, and collects any exported objects that look like a
|
|
28
|
+
* PostSynthCheck (has `id`, `description`, and `check` function).
|
|
26
29
|
*
|
|
27
30
|
* @param dir - Absolute path to the post-synth rules directory
|
|
28
31
|
* @param importMetaUrl - The caller's import.meta.url (for createRequire)
|
|
29
32
|
*/
|
|
30
33
|
export declare function discoverPostSynthChecks(dir: string, importMetaUrl: string): PostSynthCheck[];
|
|
34
|
+
/** A rule module's name without its extension: `foo` for `foo.ts` and `foo.js`. */
|
|
35
|
+
export declare function ruleModuleBase(file: string): string;
|
|
31
36
|
/**
|
|
32
|
-
* List rule
|
|
37
|
+
* List rule modules in a directory: `.ts` source or compiled `.js`, leaving
|
|
38
|
+
* out declarations (`.d.ts`), tests, helpers and the index. A directory
|
|
39
|
+
* holding both `foo.ts` and `foo.js` lists `foo.ts` alone, so a rule is
|
|
40
|
+
* never loaded twice.
|
|
33
41
|
*/
|
|
34
42
|
export declare function listRuleFiles(dir: string): string[];
|
|
35
43
|
//# sourceMappingURL=discover.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../../src/lint/discover.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../../src/lint/discover.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAsDnD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,QAAQ,EAAE,CAEhF;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,cAAc,EAAE,CAE5F;AAED,mFAAmF;AACnF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAiBnD"}
|
package/dist/lint/discover.js
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auto-discovery for lint rules and post-synth checks.
|
|
3
3
|
*
|
|
4
|
-
* Scans directories for
|
|
5
|
-
* eliminating the need to manually list every rule in plugin.ts.
|
|
4
|
+
* Scans directories for rule modules and loads exported rules/checks,
|
|
5
|
+
* eliminating the need to manually list every rule in plugin.ts. A lexicon
|
|
6
|
+
* run from source has `.ts` rule modules; one run compiled has `.js` modules
|
|
7
|
+
* beside `.d.ts` declarations (#3981). Both are found, and tsx is registered
|
|
8
|
+
* only when a module found is TypeScript.
|
|
6
9
|
*/
|
|
7
10
|
import { readdirSync } from "fs";
|
|
8
11
|
import { join } from "path";
|
|
9
12
|
import { createRequire } from "module";
|
|
10
13
|
import { ensureTypeScriptLoader } from "../ts-loader.js";
|
|
14
|
+
import { isTypeScriptModule } from "../module-source.js";
|
|
11
15
|
let cjsTypeScript = false;
|
|
12
16
|
/**
|
|
13
17
|
* Register tsx so createRequire can load TypeScript files in Node.js ESM
|
|
@@ -17,7 +21,8 @@ let cjsTypeScript = false;
|
|
|
17
21
|
* From source this runs when the module loads, as it always has: vitest and
|
|
18
22
|
* the source CLI rely on tsx's CommonJS hook being in place from then on. The
|
|
19
23
|
* compiled CLI imports this module on every start and most commands read no
|
|
20
|
-
* rule directory, so there it waits for the first
|
|
24
|
+
* rule directory, so there it waits for the first directory that holds a
|
|
25
|
+
* TypeScript rule module (#3878, #3981).
|
|
21
26
|
*/
|
|
22
27
|
function registerTypeScriptRequire() {
|
|
23
28
|
if (cjsTypeScript)
|
|
@@ -37,85 +42,88 @@ function registerTypeScriptRequire() {
|
|
|
37
42
|
if (!import.meta.url.endsWith(".js"))
|
|
38
43
|
registerTypeScriptRequire();
|
|
39
44
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* Scans the directory for .ts files (excluding tests, helpers, and index files),
|
|
43
|
-
* loads each module, and collects any exported objects that look like a LintRule
|
|
44
|
-
* (has `id`, `severity`, `category`, and `check` function).
|
|
45
|
-
*
|
|
46
|
-
* @param dir - Absolute path to the rules directory
|
|
47
|
-
* @param importMetaUrl - The caller's import.meta.url (for createRequire)
|
|
45
|
+
* Load every rule module in `dir` and collect the exports `accept` takes.
|
|
46
|
+
* Registers tsx first only when one of the modules is TypeScript.
|
|
48
47
|
*/
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
function discoverExports(dir, importMetaUrl, accept) {
|
|
49
|
+
const files = listRuleFiles(dir);
|
|
50
|
+
if (files.some(isTypeScriptModule))
|
|
51
|
+
registerTypeScriptRequire();
|
|
51
52
|
const require = createRequire(importMetaUrl);
|
|
52
|
-
const
|
|
53
|
-
for (const file of
|
|
53
|
+
const found = [];
|
|
54
|
+
for (const file of files) {
|
|
54
55
|
try {
|
|
55
|
-
|
|
56
|
-
const modPath = join(dir, file.replace(/\.ts$/, ""));
|
|
57
|
-
const mod = require(modPath);
|
|
56
|
+
const mod = require(join(dir, file));
|
|
58
57
|
for (const exp of Object.values(mod)) {
|
|
59
|
-
if (
|
|
60
|
-
|
|
58
|
+
if (accept(exp))
|
|
59
|
+
found.push(exp);
|
|
61
60
|
}
|
|
62
61
|
}
|
|
63
62
|
catch {
|
|
64
63
|
// Skip files that fail to load
|
|
65
64
|
}
|
|
66
65
|
}
|
|
67
|
-
return
|
|
66
|
+
return found;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Discover lint rules from a directory.
|
|
70
|
+
*
|
|
71
|
+
* Scans the directory for rule modules (see {@link listRuleFiles}), loads
|
|
72
|
+
* each one, and collects any exported objects that look like a LintRule (has
|
|
73
|
+
* `id`, `severity`, `category`, and `check` function).
|
|
74
|
+
*
|
|
75
|
+
* @param dir - Absolute path to the rules directory
|
|
76
|
+
* @param importMetaUrl - The caller's import.meta.url (for createRequire)
|
|
77
|
+
*/
|
|
78
|
+
export function discoverLintRules(dir, importMetaUrl) {
|
|
79
|
+
return discoverExports(dir, importMetaUrl, isLintRule).sort((a, b) => a.id.localeCompare(b.id));
|
|
68
80
|
}
|
|
69
81
|
/**
|
|
70
82
|
* Discover post-synth checks from a directory.
|
|
71
83
|
*
|
|
72
|
-
* Scans the directory for
|
|
73
|
-
*
|
|
74
|
-
* (has `id`, `description`, and `check` function).
|
|
84
|
+
* Scans the directory for rule modules (see {@link listRuleFiles}), loads
|
|
85
|
+
* each one, and collects any exported objects that look like a
|
|
86
|
+
* PostSynthCheck (has `id`, `description`, and `check` function).
|
|
75
87
|
*
|
|
76
88
|
* @param dir - Absolute path to the post-synth rules directory
|
|
77
89
|
* @param importMetaUrl - The caller's import.meta.url (for createRequire)
|
|
78
90
|
*/
|
|
79
91
|
export function discoverPostSynthChecks(dir, importMetaUrl) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
// Strip .ts extension — require() resolves without it
|
|
86
|
-
const modPath = join(dir, file.replace(/\.ts$/, ""));
|
|
87
|
-
const mod = require(modPath);
|
|
88
|
-
for (const exp of Object.values(mod)) {
|
|
89
|
-
if (isPostSynthCheck(exp))
|
|
90
|
-
checks.push(exp);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
catch {
|
|
94
|
-
// Skip files that fail to load
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return checks.sort((a, b) => a.id.localeCompare(b.id));
|
|
92
|
+
return discoverExports(dir, importMetaUrl, isPostSynthCheck).sort((a, b) => a.id.localeCompare(b.id));
|
|
93
|
+
}
|
|
94
|
+
/** A rule module's name without its extension: `foo` for `foo.ts` and `foo.js`. */
|
|
95
|
+
export function ruleModuleBase(file) {
|
|
96
|
+
return file.replace(/\.(?:ts|js)$/, "");
|
|
98
97
|
}
|
|
99
98
|
/**
|
|
100
|
-
* List rule
|
|
99
|
+
* List rule modules in a directory: `.ts` source or compiled `.js`, leaving
|
|
100
|
+
* out declarations (`.d.ts`), tests, helpers and the index. A directory
|
|
101
|
+
* holding both `foo.ts` and `foo.js` lists `foo.ts` alone, so a rule is
|
|
102
|
+
* never loaded twice.
|
|
101
103
|
*/
|
|
102
104
|
export function listRuleFiles(dir) {
|
|
105
|
+
let entries;
|
|
103
106
|
try {
|
|
104
|
-
|
|
105
|
-
if (!f.endsWith(".ts"))
|
|
106
|
-
return false;
|
|
107
|
-
if (f.endsWith(".test.ts"))
|
|
108
|
-
return false;
|
|
109
|
-
if (f === "index.ts")
|
|
110
|
-
return false;
|
|
111
|
-
if (f.includes("helper"))
|
|
112
|
-
return false;
|
|
113
|
-
return true;
|
|
114
|
-
});
|
|
107
|
+
entries = readdirSync(dir);
|
|
115
108
|
}
|
|
116
109
|
catch {
|
|
117
110
|
return [];
|
|
118
111
|
}
|
|
112
|
+
const modules = entries.filter((f) => {
|
|
113
|
+
if (!f.endsWith(".ts") && !f.endsWith(".js"))
|
|
114
|
+
return false;
|
|
115
|
+
if (f.endsWith(".d.ts"))
|
|
116
|
+
return false;
|
|
117
|
+
if (/\.test\.[tj]s$/.test(f))
|
|
118
|
+
return false;
|
|
119
|
+
if (f === "index.ts" || f === "index.js")
|
|
120
|
+
return false;
|
|
121
|
+
if (f.includes("helper"))
|
|
122
|
+
return false;
|
|
123
|
+
return true;
|
|
124
|
+
});
|
|
125
|
+
const sources = new Set(modules.filter((f) => f.endsWith(".ts")).map(ruleModuleBase));
|
|
126
|
+
return modules.filter((f) => f.endsWith(".ts") || !sources.has(ruleModuleBase(f)));
|
|
119
127
|
}
|
|
120
128
|
function isLintRule(obj) {
|
|
121
129
|
if (typeof obj !== "object" || obj === null)
|
|
@@ -16,6 +16,7 @@ export { ops014 } from "./ops014-converge-rule-refusals.js";
|
|
|
16
16
|
export { ops015 } from "./ops015-gate-approval.js";
|
|
17
17
|
export { ops016 } from "./ops016-gate-resume.js";
|
|
18
18
|
export { ops017, ops017Check, workspaceIdentityGates } from "./ops017-gate-alias.js";
|
|
19
|
+
export { ops018 } from "./ops018-shell-image-digest.js";
|
|
19
20
|
export { sys010, sys010Check } from "./sys010-key-over-plain-http.js";
|
|
20
21
|
export interface CoreOpCheckOptions {
|
|
21
22
|
/** `decide.backends` from the project's chant.config, for SYS010 (#2828). */
|
|
@@ -25,7 +26,7 @@ export interface CoreOpCheckOptions {
|
|
|
25
26
|
}
|
|
26
27
|
/**
|
|
27
28
|
* Core's own post-synth checks over the Op model: OPS012, OPS013, OPS014,
|
|
28
|
-
* OPS015, OPS016, OPS017 over the workspace's `identity.gates`, and SYS010
|
|
29
|
+
* OPS015, OPS016, OPS017 over the workspace's `identity.gates`, OPS018, and SYS010
|
|
29
30
|
* over the `decide` steps and the configured decide backends.
|
|
30
31
|
*/
|
|
31
32
|
export declare function coreOpChecks(opts?: CoreOpCheckOptions): PostSynthCheck[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lint/rules/op/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lint/rules/op/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AASvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,iCAAiC,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAClF,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAEnE,MAAM,WAAW,kBAAkB;IACjC,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC;IACpE,6GAA6G;IAC7G,aAAa,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;CACpD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,GAAE,kBAAuB,GAAG,cAAc,EAAE,CAE5E"}
|
|
@@ -14,6 +14,7 @@ import { ops014 } from "./ops014-converge-rule-refusals.js";
|
|
|
14
14
|
import { ops015 } from "./ops015-gate-approval.js";
|
|
15
15
|
import { ops016 } from "./ops016-gate-resume.js";
|
|
16
16
|
import { ops017Check } from "./ops017-gate-alias.js";
|
|
17
|
+
import { ops018 } from "./ops018-shell-image-digest.js";
|
|
17
18
|
import { sys010Check } from "./sys010-key-over-plain-http.js";
|
|
18
19
|
export { ops012 } from "./ops012-activity-contract.js";
|
|
19
20
|
export { ops013 } from "./ops013-step-output-ref.js";
|
|
@@ -21,12 +22,13 @@ export { ops014 } from "./ops014-converge-rule-refusals.js";
|
|
|
21
22
|
export { ops015 } from "./ops015-gate-approval.js";
|
|
22
23
|
export { ops016 } from "./ops016-gate-resume.js";
|
|
23
24
|
export { ops017, ops017Check, workspaceIdentityGates } from "./ops017-gate-alias.js";
|
|
25
|
+
export { ops018 } from "./ops018-shell-image-digest.js";
|
|
24
26
|
export { sys010, sys010Check } from "./sys010-key-over-plain-http.js";
|
|
25
27
|
/**
|
|
26
28
|
* Core's own post-synth checks over the Op model: OPS012, OPS013, OPS014,
|
|
27
|
-
* OPS015, OPS016, OPS017 over the workspace's `identity.gates`, and SYS010
|
|
29
|
+
* OPS015, OPS016, OPS017 over the workspace's `identity.gates`, OPS018, and SYS010
|
|
28
30
|
* over the `decide` steps and the configured decide backends.
|
|
29
31
|
*/
|
|
30
32
|
export function coreOpChecks(opts = {}) {
|
|
31
|
-
return [ops012, ops013, ops014, ops015, ops016, ops017Check(opts.identityGates), sys010Check(opts.decideBackends)];
|
|
33
|
+
return [ops012, ops013, ops014, ops015, ops016, ops017Check(opts.identityGates), ops018, sys010Check(opts.decideBackends)];
|
|
32
34
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OPS018: a `shellCmd` step that runs in a container (#4015) names its image
|
|
3
|
+
* pinned by digest, `<ref>@sha256:<digest>`, as a literal string. A tag can
|
|
4
|
+
* move between two runs of the same Op, and then the step record's image no
|
|
5
|
+
* longer says what ran. Checked over the main phases, `onFailure`, and the
|
|
6
|
+
* steps inside an effect.
|
|
7
|
+
*/
|
|
8
|
+
import type { PostSynthCheck } from "../../post-synth.js";
|
|
9
|
+
export declare const ops018: PostSynthCheck;
|
|
10
|
+
//# sourceMappingURL=ops018-shell-image-digest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ops018-shell-image-digest.d.ts","sourceRoot":"","sources":["../../../../src/lint/rules/op/ops018-shell-image-digest.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,cAAc,EAAyC,MAAM,kBAAkB,CAAC;AAW9F,eAAO,MAAM,MAAM,EAAE,cA6BpB,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { imageProblem } from "../../../op/activities/shell.js";
|
|
2
|
+
import { isOpEntity } from "./support.js";
|
|
3
|
+
function activitySteps(steps) {
|
|
4
|
+
return steps.flatMap((step) => step.kind === "activity" ? [step] : step.kind === "effect" ? step.steps.filter((s) => s.kind === "activity") : []);
|
|
5
|
+
}
|
|
6
|
+
export const ops018 = {
|
|
7
|
+
id: "OPS018",
|
|
8
|
+
description: "A shell step with an image names it pinned by digest, as a literal string",
|
|
9
|
+
check(ctx) {
|
|
10
|
+
const diagnostics = [];
|
|
11
|
+
for (const [entityKey, entity] of ctx.entities) {
|
|
12
|
+
if (!isOpEntity(entity))
|
|
13
|
+
continue;
|
|
14
|
+
const rec = entity;
|
|
15
|
+
const props = (entity.props ?? {});
|
|
16
|
+
if (typeof props.name !== "string" || !Array.isArray(props.phases))
|
|
17
|
+
continue;
|
|
18
|
+
const phases = [...props.phases, ...(props.onFailure ?? [])];
|
|
19
|
+
for (const phase of phases) {
|
|
20
|
+
for (const step of activitySteps(phase.steps ?? [])) {
|
|
21
|
+
if (step.fn !== "shellCmd" || step.args?.image === undefined)
|
|
22
|
+
continue;
|
|
23
|
+
const problem = imageProblem(step.args.image);
|
|
24
|
+
if (!problem)
|
|
25
|
+
continue;
|
|
26
|
+
diagnostics.push({
|
|
27
|
+
checkId: "OPS018",
|
|
28
|
+
severity: "error",
|
|
29
|
+
message: `Op "${props.name}", phase "${phase.name}", shellCmd: ${problem}`,
|
|
30
|
+
entity: entityKey,
|
|
31
|
+
lexicon: typeof rec.lexicon === "string" ? rec.lexicon : undefined,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return diagnostics;
|
|
37
|
+
},
|
|
38
|
+
};
|