@intentius/chant 0.80.0 → 0.81.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/audit/discover.d.ts +8 -16
- package/dist/audit/discover.d.ts.map +1 -1
- package/dist/audit/report-html.d.ts +5 -0
- package/dist/audit/report-html.d.ts.map +1 -1
- package/dist/audit/report-model.d.ts +13 -0
- package/dist/audit/report-model.d.ts.map +1 -1
- package/dist/audit/terraform-state.d.ts +4 -5
- package/dist/audit/terraform-state.d.ts.map +1 -1
- package/dist/cli/commands/audit.d.ts +25 -9
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon.d.ts +8 -0
- package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/import-agents.d.ts.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/update.d.ts +6 -0
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/vendor.d.ts +5 -0
- package/dist/cli/commands/vendor.d.ts.map +1 -1
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/components.d.ts.map +1 -1
- package/dist/cli/handlers/dev.d.ts.map +1 -1
- package/dist/cli/handlers/fan-out.d.ts.map +1 -1
- package/dist/cli/handlers/init.d.ts.map +1 -1
- package/dist/cli/handlers/operator.d.ts +7 -0
- package/dist/cli/handlers/operator.d.ts.map +1 -1
- package/dist/cli/handlers/promote.d.ts +7 -4
- package/dist/cli/handlers/promote.d.ts.map +1 -1
- package/dist/cli/handlers/run-generate.d.ts.map +1 -1
- package/dist/cli/handlers/run.d.ts +4 -1
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/handlers/vendor.d.ts +8 -3
- package/dist/cli/handlers/vendor.d.ts.map +1 -1
- package/dist/cli/main.d.ts +12 -0
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/plugins.d.ts +12 -7
- package/dist/cli/plugins.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +32 -0
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/codegen/fetch.d.ts +10 -0
- package/dist/codegen/fetch.d.ts.map +1 -1
- package/dist/components/cli-support.d.ts +3 -1
- package/dist/components/cli-support.d.ts.map +1 -1
- package/dist/components/discover.d.ts.map +1 -1
- package/dist/components/driver.d.ts +16 -2
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/gate-plan.d.ts +40 -0
- package/dist/components/gate-plan.d.ts.map +1 -0
- package/dist/components/promote.d.ts +60 -7
- package/dist/components/promote.d.ts.map +1 -1
- package/dist/components/sandbox/driver.d.ts.map +1 -1
- package/dist/components/sandbox/run.d.ts.map +1 -1
- package/dist/components/verbs/build-archive.d.ts +22 -11
- package/dist/components/verbs/build-archive.d.ts.map +1 -1
- package/dist/components/verbs/run-agent.d.ts.map +1 -1
- package/dist/config-static.d.ts +59 -0
- package/dist/config-static.d.ts.map +1 -0
- package/dist/config.d.ts +32 -10
- package/dist/config.d.ts.map +1 -1
- package/dist/content-digest.d.ts +17 -0
- package/dist/content-digest.d.ts.map +1 -0
- package/dist/discovery/files.d.ts +10 -5
- package/dist/discovery/files.d.ts.map +1 -1
- package/dist/discovery/fold-import.d.ts +20 -4
- package/dist/discovery/fold-import.d.ts.map +1 -1
- package/dist/discovery/index.d.ts.map +1 -1
- package/dist/discovery/sandbox/driver.d.ts +20 -0
- package/dist/discovery/sandbox/driver.d.ts.map +1 -1
- package/dist/discovery/sandbox/fork.d.ts +20 -0
- package/dist/discovery/sandbox/fork.d.ts.map +1 -1
- package/dist/discovery/walk.d.ts +119 -0
- package/dist/discovery/walk.d.ts.map +1 -0
- package/dist/graph-ir.d.ts +4 -1
- package/dist/graph-ir.d.ts.map +1 -1
- package/dist/join-key.d.ts +31 -0
- package/dist/join-key.d.ts.map +1 -0
- package/dist/lexicon-module.d.ts +51 -6
- package/dist/lexicon-module.d.ts.map +1 -1
- package/dist/lexicon.d.ts +58 -1
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/build-ledger-store.d.ts.map +1 -1
- package/dist/lifecycle/digest.d.ts +5 -1
- package/dist/lifecycle/digest.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.d.ts +20 -5
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/git.d.ts +64 -0
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lifecycle/lease.d.ts +8 -1
- package/dist/lifecycle/lease.d.ts.map +1 -1
- package/dist/lifecycle/legacy-digest.d.ts +41 -8
- package/dist/lifecycle/legacy-digest.d.ts.map +1 -1
- package/dist/lifecycle/member-ledger.d.ts +67 -0
- package/dist/lifecycle/member-ledger.d.ts.map +1 -0
- package/dist/lifecycle/plan-digest.d.ts +4 -3
- package/dist/lifecycle/plan-digest.d.ts.map +1 -1
- package/dist/lifecycle/release-ledger.d.ts +18 -2
- package/dist/lifecycle/release-ledger.d.ts.map +1 -1
- package/dist/lifecycle/status.d.ts +90 -5
- package/dist/lifecycle/status.d.ts.map +1 -1
- package/dist/op/activities/activity-contracts.d.ts +32 -0
- package/dist/op/activities/activity-contracts.d.ts.map +1 -1
- package/dist/op/activities/index.d.ts +2 -0
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/activities/propose-upgrade.d.ts +75 -0
- package/dist/op/activities/propose-upgrade.d.ts.map +1 -0
- package/dist/op/discover.d.ts.map +1 -1
- package/dist/op/gate-name.d.ts +7 -0
- package/dist/op/gate-name.d.ts.map +1 -1
- package/dist/op/gate-summary.d.ts +16 -0
- package/dist/op/gate-summary.d.ts.map +1 -1
- package/dist/op/gate.d.ts +16 -2
- package/dist/op/gate.d.ts.map +1 -1
- package/dist/project-root.d.ts +26 -0
- package/dist/project-root.d.ts.map +1 -1
- package/dist/workspace/__fixtures__/contract-repo.d.ts +37 -0
- package/dist/workspace/__fixtures__/contract-repo.d.ts.map +1 -0
- package/dist/workspace/__fixtures__/two-member-workspace.d.ts +11 -0
- package/dist/workspace/__fixtures__/two-member-workspace.d.ts.map +1 -0
- package/dist/workspace/checks/generated.d.ts +156 -0
- package/dist/workspace/checks/generated.d.ts.map +1 -0
- package/dist/workspace/checks/ledgers.d.ts +78 -0
- package/dist/workspace/checks/ledgers.d.ts.map +1 -0
- package/dist/workspace/checks/links.d.ts +25 -0
- package/dist/workspace/checks/links.d.ts.map +1 -0
- package/dist/workspace/checks/pipelines.d.ts +76 -0
- package/dist/workspace/checks/pipelines.d.ts.map +1 -0
- package/dist/workspace/checks.d.ts +161 -0
- package/dist/workspace/checks.d.ts.map +1 -0
- package/dist/workspace/compose-graph.d.ts +115 -0
- package/dist/workspace/compose-graph.d.ts.map +1 -0
- package/dist/workspace/compose-reports.d.ts +68 -0
- package/dist/workspace/compose-reports.d.ts.map +1 -0
- package/dist/workspace/declaration.d.ts +220 -0
- package/dist/workspace/declaration.d.ts.map +1 -0
- package/dist/workspace/declaration.schema.json +434 -0
- package/dist/workspace/generated-files.d.ts +65 -0
- package/dist/workspace/generated-files.d.ts.map +1 -0
- package/dist/workspace/glob.d.ts +13 -0
- package/dist/workspace/glob.d.ts.map +1 -0
- package/dist/workspace/graph-cli.d.ts +75 -0
- package/dist/workspace/graph-cli.d.ts.map +1 -0
- package/dist/workspace/init.d.ts +96 -0
- package/dist/workspace/init.d.ts.map +1 -0
- package/dist/workspace/jsonc.d.ts +38 -0
- package/dist/workspace/jsonc.d.ts.map +1 -0
- package/dist/workspace/kinds.d.ts +192 -0
- package/dist/workspace/kinds.d.ts.map +1 -0
- package/dist/workspace/lineage-check.d.ts +84 -0
- package/dist/workspace/lineage-check.d.ts.map +1 -0
- package/dist/workspace/lineage-cli.d.ts +31 -0
- package/dist/workspace/lineage-cli.d.ts.map +1 -0
- package/dist/workspace/lineage-init.d.ts +101 -0
- package/dist/workspace/lineage-init.d.ts.map +1 -0
- package/dist/workspace/lineage-lock.d.ts +258 -0
- package/dist/workspace/lineage-lock.d.ts.map +1 -0
- package/dist/workspace/lineage-merge.d.ts +14 -0
- package/dist/workspace/lineage-merge.d.ts.map +1 -0
- package/dist/workspace/lineage-migrations.d.ts +178 -0
- package/dist/workspace/lineage-migrations.d.ts.map +1 -0
- package/dist/workspace/lineage-update.d.ts +59 -0
- package/dist/workspace/lineage-update.d.ts.map +1 -0
- package/dist/workspace/lineage-upgrade-cli.d.ts +40 -0
- package/dist/workspace/lineage-upgrade-cli.d.ts.map +1 -0
- package/dist/workspace/lineage-upgrade.d.ts +146 -0
- package/dist/workspace/lineage-upgrade.d.ts.map +1 -0
- package/dist/workspace/lineage-vendor.d.ts +63 -0
- package/dist/workspace/lineage-vendor.d.ts.map +1 -0
- package/dist/workspace/lineage-version.d.ts +32 -0
- package/dist/workspace/lineage-version.d.ts.map +1 -0
- package/dist/workspace/links.d.ts +150 -0
- package/dist/workspace/links.d.ts.map +1 -0
- package/dist/workspace/ls.d.ts +99 -0
- package/dist/workspace/ls.d.ts.map +1 -0
- package/dist/workspace/member-commands.d.ts +139 -0
- package/dist/workspace/member-commands.d.ts.map +1 -0
- package/dist/workspace/member-handles.d.ts +54 -0
- package/dist/workspace/member-handles.d.ts.map +1 -0
- package/dist/workspace/member-pipeline.d.ts +143 -0
- package/dist/workspace/member-pipeline.d.ts.map +1 -0
- package/dist/workspace/member-run.d.ts +67 -0
- package/dist/workspace/member-run.d.ts.map +1 -0
- package/dist/workspace/reason-codes.d.ts +65 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -0
- package/dist/workspace/records-cli.d.ts +28 -4
- package/dist/workspace/records-cli.d.ts.map +1 -1
- package/dist/workspace/records.d.ts.map +1 -1
- package/dist/workspace/root-refusal.d.ts +53 -0
- package/dist/workspace/root-refusal.d.ts.map +1 -0
- package/dist/workspace/status.d.ts +150 -0
- package/dist/workspace/status.d.ts.map +1 -0
- package/dist/workspace/template-manifest.d.ts +90 -0
- package/dist/workspace/template-manifest.d.ts.map +1 -0
- package/dist/workspace/tree.d.ts +36 -0
- package/dist/workspace/tree.d.ts.map +1 -0
- package/dist/workspace/trust/attestor.d.ts +67 -0
- package/dist/workspace/trust/attestor.d.ts.map +1 -0
- package/dist/workspace/trust/policy.d.ts +111 -0
- package/dist/workspace/trust/policy.d.ts.map +1 -0
- package/dist/workspace/trust/provenance.d.ts +67 -0
- package/dist/workspace/trust/provenance.d.ts.map +1 -0
- package/dist/workspace/trust/ssh-commit.d.ts +43 -0
- package/dist/workspace/trust/ssh-commit.d.ts.map +1 -0
- package/dist/workspace/trust/test-repo.d.ts +42 -0
- package/dist/workspace/trust/test-repo.d.ts.map +1 -0
- package/dist/workspace/trust/verify-cli.d.ts +9 -0
- package/dist/workspace/trust/verify-cli.d.ts.map +1 -0
- package/dist/workspace/trust/verify.d.ts +66 -0
- package/dist/workspace/trust/verify.d.ts.map +1 -0
- package/dist/workspace/which-chant.d.ts +58 -0
- package/dist/workspace/which-chant.d.ts.map +1 -0
- package/dist/workspace/workspace-kinds.schema.json +133 -0
- package/package.json +2 -1
- package/src/audit/discover.ts +66 -78
- package/src/audit/report-html.ts +3 -1
- package/src/audit/report-model.ts +14 -1
- package/src/audit/terraform-state.test.ts +4 -9
- package/src/audit/terraform-state.ts +4 -5
- package/src/cli/commands/audit-truncation.test.ts +167 -0
- package/src/cli/commands/audit.ts +89 -60
- package/src/cli/commands/check-lexicon.ts +24 -0
- package/src/cli/commands/doctor.test.ts +30 -0
- package/src/cli/commands/doctor.ts +18 -0
- package/src/cli/commands/import-agents.ts +6 -2
- package/src/cli/commands/init.ts +22 -3
- package/src/cli/commands/lint.test.ts +17 -23
- package/src/cli/commands/lint.ts +24 -84
- package/src/cli/commands/update.ts +13 -4
- package/src/cli/commands/vendor.ts +11 -6
- package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +38 -0
- package/src/cli/handlers/build-member.test.ts +127 -0
- package/src/cli/handlers/build.ts +35 -1
- package/src/cli/handlers/components.test.ts +127 -0
- package/src/cli/handlers/components.ts +70 -8
- package/src/cli/handlers/dev.ts +5 -3
- package/src/cli/handlers/fan-out.ts +9 -2
- package/src/cli/handlers/init.ts +54 -1
- package/src/cli/handlers/operator.test.ts +68 -0
- package/src/cli/handlers/operator.ts +37 -9
- package/src/cli/handlers/promote.test.ts +118 -2
- package/src/cli/handlers/promote.ts +82 -16
- package/src/cli/handlers/run-generate-member.test.ts +83 -0
- package/src/cli/handlers/run-generate.test.ts +6 -8
- package/src/cli/handlers/run-generate.ts +36 -1
- package/src/cli/handlers/run.test.ts +47 -0
- package/src/cli/handlers/run.ts +28 -5
- package/src/cli/handlers/vendor.ts +147 -43
- package/src/cli/main.test.ts +105 -1
- package/src/cli/main.ts +230 -17
- package/src/cli/plugins.ts +17 -17
- package/src/cli/registry.ts +32 -0
- package/src/cli/static-config-read.test.ts +208 -0
- package/src/codegen/fetch.test.ts +63 -1
- package/src/codegen/fetch.ts +30 -1
- package/src/components/cli-support.ts +6 -1
- package/src/components/discover.test.ts +27 -57
- package/src/components/discover.ts +13 -68
- package/src/components/driver.test.ts +78 -1
- package/src/components/driver.ts +43 -7
- package/src/components/gate-plan.ts +53 -0
- package/src/components/promote.test.ts +276 -2
- package/src/components/promote.ts +119 -15
- package/src/components/sandbox/driver.ts +8 -8
- package/src/components/sandbox/run.ts +4 -1
- package/src/components/verbs/build-archive.ts +27 -21
- package/src/components/verbs/run-agent.ts +3 -5
- package/src/config-static.test.ts +136 -0
- package/src/config-static.ts +232 -0
- package/src/config.test.ts +2 -2
- package/src/config.ts +48 -15
- package/src/content-digest.test.ts +120 -0
- package/src/content-digest.ts +21 -0
- package/src/discovery/files.test.ts +10 -10
- package/src/discovery/files.ts +25 -81
- package/src/discovery/fold-import.ts +49 -5
- package/src/discovery/index.ts +1 -0
- package/src/discovery/sandbox/driver.ts +73 -35
- package/src/discovery/sandbox/fork-diagnostic.test.ts +136 -13
- package/src/discovery/sandbox/fork.ts +83 -43
- package/src/discovery/sandbox/path-lexicon-multifile.test.ts +285 -0
- package/src/discovery/walk.test.ts +263 -0
- package/src/discovery/walk.ts +334 -0
- package/src/effect-receipt.ts +2 -2
- package/src/graph-ir.ts +4 -1
- package/src/join-key.test.ts +25 -0
- package/src/join-key.ts +39 -0
- package/src/lexicon-module.ts +108 -10
- package/src/lexicon.ts +79 -1
- package/src/lifecycle/build-ledger-store.ts +11 -10
- package/src/lifecycle/digest.ts +9 -5
- package/src/lifecycle/gate-ledger.test.ts +20 -0
- package/src/lifecycle/gate-ledger.ts +28 -6
- package/src/lifecycle/git.test.ts +13 -1
- package/src/lifecycle/git.ts +221 -176
- package/src/lifecycle/lease.ts +25 -10
- package/src/lifecycle/legacy-digest.test.ts +115 -23
- package/src/lifecycle/legacy-digest.ts +60 -19
- package/src/lifecycle/member-ledger.test.ts +319 -0
- package/src/lifecycle/member-ledger.ts +145 -0
- package/src/lifecycle/plan-digest.ts +7 -7
- package/src/lifecycle/release-ledger.test.ts +20 -0
- package/src/lifecycle/release-ledger.ts +23 -7
- package/src/lifecycle/status.test.ts +151 -1
- package/src/lifecycle/status.ts +228 -7
- package/src/op/activities/activity-contracts.ts +37 -0
- package/src/op/activities/index.ts +10 -0
- package/src/op/activities/propose-upgrade.ts +206 -0
- package/src/op/discover.test.ts +14 -4
- package/src/op/discover.ts +19 -27
- package/src/op/gate-name.ts +8 -0
- package/src/op/gate-summary.test.ts +14 -0
- package/src/op/gate-summary.ts +25 -2
- package/src/op/gate.ts +36 -7
- package/src/op/generate-pipeline.test.ts +14 -5
- package/src/project-root.test.ts +66 -1
- package/src/project-root.ts +48 -0
- package/src/workspace/__fixtures__/contract-repo.ts +100 -0
- package/src/workspace/__fixtures__/two-member-workspace.ts +35 -0
- package/src/workspace/behold-kinds.test.ts +162 -0
- package/src/workspace/check-contract.test.ts +127 -0
- package/src/workspace/check.schema.json +347 -0
- package/src/workspace/checks/generated.test.ts +287 -0
- package/src/workspace/checks/generated.ts +475 -0
- package/src/workspace/checks/ledgers.test.ts +139 -0
- package/src/workspace/checks/ledgers.ts +246 -0
- package/src/workspace/checks/links.ts +183 -0
- package/src/workspace/checks/pipelines.test.ts +133 -0
- package/src/workspace/checks/pipelines.ts +225 -0
- package/src/workspace/checks-repo.test.ts +71 -0
- package/src/workspace/checks.test.ts +450 -0
- package/src/workspace/checks.ts +461 -0
- package/src/workspace/compose-graph.test.ts +146 -0
- package/src/workspace/compose-graph.ts +228 -0
- package/src/workspace/compose-reports.test.ts +109 -0
- package/src/workspace/compose-reports.ts +186 -0
- package/src/workspace/declaration.schema.json +434 -0
- package/src/workspace/declaration.test.ts +347 -0
- package/src/workspace/declaration.ts +623 -0
- package/src/workspace/generated-files.test.ts +114 -0
- package/src/workspace/generated-files.ts +94 -0
- package/src/workspace/glob.ts +49 -0
- package/src/workspace/graph-cli.ts +220 -0
- package/src/workspace/graph-contract.test.ts +204 -0
- package/src/workspace/graph.schema.json +662 -0
- package/src/workspace/init.test.ts +223 -0
- package/src/workspace/init.ts +585 -0
- package/src/workspace/jsonc.test.ts +65 -0
- package/src/workspace/jsonc.ts +231 -0
- package/src/workspace/kinds.test.ts +288 -0
- package/src/workspace/kinds.ts +506 -0
- package/src/workspace/lineage-check.ts +264 -0
- package/src/workspace/lineage-cli.ts +114 -0
- package/src/workspace/lineage-init.test.ts +231 -0
- package/src/workspace/lineage-init.ts +365 -0
- package/src/workspace/lineage-lock.test.ts +224 -0
- package/src/workspace/lineage-lock.ts +357 -0
- package/src/workspace/lineage-merge.ts +44 -0
- package/src/workspace/lineage-migrations.test.ts +178 -0
- package/src/workspace/lineage-migrations.ts +343 -0
- package/src/workspace/lineage-update.ts +160 -0
- package/src/workspace/lineage-upgrade-cli.ts +151 -0
- package/src/workspace/lineage-upgrade.test.ts +474 -0
- package/src/workspace/lineage-upgrade.ts +624 -0
- package/src/workspace/lineage-vendor.test.ts +126 -0
- package/src/workspace/lineage-vendor.ts +215 -0
- package/src/workspace/lineage-version.ts +127 -0
- package/src/workspace/links.test.ts +344 -0
- package/src/workspace/links.ts +331 -0
- package/src/workspace/ls-contract.test.ts +200 -0
- package/src/workspace/ls.schema.json +190 -0
- package/src/workspace/ls.ts +254 -0
- package/src/workspace/member-commands.e2e.test.ts +244 -0
- package/src/workspace/member-commands.test.ts +217 -0
- package/src/workspace/member-commands.ts +540 -0
- package/src/workspace/member-handles.test.ts +76 -0
- package/src/workspace/member-handles.ts +228 -0
- package/src/workspace/member-pipeline.test.ts +135 -0
- package/src/workspace/member-pipeline.ts +317 -0
- package/src/workspace/member-run.ts +146 -0
- package/src/workspace/read-contract.test.ts +129 -0
- package/src/workspace/reason-codes.test.ts +113 -0
- package/src/workspace/reason-codes.ts +81 -0
- package/src/workspace/records-cli.ts +86 -14
- package/src/workspace/records-contract.test.ts +5 -0
- package/src/workspace/records.schema.json +32 -2
- package/src/workspace/records.ts +3 -2
- package/src/workspace/root-refusal.ts +97 -0
- package/src/workspace/status-contract.test.ts +308 -0
- package/src/workspace/status.schema.json +210 -0
- package/src/workspace/status.ts +412 -0
- package/src/workspace/template-manifest.test.ts +79 -0
- package/src/workspace/template-manifest.ts +221 -0
- package/src/workspace/tree.ts +132 -0
- package/src/workspace/trust/attestor.ts +93 -0
- package/src/workspace/trust/policy.ts +306 -0
- package/src/workspace/trust/provenance.ts +181 -0
- package/src/workspace/trust/ssh-commit.ts +138 -0
- package/src/workspace/trust/test-repo.ts +138 -0
- package/src/workspace/trust/trust.test.ts +397 -0
- package/src/workspace/trust/verify-cli.ts +56 -0
- package/src/workspace/trust/verify.ts +194 -0
- package/src/workspace/which-chant.test.ts +117 -0
- package/src/workspace/which-chant.ts +151 -0
- package/src/workspace/workspace-kinds.schema.json +133 -0
- package/dist/components/unbound-gate-approval.d.ts +0 -24
- package/dist/components/unbound-gate-approval.d.ts.map +0 -1
- package/dist/discovery/convergence.d.ts +0 -97
- package/dist/discovery/convergence.d.ts.map +0 -1
- package/src/cli/commands/audit-walk-warnings.test.ts +0 -156
- package/src/components/unbound-gate-approval.test.ts +0 -82
- package/src/components/unbound-gate-approval.ts +0 -51
- package/src/discovery/convergence.test.ts +0 -231
- package/src/discovery/convergence.ts +0 -399
- package/src/op/discover-convergence.test.ts +0 -70
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* chant#2591, chant#2589 — `init --force`, `dev onboard`, `import --agents`
|
|
3
|
+
* and `audit` learn the lexicons a project declares by path without running
|
|
4
|
+
* its `chant.config.ts`.
|
|
5
|
+
*
|
|
6
|
+
* The CLI is spawned the way `bin/chant` runs it, because `main.ts` loads the
|
|
7
|
+
* config before dispatch for most commands, and a test calling the command
|
|
8
|
+
* functions would miss that load. Each fixture's config writes a marker file
|
|
9
|
+
* when it runs. The marker must never appear, and each command's output must
|
|
10
|
+
* still name the lexicon's path.
|
|
11
|
+
*/
|
|
12
|
+
import { describe, test, expect, beforeEach, afterEach } from "vitest";
|
|
13
|
+
import { spawnSync } from "node:child_process";
|
|
14
|
+
import { existsSync, mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
15
|
+
import { tmpdir } from "node:os";
|
|
16
|
+
import { dirname, join, resolve } from "node:path";
|
|
17
|
+
import { fileURLToPath } from "node:url";
|
|
18
|
+
import { auditCommand } from "./commands/audit";
|
|
19
|
+
import { runCommandInProcess } from "./main";
|
|
20
|
+
import { resetLexiconModules } from "../lexicon-module";
|
|
21
|
+
import { captureRun } from "../workspace/member-run";
|
|
22
|
+
|
|
23
|
+
const thisDir = dirname(fileURLToPath(import.meta.url));
|
|
24
|
+
const mainTs = resolve(thisDir, "main.ts");
|
|
25
|
+
const repoRoot = resolve(thisDir, "../../../..");
|
|
26
|
+
const tsxLoader = join(repoRoot, "node_modules", "tsx", "dist", "loader.mjs");
|
|
27
|
+
|
|
28
|
+
let root: string;
|
|
29
|
+
let project: string;
|
|
30
|
+
let marker: string;
|
|
31
|
+
let home: string;
|
|
32
|
+
let moduleMarker: string;
|
|
33
|
+
|
|
34
|
+
function writeConfig(lexicons: string): void {
|
|
35
|
+
writeFileSync(
|
|
36
|
+
join(project, "chant.config.ts"),
|
|
37
|
+
`import { writeFileSync } from "node:fs";\n` +
|
|
38
|
+
`writeFileSync(${JSON.stringify(marker)}, "ran");\n` +
|
|
39
|
+
`export default { lexicons: ${lexicons} };\n`,
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
beforeEach(() => {
|
|
44
|
+
resetLexiconModules();
|
|
45
|
+
root = realpathSync(mkdtempSync(join(tmpdir(), "chant-2591-cli-")));
|
|
46
|
+
project = join(root, "project");
|
|
47
|
+
marker = join(root, "config-ran");
|
|
48
|
+
home = join(root, "home");
|
|
49
|
+
moduleMarker = join(root, "module-ran");
|
|
50
|
+
mkdirSync(join(project, ".github", "workflows"), { recursive: true });
|
|
51
|
+
mkdirSync(join(project, "gh"), { recursive: true });
|
|
52
|
+
mkdirSync(join(project, ".git"));
|
|
53
|
+
// The path lexicon's module is project code too. Audit must never import it.
|
|
54
|
+
writeFileSync(
|
|
55
|
+
join(project, "gh", "index.ts"),
|
|
56
|
+
`import { writeFileSync } from "node:fs";\nwriteFileSync(${JSON.stringify(moduleMarker)}, "ran");\nexport {};\n`,
|
|
57
|
+
);
|
|
58
|
+
writeFileSync(
|
|
59
|
+
join(project, ".github", "workflows", "ci.yml"),
|
|
60
|
+
"on: push\njobs:\n a:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n",
|
|
61
|
+
);
|
|
62
|
+
mkdirSync(join(home, ".claude"), { recursive: true });
|
|
63
|
+
writeFileSync(join(home, ".claude", "mcp.json"), JSON.stringify({ mcpServers: { a: { command: "x" } } }));
|
|
64
|
+
writeConfig(`[{ name: "github", module: "./gh/index.ts" }]`);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
afterEach(() => {
|
|
68
|
+
resetLexiconModules();
|
|
69
|
+
rmSync(root, { recursive: true, force: true });
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
function chant(args: string[], cwd: string): string {
|
|
73
|
+
const result = spawnSync(process.execPath, ["--import", tsxLoader, mainTs, ...args], {
|
|
74
|
+
cwd,
|
|
75
|
+
env: { PATH: process.env.PATH ?? "", HOME: home },
|
|
76
|
+
encoding: "utf-8",
|
|
77
|
+
input: "n\n",
|
|
78
|
+
timeout: 60_000,
|
|
79
|
+
});
|
|
80
|
+
return `${result.stdout}\n${result.stderr}`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const COMMANDS: Array<{ name: string; args: () => string[]; cwd: () => string }> = [
|
|
84
|
+
{ name: "init --force", args: () => ["init", project, "--lexicon", "github", "--force", "--skip-mcp"], cwd: () => root },
|
|
85
|
+
{ name: "dev onboard", args: () => ["dev", "onboard", "github"], cwd: () => project },
|
|
86
|
+
{ name: "import --agents", args: () => ["import", "--agents", "--lexicon", "github", "--output", join(root, "out")], cwd: () => project },
|
|
87
|
+
];
|
|
88
|
+
|
|
89
|
+
describe("commands that read path lexicons statically run no project code", () => {
|
|
90
|
+
for (const command of COMMANDS) {
|
|
91
|
+
for (const sandbox of [false, true]) {
|
|
92
|
+
test(`${command.name}${sandbox ? " --sandbox" : ""} names the path and never runs chant.config.ts`, () => {
|
|
93
|
+
const output = chant([...command.args(), ...(sandbox ? ["--sandbox"] : [])], command.cwd());
|
|
94
|
+
expect(output).toContain("./gh/index.ts");
|
|
95
|
+
expect(existsSync(marker)).toBe(false);
|
|
96
|
+
}, 90_000);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
test("audit never runs chant.config.ts or the path lexicon's module", () => {
|
|
101
|
+
chant(["audit", project], root);
|
|
102
|
+
expect(existsSync(marker)).toBe(false);
|
|
103
|
+
expect(existsSync(moduleMarker)).toBe(false);
|
|
104
|
+
}, 90_000);
|
|
105
|
+
|
|
106
|
+
test("a config it cannot read is reported, and still not run", () => {
|
|
107
|
+
writeConfig(`process.env.CI ? ["github"] : [{ name: "github", module: "./gh/index.ts" }]`);
|
|
108
|
+
const output = chant(["dev", "onboard", "github"], project);
|
|
109
|
+
expect(output).toContain("could not read the lexicons in");
|
|
110
|
+
expect(output).toContain("treated as a package");
|
|
111
|
+
expect(existsSync(marker)).toBe(false);
|
|
112
|
+
|
|
113
|
+
const audit = chant(["audit", project], root);
|
|
114
|
+
expect(audit).toContain("could not read the lexicons in");
|
|
115
|
+
expect(existsSync(marker)).toBe(false);
|
|
116
|
+
}, 180_000);
|
|
117
|
+
|
|
118
|
+
test("control: build does run chant.config.ts", () => {
|
|
119
|
+
chant(["build", "."], project);
|
|
120
|
+
expect(existsSync(marker)).toBe(true);
|
|
121
|
+
}, 90_000);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
describe("audit names a path lexicon by its path and leaves it out of the install line (chant#2589)", () => {
|
|
125
|
+
test("text output", async () => {
|
|
126
|
+
const result = await auditCommand({ path: project, plugins: [] });
|
|
127
|
+
expect(result.status).toBe("no-lexicons");
|
|
128
|
+
expect(result.output).toContain("github is declared by path: ");
|
|
129
|
+
expect(result.output).toContain("gh/index.ts");
|
|
130
|
+
const install = result.output.split("\n").find((line) => line.includes("npx "));
|
|
131
|
+
expect(install).toBeDefined();
|
|
132
|
+
expect(install).not.toContain("@intentius/chant-lexicon-github");
|
|
133
|
+
expect(existsSync(marker)).toBe(false);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test("json output", async () => {
|
|
137
|
+
const result = await auditCommand({ path: project, plugins: [], format: "json" });
|
|
138
|
+
const report = JSON.parse(result.output) as { install: string };
|
|
139
|
+
expect(report.install).toMatch(/^npx -p @intentius\/chant( |$)/);
|
|
140
|
+
expect(report.install).not.toContain("@intentius/chant-lexicon-github");
|
|
141
|
+
expect(existsSync(marker)).toBe(false);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test("a partial run names the path in its coverage note", async () => {
|
|
145
|
+
// Some other audit lexicon loaded, github not: the workflow is skipped and the note names the path.
|
|
146
|
+
const { loadPlugin } = await import("./plugins");
|
|
147
|
+
const docker = await loadPlugin("docker");
|
|
148
|
+
const result = await auditCommand({ path: project, plugins: [docker] });
|
|
149
|
+
expect(result.output).toContain("github is declared by path: ");
|
|
150
|
+
expect(result.output).not.toContain("npm i @intentius/chant-lexicon-github");
|
|
151
|
+
expect(existsSync(marker)).toBe(false);
|
|
152
|
+
expect(existsSync(moduleMarker)).toBe(false);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* chant#2618 — the other ways into `audit`: main's dispatch run in-process
|
|
158
|
+
* (what `workspace member-run` calls once per member), and `workspace audit`
|
|
159
|
+
* through the CLI, which reaches it through that member-run process.
|
|
160
|
+
*/
|
|
161
|
+
describe("chant audit never evaluates the audited repository's config (chant#2618)", () => {
|
|
162
|
+
test("main's in-process dispatch runs neither the config nor the path lexicon's module", async () => {
|
|
163
|
+
const run = await captureRun(() => runCommandInProcess(["audit", project]));
|
|
164
|
+
expect(run.exitCode).toBe(0);
|
|
165
|
+
expect(existsSync(marker)).toBe(false);
|
|
166
|
+
expect(existsSync(moduleMarker)).toBe(false);
|
|
167
|
+
}, 90_000);
|
|
168
|
+
|
|
169
|
+
test("workspace audit runs no member's config and no path lexicon's module", () => {
|
|
170
|
+
// The project becomes the root member of a workspace, with a second
|
|
171
|
+
// member whose config and path lexicon leave markers of their own.
|
|
172
|
+
const apiMarker = join(root, "api-config-ran");
|
|
173
|
+
const apiModuleMarker = join(root, "api-module-ran");
|
|
174
|
+
const api = join(project, "api");
|
|
175
|
+
mkdirSync(join(api, ".github", "workflows"), { recursive: true });
|
|
176
|
+
mkdirSync(join(api, "gh"), { recursive: true });
|
|
177
|
+
writeFileSync(
|
|
178
|
+
join(api, "chant.config.ts"),
|
|
179
|
+
`import { writeFileSync } from "node:fs";\nwriteFileSync(${JSON.stringify(apiMarker)}, "ran");\n` +
|
|
180
|
+
`export default { lexicons: [{ name: "github", module: "./gh/index.ts" }] };\n`,
|
|
181
|
+
);
|
|
182
|
+
writeFileSync(
|
|
183
|
+
join(api, "gh", "index.ts"),
|
|
184
|
+
`import { writeFileSync } from "node:fs";\nwriteFileSync(${JSON.stringify(apiModuleMarker)}, "ran");\nexport {};\n`,
|
|
185
|
+
);
|
|
186
|
+
writeFileSync(
|
|
187
|
+
join(api, ".github", "workflows", "ci.yml"),
|
|
188
|
+
"on: push\njobs:\n a:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n",
|
|
189
|
+
);
|
|
190
|
+
writeFileSync(
|
|
191
|
+
join(project, "chant.workspace.json"),
|
|
192
|
+
JSON.stringify({
|
|
193
|
+
name: "acme",
|
|
194
|
+
schema: 1,
|
|
195
|
+
members: [
|
|
196
|
+
{ name: "root", dir: ".", kind: "chant" },
|
|
197
|
+
{ name: "api", dir: "api", kind: "chant" },
|
|
198
|
+
],
|
|
199
|
+
}),
|
|
200
|
+
);
|
|
201
|
+
const output = chant(["workspace", "audit", "--json"], project);
|
|
202
|
+
expect(output).toContain('"api"');
|
|
203
|
+
expect(existsSync(marker)).toBe(false);
|
|
204
|
+
expect(existsSync(moduleMarker)).toBe(false);
|
|
205
|
+
expect(existsSync(apiMarker)).toBe(false);
|
|
206
|
+
expect(existsSync(apiModuleMarker)).toBe(false);
|
|
207
|
+
}, 180_000);
|
|
208
|
+
});
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { describe, test, expect, vi, afterEach } from "vitest";
|
|
2
|
-
import { extractFromTar, fetchWithRetry, TransientFetchError } from "./fetch";
|
|
2
|
+
import { extractFromTar, fetchWithCache, fetchWithRetry, TransientFetchError } from "./fetch";
|
|
3
|
+
import { mkdtempSync, utimesSync, writeFileSync } from "fs";
|
|
4
|
+
import { tmpdir } from "os";
|
|
5
|
+
import { join } from "path";
|
|
3
6
|
|
|
4
7
|
/**
|
|
5
8
|
* Build a minimal valid tar buffer with a single file entry.
|
|
@@ -318,3 +321,62 @@ describe("fetchWithRetry", () => {
|
|
|
318
321
|
expect((err as TransientFetchError).message).toContain("1 attempt");
|
|
319
322
|
});
|
|
320
323
|
});
|
|
324
|
+
|
|
325
|
+
describe("fetchWithCache", () => {
|
|
326
|
+
afterEach(() => {
|
|
327
|
+
vi.unstubAllGlobals();
|
|
328
|
+
vi.restoreAllMocks();
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
function cacheAt(ageMs: number, content = "stale bytes"): string {
|
|
332
|
+
const file = join(mkdtempSync(join(tmpdir(), "chant-fetch-cache-")), "spec.bin");
|
|
333
|
+
writeFileSync(file, content);
|
|
334
|
+
const then = (Date.now() - ageMs) / 1000;
|
|
335
|
+
utimesSync(file, then, then);
|
|
336
|
+
return file;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
test("returns the stale cached copy when every download attempt fails transiently", async () => {
|
|
340
|
+
const cacheFile = cacheAt(2 * 24 * 60 * 60 * 1000);
|
|
341
|
+
const fetchMock = vi.fn().mockRejectedValue(new Error("ECONNRESET"));
|
|
342
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
343
|
+
const errors: string[] = [];
|
|
344
|
+
vi.spyOn(console, "error").mockImplementation((m: unknown) => { errors.push(String(m)); });
|
|
345
|
+
|
|
346
|
+
const data = await fetchWithCache({ url: "https://example.test/spec", cacheFile, retries: 1, backoffMs: 1 });
|
|
347
|
+
|
|
348
|
+
expect(data.toString()).toBe("stale bytes");
|
|
349
|
+
expect(fetchMock).toHaveBeenCalledTimes(2);
|
|
350
|
+
expect(errors.join("\n")).toContain("Using the cached copy");
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
test("force ignores the stale copy and throws", async () => {
|
|
354
|
+
const cacheFile = cacheAt(2 * 24 * 60 * 60 * 1000);
|
|
355
|
+
vi.stubGlobal("fetch", vi.fn().mockRejectedValue(new Error("ECONNRESET")));
|
|
356
|
+
|
|
357
|
+
await expect(
|
|
358
|
+
fetchWithCache({ url: "https://example.test/spec", cacheFile, retries: 1, backoffMs: 1 }, true),
|
|
359
|
+
).rejects.toBeInstanceOf(TransientFetchError);
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
test("a permanent failure with a stale copy still throws", async () => {
|
|
363
|
+
const cacheFile = cacheAt(2 * 24 * 60 * 60 * 1000);
|
|
364
|
+
vi.stubGlobal("fetch", vi.fn().mockResolvedValue(new Response("gone", { status: 404 })));
|
|
365
|
+
|
|
366
|
+
await expect(
|
|
367
|
+
fetchWithCache({ url: "https://example.test/spec", cacheFile, retries: 1, backoffMs: 1 }),
|
|
368
|
+
).rejects.toThrow();
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
test("passes attemptTimeoutMs through as the attempt signal", async () => {
|
|
372
|
+
const cacheFile = cacheAt(2 * 24 * 60 * 60 * 1000);
|
|
373
|
+
const fetchMock = vi.fn().mockResolvedValue(new Response("fresh"));
|
|
374
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
375
|
+
|
|
376
|
+
const data = await fetchWithCache({ url: "https://example.test/spec", cacheFile, attemptTimeoutMs: 120_000 });
|
|
377
|
+
|
|
378
|
+
expect(data.toString()).toBe("fresh");
|
|
379
|
+
const init = fetchMock.mock.calls[0][1] as RequestInit;
|
|
380
|
+
expect(init.signal).toBeInstanceOf(AbortSignal);
|
|
381
|
+
});
|
|
382
|
+
});
|
package/src/codegen/fetch.ts
CHANGED
|
@@ -18,6 +18,16 @@ export interface FetchConfig {
|
|
|
18
18
|
cacheFile: string;
|
|
19
19
|
/** Cache TTL in milliseconds (default: 24 hours). */
|
|
20
20
|
cacheTtlMs?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Per-attempt timeout for the download in milliseconds (default: 15 seconds).
|
|
23
|
+
* A source archive of tens of megabytes needs more than the default, which
|
|
24
|
+
* is sized for a JSON schema.
|
|
25
|
+
*/
|
|
26
|
+
attemptTimeoutMs?: number;
|
|
27
|
+
/** Retries after the first attempt (default: 4). */
|
|
28
|
+
retries?: number;
|
|
29
|
+
/** Base back-off between attempts in milliseconds (default: 1 second). */
|
|
30
|
+
backoffMs?: number;
|
|
21
31
|
}
|
|
22
32
|
|
|
23
33
|
// ── Transient-aware fetch ──────────────────────────────────────────
|
|
@@ -198,7 +208,26 @@ export async function fetchWithCache(config: FetchConfig, force = false): Promis
|
|
|
198
208
|
}
|
|
199
209
|
}
|
|
200
210
|
|
|
201
|
-
|
|
211
|
+
let response: Response;
|
|
212
|
+
try {
|
|
213
|
+
response = await fetchWithRetry(
|
|
214
|
+
config.url,
|
|
215
|
+
config.retries ?? DEFAULT_RETRIES,
|
|
216
|
+
config.backoffMs ?? DEFAULT_BACKOFF_MS,
|
|
217
|
+
undefined,
|
|
218
|
+
config.attemptTimeoutMs ?? DEFAULT_ATTEMPT_TIMEOUT_MS,
|
|
219
|
+
);
|
|
220
|
+
} catch (e) {
|
|
221
|
+
// A stale copy beats a failed build. The archives this caches are pinned
|
|
222
|
+
// by tag or by version in the URL, so a copy past its TTL is the same
|
|
223
|
+
// bytes; the TTL exists to notice an unpinned URL moving, not to expire
|
|
224
|
+
// good data. `force` means the caller needs fresh bytes, so it still throws.
|
|
225
|
+
if (!force && e instanceof TransientFetchError && existsSync(config.cacheFile)) {
|
|
226
|
+
console.error(`${e.message} Using the cached copy at ${config.cacheFile} from ${new Date(statSync(config.cacheFile).mtimeMs).toISOString()}.`);
|
|
227
|
+
return readFileSync(config.cacheFile) as unknown as Buffer;
|
|
228
|
+
}
|
|
229
|
+
throw e;
|
|
230
|
+
}
|
|
202
231
|
const arrayBuffer = await response.arrayBuffer();
|
|
203
232
|
const data = Buffer.from(arrayBuffer);
|
|
204
233
|
|
|
@@ -39,7 +39,7 @@ import {
|
|
|
39
39
|
type DriverRunResult,
|
|
40
40
|
} from "./driver";
|
|
41
41
|
import type { PendingGateRecord } from "../lifecycle/gate-ledger";
|
|
42
|
-
import type { GateLedgerPort } from "../op/gate";
|
|
42
|
+
import type { GateDigestMismatch, GateLedgerPort } from "../op/gate";
|
|
43
43
|
import { gateName } from "../op/gate-name";
|
|
44
44
|
import { isLexiconPlugin, type LexiconPlugin, type ComponentPipelineOptions } from "../lexicon";
|
|
45
45
|
import type { RunProgressEvent } from "./run-progress";
|
|
@@ -432,6 +432,8 @@ export interface RunComponentsResult {
|
|
|
432
432
|
/** Whether this run's own append reached the remote (#2310); absent when the pending fact was already standing. */
|
|
433
433
|
pushed?: boolean;
|
|
434
434
|
pushWarning?: string;
|
|
435
|
+
/** Set when an approval stands for this gate, but for another plan or none (#2574). */
|
|
436
|
+
mismatch?: GateDigestMismatch;
|
|
435
437
|
};
|
|
436
438
|
/** This run's resolved build-time parameters (chant #1108) — the component-driver counterpart of `../cli/commands/build.ts`'s `BuildResult.buildParams`. Present only once the run actually reached dispatch (mirrors `BuildResult.buildParams`, which is likewise absent on an early-error return). */
|
|
437
439
|
buildParams?: BuildParamProvenance[];
|
|
@@ -584,6 +586,7 @@ export async function runComponents(
|
|
|
584
586
|
gate: run.gate,
|
|
585
587
|
...(run.gatePushed !== undefined ? { pushed: run.gatePushed } : {}),
|
|
586
588
|
...(run.gatePushWarning ? { pushWarning: run.gatePushWarning } : {}),
|
|
589
|
+
...(run.gateMismatch ? { mismatch: run.gateMismatch } : {}),
|
|
587
590
|
},
|
|
588
591
|
}
|
|
589
592
|
: {}),
|
|
@@ -632,6 +635,7 @@ export async function runComponents(
|
|
|
632
635
|
gate: componentResult.gate,
|
|
633
636
|
...(componentResult.gatePushed !== undefined ? { gatePushed: componentResult.gatePushed } : {}),
|
|
634
637
|
...(componentResult.gatePushWarning ? { gatePushWarning: componentResult.gatePushWarning } : {}),
|
|
638
|
+
...(componentResult.gateMismatch ? { gateMismatch: componentResult.gateMismatch } : {}),
|
|
635
639
|
}
|
|
636
640
|
: {}),
|
|
637
641
|
componentOutputs,
|
|
@@ -648,6 +652,7 @@ export async function runComponents(
|
|
|
648
652
|
gate: componentResult.gate,
|
|
649
653
|
...(componentResult.gatePushed !== undefined ? { pushed: componentResult.gatePushed } : {}),
|
|
650
654
|
...(componentResult.gatePushWarning ? { pushWarning: componentResult.gatePushWarning } : {}),
|
|
655
|
+
...(componentResult.gateMismatch ? { mismatch: componentResult.gateMismatch } : {}),
|
|
651
656
|
},
|
|
652
657
|
}
|
|
653
658
|
: {}),
|
|
@@ -280,76 +280,46 @@ describe("discoverComponents", () => {
|
|
|
280
280
|
expect(result.errors.some((e) => e.type === "import")).toBe(true);
|
|
281
281
|
});
|
|
282
282
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
// directory — the skip only applies to a *second* nested config found
|
|
287
|
-
// after that (see the next test).
|
|
288
|
-
const childDir = join(testDir, "child-project");
|
|
289
|
-
await mkdir(childDir, { recursive: true });
|
|
290
|
-
await writeFile(join(childDir, "chant.config.ts"), `export default {};`);
|
|
291
|
-
await writeFile(
|
|
292
|
-
join(childDir, "child.component.ts"),
|
|
293
|
-
`
|
|
294
|
-
export const childSvc = {
|
|
295
|
-
name: "child-svc",
|
|
296
|
-
dependsOn: [],
|
|
297
|
-
deploy: [{ phase: "Apply", steps: [{ kind: "shell" }] }],
|
|
298
|
-
};
|
|
299
|
-
`,
|
|
300
|
-
);
|
|
301
|
-
await writeFile(
|
|
302
|
-
join(testDir, "root.component.ts"),
|
|
303
|
-
`
|
|
304
|
-
export const rootSvc = {
|
|
305
|
-
name: "root-svc",
|
|
283
|
+
const svc = (exportName: string, name: string) => `
|
|
284
|
+
export const ${exportName} = {
|
|
285
|
+
name: "${name}",
|
|
306
286
|
dependsOn: [],
|
|
307
287
|
deploy: [{ phase: "Apply", steps: [{ kind: "shell" }] }],
|
|
308
288
|
};
|
|
309
|
-
|
|
310
|
-
);
|
|
289
|
+
`;
|
|
311
290
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
test("a second nested chant.config.ts (a true child project) is not descended into", async () => {
|
|
291
|
+
test("from outside every project, every child project is read (#2527)", async () => {
|
|
292
|
+
// The source-root quirk is gone: no child config is special for being
|
|
293
|
+
// found first. The scan root has no config at or above it, so every
|
|
294
|
+
// child project's components are discovered, nested ones included.
|
|
319
295
|
const firstConfigDir = join(testDir, "first-config");
|
|
320
296
|
const nestedChildProject = join(firstConfigDir, "nested-child-project");
|
|
321
297
|
await mkdir(nestedChildProject, { recursive: true });
|
|
322
298
|
await writeFile(join(firstConfigDir, "chant.config.ts"), `export default {};`);
|
|
323
299
|
await writeFile(join(nestedChildProject, "chant.config.ts"), `export default {};`);
|
|
324
|
-
await writeFile(
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
export const firstSvc = {
|
|
328
|
-
name: "first-svc",
|
|
329
|
-
dependsOn: [],
|
|
330
|
-
deploy: [{ phase: "Apply", steps: [{ kind: "shell" }] }],
|
|
331
|
-
};
|
|
332
|
-
`,
|
|
333
|
-
);
|
|
334
|
-
await writeFile(
|
|
335
|
-
join(nestedChildProject, "nested.component.ts"),
|
|
336
|
-
`
|
|
337
|
-
export const nestedSvc = {
|
|
338
|
-
name: "nested-svc",
|
|
339
|
-
dependsOn: [],
|
|
340
|
-
deploy: [{ phase: "Apply", steps: [{ kind: "shell" }] }],
|
|
341
|
-
};
|
|
342
|
-
`,
|
|
343
|
-
);
|
|
300
|
+
await writeFile(join(testDir, "root.component.ts"), svc("rootSvc", "root-svc"));
|
|
301
|
+
await writeFile(join(firstConfigDir, "first.component.ts"), svc("firstSvc", "first-svc"));
|
|
302
|
+
await writeFile(join(nestedChildProject, "nested.component.ts"), svc("nestedSvc", "nested-svc"));
|
|
344
303
|
|
|
345
304
|
const result = await discoverComponents(testDir);
|
|
346
305
|
|
|
347
|
-
|
|
348
|
-
// and is scanned; nested-child-project/'s own chant.config.ts is the
|
|
349
|
-
// *second* config encountered, so it is treated as a separate project
|
|
350
|
-
// scope and not descended into.
|
|
306
|
+
expect(result.components.has("root-svc")).toBe(true);
|
|
351
307
|
expect(result.components.has("first-svc")).toBe(true);
|
|
352
|
-
expect(result.components.has("nested-svc")).toBe(
|
|
308
|
+
expect(result.components.has("nested-svc")).toBe(true);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
test("from inside a project, a child project is a boundary (#2527)", async () => {
|
|
312
|
+
const childDir = join(testDir, "child-project");
|
|
313
|
+
await mkdir(childDir, { recursive: true });
|
|
314
|
+
await writeFile(join(testDir, "chant.config.ts"), `export default {};`);
|
|
315
|
+
await writeFile(join(childDir, "chant.config.ts"), `export default {};`);
|
|
316
|
+
await writeFile(join(testDir, "root.component.ts"), svc("rootSvc", "root-svc"));
|
|
317
|
+
await writeFile(join(childDir, "child.component.ts"), svc("childSvc", "child-svc"));
|
|
318
|
+
|
|
319
|
+
const result = await discoverComponents(testDir);
|
|
320
|
+
|
|
321
|
+
expect(result.components.has("root-svc")).toBe(true);
|
|
322
|
+
expect(result.components.has("child-svc")).toBe(false);
|
|
353
323
|
});
|
|
354
324
|
|
|
355
325
|
// ── chant #1108 — build-time parameters populated before import ────────────
|
|
@@ -40,18 +40,16 @@
|
|
|
40
40
|
* `./component.ts`, already proves the plain-JSON round-trip).
|
|
41
41
|
*/
|
|
42
42
|
|
|
43
|
-
import {
|
|
44
|
-
import { join, resolve } from "node:path";
|
|
43
|
+
import { resolve } from "node:path";
|
|
45
44
|
import { pathToFileURL } from "node:url";
|
|
46
|
-
import { existsSync } from "node:fs";
|
|
47
45
|
import { DiscoveryError } from "../errors";
|
|
48
46
|
import { isComponent, type Component } from "./component";
|
|
49
47
|
import type { BuildParamProvenance } from "../provenance";
|
|
50
48
|
import { buildParamValues } from "../build-params";
|
|
51
49
|
import { setBuildParams } from "../params";
|
|
52
|
-
import {
|
|
50
|
+
import { hasDiscoveryMarkerSync } from "../discovery/files";
|
|
53
51
|
import { resolveDiscoveryGlobs } from "../config";
|
|
54
|
-
import {
|
|
52
|
+
import { walkDiscovery, workspaceMemberDirs } from "../discovery/walk";
|
|
55
53
|
|
|
56
54
|
/** One discovered component, paired with the file it was exported from. */
|
|
57
55
|
export interface DiscoveredComponent {
|
|
@@ -118,77 +116,24 @@ export interface ImportedComponentModule {
|
|
|
118
116
|
}
|
|
119
117
|
|
|
120
118
|
/**
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
* project
|
|
126
|
-
* do there (#2519).
|
|
119
|
+
* Every `*.component.ts` file under `path`, through the one discovery walk
|
|
120
|
+
* (`../discovery/walk.ts`, #2527): the same dot-directory, `dist`,
|
|
121
|
+
* git-ignore and child-project rules as source discovery, the project's
|
|
122
|
+
* `exclude`/`include` globs and the skip marker (#2519). Scanned from outside
|
|
123
|
+
* any project, every child project is read.
|
|
127
124
|
*/
|
|
128
125
|
async function findComponentFiles(path: string): Promise<string[]> {
|
|
129
|
-
|
|
130
|
-
let sourceRoot: string | null = null;
|
|
131
|
-
const skip = compileDiscoveryFilter(await resolveDiscoveryGlobs(path));
|
|
132
|
-
const skippedChildren: string[] = [];
|
|
133
|
-
|
|
134
|
-
async function scanDirectory(dir: string): Promise<void> {
|
|
135
|
-
let entries;
|
|
136
|
-
try {
|
|
137
|
-
entries = await readdir(dir, { withFileTypes: true });
|
|
138
|
-
} catch {
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
for (const entry of entries) {
|
|
143
|
-
const fullPath = join(dir, entry.name);
|
|
144
|
-
|
|
145
|
-
if (entry.isDirectory()) {
|
|
146
|
-
// Skip dependency and tool/VCS directories: component sources never live
|
|
147
|
-
// in them, and descending in is both wasted work and a correctness bug —
|
|
148
|
-
// e.g. a CI runner like gitlab-ci-local stages a copy of the project
|
|
149
|
-
// under `.gitlab-ci-local/`, which discovery would otherwise pick up as
|
|
150
|
-
// duplicate component names alongside the originals.
|
|
151
|
-
if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
|
|
152
|
-
|
|
153
|
-
const configPath = join(fullPath, "chant.config.ts");
|
|
154
|
-
if (existsSync(configPath)) {
|
|
155
|
-
if (sourceRoot === null) {
|
|
156
|
-
sourceRoot = fullPath;
|
|
157
|
-
} else {
|
|
158
|
-
skippedChildren.push(fullPath);
|
|
159
|
-
continue;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
await scanDirectory(fullPath);
|
|
163
|
-
} else if (
|
|
164
|
-
entry.isFile() &&
|
|
165
|
-
entry.name.endsWith(".component.ts") &&
|
|
166
|
-
!entry.name.endsWith(".test.component.ts") &&
|
|
167
|
-
!entry.name.endsWith(".spec.component.ts") &&
|
|
168
|
-
!skip?.(fullPath) &&
|
|
169
|
-
!(await hasDiscoveryMarker(fullPath))
|
|
170
|
-
) {
|
|
171
|
-
files.push(fullPath);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
await scanDirectory(path);
|
|
177
|
-
// #2527's warning release: the list returned is today's, unchanged.
|
|
178
|
-
await warnDiscoveryChanges({
|
|
126
|
+
return walkDiscovery({
|
|
179
127
|
walker: "components",
|
|
180
128
|
root: path,
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
fileOk: async (name, full) =>
|
|
129
|
+
globs: await resolveDiscoveryGlobs(path),
|
|
130
|
+
excludeDirs: await workspaceMemberDirs(path),
|
|
131
|
+
accept: (name, full) =>
|
|
185
132
|
name.endsWith(".component.ts") &&
|
|
186
133
|
!name.endsWith(".test.component.ts") &&
|
|
187
134
|
!name.endsWith(".spec.component.ts") &&
|
|
188
|
-
!
|
|
189
|
-
!(await hasDiscoveryMarker(full)),
|
|
135
|
+
!hasDiscoveryMarkerSync(full),
|
|
190
136
|
});
|
|
191
|
-
return files;
|
|
192
137
|
}
|
|
193
138
|
|
|
194
139
|
/**
|