@intentius/chant 0.13.1 → 0.15.1
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/catalog.d.ts +45 -5
- package/dist/audit/catalog.d.ts.map +1 -1
- package/dist/audit/proof.d.ts +3 -0
- package/dist/audit/proof.d.ts.map +1 -1
- package/dist/audit/report-model.d.ts +4 -1
- package/dist/audit/report-model.d.ts.map +1 -1
- package/dist/audit/report.d.ts +3 -0
- package/dist/audit/report.d.ts.map +1 -1
- package/dist/audit/rules-doc.d.ts +8 -2
- package/dist/audit/rules-doc.d.ts.map +1 -1
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/lexicon-rolling-upgrade.d.ts +37 -0
- package/dist/cli/commands/lexicon-rolling-upgrade.d.ts.map +1 -0
- package/dist/cli/commands/lexicon-surface-diff.d.ts +48 -0
- package/dist/cli/commands/lexicon-surface-diff.d.ts.map +1 -0
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/pinned-upgrade.d.ts +41 -0
- package/dist/cli/commands/pinned-upgrade.d.ts.map +1 -0
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/components.d.ts +39 -0
- package/dist/cli/handlers/components.d.ts.map +1 -0
- package/dist/cli/handlers/dev.d.ts +3 -0
- package/dist/cli/handlers/dev.d.ts.map +1 -1
- package/dist/cli/handlers/graph.d.ts +4 -2
- package/dist/cli/handlers/graph.d.ts.map +1 -1
- package/dist/cli/handlers/misc.d.ts.map +1 -1
- package/dist/cli/handlers/run.d.ts +49 -0
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +35 -0
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/codegen/fetch.d.ts +22 -0
- package/dist/codegen/fetch.d.ts.map +1 -1
- package/dist/codegen/lexicon-regen.d.ts +110 -0
- package/dist/codegen/lexicon-regen.d.ts.map +1 -0
- package/dist/codegen/pinned-upgrade.d.ts +153 -0
- package/dist/codegen/pinned-upgrade.d.ts.map +1 -0
- package/dist/codegen/rolling-upgrade.d.ts +138 -0
- package/dist/codegen/rolling-upgrade.d.ts.map +1 -0
- package/dist/codegen/surface-snapshot.d.ts +173 -0
- package/dist/codegen/surface-snapshot.d.ts.map +1 -0
- package/dist/codegen/version-bump.d.ts +21 -0
- package/dist/codegen/version-bump.d.ts.map +1 -0
- package/dist/components/auto-release.d.ts +93 -0
- package/dist/components/auto-release.d.ts.map +1 -0
- package/dist/components/builders.d.ts +37 -0
- package/dist/components/builders.d.ts.map +1 -0
- package/dist/components/capability-plugin-loader.d.ts +111 -0
- package/dist/components/capability-plugin-loader.d.ts.map +1 -0
- package/dist/components/capability-plugin-schema.d.ts +24 -0
- package/dist/components/capability-plugin-schema.d.ts.map +1 -0
- package/dist/components/capability-plugin.d.ts +85 -0
- package/dist/components/capability-plugin.d.ts.map +1 -0
- package/dist/components/capability.d.ts +89 -0
- package/dist/components/capability.d.ts.map +1 -0
- package/dist/components/cli-support.d.ts +204 -0
- package/dist/components/cli-support.d.ts.map +1 -0
- package/dist/components/component.d.ts +179 -0
- package/dist/components/component.d.ts.map +1 -0
- package/dist/components/config-defaults.d.ts +41 -0
- package/dist/components/config-defaults.d.ts.map +1 -0
- package/dist/components/discover.d.ts +60 -0
- package/dist/components/discover.d.ts.map +1 -0
- package/dist/components/driver-output.d.ts +20 -0
- package/dist/components/driver-output.d.ts.map +1 -0
- package/dist/components/driver.d.ts +209 -0
- package/dist/components/driver.d.ts.map +1 -0
- package/dist/components/index.d.ts +22 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/manifest-persistence.d.ts +79 -0
- package/dist/components/manifest-persistence.d.ts.map +1 -0
- package/dist/components/pilots/alb-ecs.pilot.d.ts +27 -0
- package/dist/components/pilots/alb-ecs.pilot.d.ts.map +1 -0
- package/dist/components/pilots/dynamodb.pilot.d.ts +22 -0
- package/dist/components/pilots/dynamodb.pilot.d.ts.map +1 -0
- package/dist/components/pilots/jar-emr.pilot.d.ts +37 -0
- package/dist/components/pilots/jar-emr.pilot.d.ts.map +1 -0
- package/dist/components/pilots/lambda.pilot.d.ts +35 -0
- package/dist/components/pilots/lambda.pilot.d.ts.map +1 -0
- package/dist/components/pilots/neo4j-fanout.pilot.d.ts +17 -0
- package/dist/components/pilots/neo4j-fanout.pilot.d.ts.map +1 -0
- package/dist/components/pilots/project.d.ts +13 -0
- package/dist/components/pilots/project.d.ts.map +1 -0
- package/dist/components/presets/ecs-fargate.d.ts +59 -0
- package/dist/components/presets/ecs-fargate.d.ts.map +1 -0
- package/dist/components/presets/index.d.ts +29 -0
- package/dist/components/presets/index.d.ts.map +1 -0
- package/dist/components/presets/lambda.d.ts +35 -0
- package/dist/components/presets/lambda.d.ts.map +1 -0
- package/dist/components/presets/single-host-compose.d.ts +43 -0
- package/dist/components/presets/single-host-compose.d.ts.map +1 -0
- package/dist/components/registry.d.ts +29 -0
- package/dist/components/registry.d.ts.map +1 -0
- package/dist/components/starter-plugin.d.ts +51 -0
- package/dist/components/starter-plugin.d.ts.map +1 -0
- package/dist/components/temporal-codegen-loader.d.ts +27 -0
- package/dist/components/temporal-codegen-loader.d.ts.map +1 -0
- package/dist/components/verbs/__tests__/mock-cloud-executor.d.ts +35 -0
- package/dist/components/verbs/__tests__/mock-cloud-executor.d.ts.map +1 -0
- package/dist/components/verbs/__tests__/mock-process-runner.d.ts +45 -0
- package/dist/components/verbs/__tests__/mock-process-runner.d.ts.map +1 -0
- package/dist/components/verbs/__tests__/mock-sbom-generator.d.ts +33 -0
- package/dist/components/verbs/__tests__/mock-sbom-generator.d.ts.map +1 -0
- package/dist/components/verbs/bom-writer.d.ts +155 -0
- package/dist/components/verbs/bom-writer.d.ts.map +1 -0
- package/dist/components/verbs/build-archive.d.ts +205 -0
- package/dist/components/verbs/build-archive.d.ts.map +1 -0
- package/dist/components/verbs/build.d.ts +150 -0
- package/dist/components/verbs/build.d.ts.map +1 -0
- package/dist/components/verbs/cloud-executor.d.ts +88 -0
- package/dist/components/verbs/cloud-executor.d.ts.map +1 -0
- package/dist/components/verbs/component-bom.d.ts +103 -0
- package/dist/components/verbs/component-bom.d.ts.map +1 -0
- package/dist/components/verbs/index.d.ts +49 -0
- package/dist/components/verbs/index.d.ts.map +1 -0
- package/dist/components/verbs/license-policy.d.ts +56 -0
- package/dist/components/verbs/license-policy.d.ts.map +1 -0
- package/dist/components/verbs/lockfile-sbom-generator.d.ts +81 -0
- package/dist/components/verbs/lockfile-sbom-generator.d.ts.map +1 -0
- package/dist/components/verbs/process-runner.d.ts +64 -0
- package/dist/components/verbs/process-runner.d.ts.map +1 -0
- package/dist/components/verbs/reproducibility.d.ts +80 -0
- package/dist/components/verbs/reproducibility.d.ts.map +1 -0
- package/dist/components/verbs/sbom-generator.d.ts +157 -0
- package/dist/components/verbs/sbom-generator.d.ts.map +1 -0
- package/dist/components/verbs/sbom.d.ts +79 -0
- package/dist/components/verbs/sbom.d.ts.map +1 -0
- package/dist/components/verbs/shell.d.ts +35 -0
- package/dist/components/verbs/shell.d.ts.map +1 -0
- package/dist/components/verbs/sign.d.ts +222 -0
- package/dist/components/verbs/sign.d.ts.map +1 -0
- package/dist/components/verbs/stub.d.ts +18 -0
- package/dist/components/verbs/stub.d.ts.map +1 -0
- package/dist/components/verbs/tool-sbom-generator.d.ts +51 -0
- package/dist/components/verbs/tool-sbom-generator.d.ts.map +1 -0
- package/dist/components/verbs/verify.d.ts +106 -0
- package/dist/components/verbs/verify.d.ts.map +1 -0
- package/dist/components/verbs/vex.d.ts +65 -0
- package/dist/components/verbs/vex.d.ts.map +1 -0
- package/dist/components/verbs/vuln-gate.d.ts +91 -0
- package/dist/components/verbs/vuln-gate.d.ts.map +1 -0
- package/dist/components/verbs/vuln-scan.d.ts +116 -0
- package/dist/components/verbs/vuln-scan.d.ts.map +1 -0
- package/dist/components/verbs/wait-verify.d.ts +85 -0
- package/dist/components/verbs/wait-verify.d.ts.map +1 -0
- package/dist/config.d.ts +205 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/lexicon.d.ts +78 -0
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/build-ledger-store.d.ts +121 -0
- package/dist/lifecycle/build-ledger-store.d.ts.map +1 -0
- package/dist/lifecycle/build-ledger.d.ts +225 -0
- package/dist/lifecycle/build-ledger.d.ts.map +1 -0
- package/dist/lifecycle/git.d.ts +84 -0
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lifecycle/index.d.ts +5 -0
- package/dist/lifecycle/index.d.ts.map +1 -1
- package/dist/lifecycle/oras-referrer-lookup.d.ts +41 -0
- package/dist/lifecycle/oras-referrer-lookup.d.ts.map +1 -0
- package/dist/lifecycle/release-ledger.d.ts +122 -0
- package/dist/lifecycle/release-ledger.d.ts.map +1 -0
- package/dist/lifecycle/status.d.ts +150 -0
- package/dist/lifecycle/status.d.ts.map +1 -0
- package/dist/lint/component-checks.d.ts +95 -0
- package/dist/lint/component-checks.d.ts.map +1 -0
- package/dist/lint/engine.d.ts +23 -0
- package/dist/lint/engine.d.ts.map +1 -1
- package/dist/lint/presets/strict.json +8 -1
- package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.d.ts +10 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.d.ts +3 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.d.ts +3 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp001-publishes-never-applies.d.ts +20 -0
- package/dist/lint/rules/comp/comp001-publishes-never-applies.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp002-dangling-wiring-ref.d.ts +28 -0
- package/dist/lint/rules/comp/comp002-dangling-wiring-ref.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp003-mutating-no-rollback.d.ts +39 -0
- package/dist/lint/rules/comp/comp003-mutating-no-rollback.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts +37 -0
- package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp005-capability-kind-is-noun.d.ts +43 -0
- package/dist/lint/rules/comp/comp005-capability-kind-is-noun.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp006-shell-needs-reason.d.ts +22 -0
- package/dist/lint/rules/comp/comp006-shell-needs-reason.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp007-composition-sprawl.d.ts +33 -0
- package/dist/lint/rules/comp/comp007-composition-sprawl.d.ts.map +1 -0
- package/dist/lint/rules/comp/index.d.ts +18 -0
- package/dist/lint/rules/comp/index.d.ts.map +1 -0
- package/dist/lint/rules/comp/support.d.ts +71 -0
- package/dist/lint/rules/comp/support.d.ts.map +1 -0
- package/dist/lsp/lexicon-providers.d.ts.map +1 -1
- package/dist/op/activity-registry.d.ts +11 -6
- package/dist/op/activity-registry.d.ts.map +1 -1
- package/dist/op/activity-runtime.d.ts +24 -0
- package/dist/op/activity-runtime.d.ts.map +1 -0
- package/dist/op/builders.d.ts +59 -0
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/index.d.ts +2 -1
- package/dist/op/index.d.ts.map +1 -1
- package/dist/ownership.d.ts +20 -14
- package/dist/ownership.d.ts.map +1 -1
- package/package.json +14 -1
- package/src/audit/catalog.test.ts +74 -22
- package/src/audit/catalog.ts +74 -471
- package/src/audit/proof.ts +4 -2
- package/src/audit/report-html.test.ts +14 -7
- package/src/audit/report-model.ts +20 -9
- package/src/audit/report.test.ts +36 -13
- package/src/audit/report.ts +2 -0
- package/src/audit/rules-doc.test.ts +8 -6
- package/src/audit/rules-doc.ts +13 -5
- package/src/cli/commands/audit.ts +23 -18
- package/src/cli/commands/component-lint.test.ts +158 -0
- package/src/cli/commands/doctor.test.ts +116 -2
- package/src/cli/commands/doctor.ts +46 -0
- package/src/cli/commands/lexicon-rolling-upgrade.ts +198 -0
- package/src/cli/commands/lexicon-surface-diff.test.ts +104 -0
- package/src/cli/commands/lexicon-surface-diff.ts +185 -0
- package/src/cli/commands/lint.ts +142 -1
- package/src/cli/commands/pinned-upgrade.ts +204 -0
- package/src/cli/handlers/build.ts +58 -1
- package/src/cli/handlers/components.test.ts +504 -0
- package/src/cli/handlers/components.ts +404 -0
- package/src/cli/handlers/dev.ts +60 -1
- package/src/cli/handlers/graph.ts +47 -2
- package/src/cli/handlers/misc.ts +45 -1
- package/src/cli/handlers/run.test.ts +967 -3
- package/src/cli/handlers/run.ts +618 -11
- package/src/cli/main.test.ts +66 -0
- package/src/cli/main.ts +105 -2
- package/src/cli/registry.ts +35 -0
- package/src/codegen/fetch.test.ts +84 -3
- package/src/codegen/fetch.ts +76 -2
- package/src/codegen/lexicon-regen.test.ts +298 -0
- package/src/codegen/lexicon-regen.ts +545 -0
- package/src/codegen/pinned-upgrade.test.ts +399 -0
- package/src/codegen/pinned-upgrade.ts +423 -0
- package/src/codegen/rolling-upgrade.test.ts +333 -0
- package/src/codegen/rolling-upgrade.ts +320 -0
- package/src/codegen/surface-snapshot.test.ts +461 -0
- package/src/codegen/surface-snapshot.ts +546 -0
- package/src/codegen/version-bump.test.ts +47 -0
- package/src/codegen/version-bump.ts +39 -0
- package/src/components/README.md +130 -0
- package/src/components/SPRAWL-VALIDATION.md +181 -0
- package/src/components/__fixtures__/alb-ecs-service.json +51 -0
- package/src/components/__fixtures__/dynamodb-infra.json +32 -0
- package/src/components/__fixtures__/emr-job-consumer.json +26 -0
- package/src/components/__fixtures__/jar-lib-producer.json +16 -0
- package/src/components/__fixtures__/lambda-image-processor.json +28 -0
- package/src/components/__fixtures__/neo4j-fanout.json +34 -0
- package/src/components/__fixtures__/single-host-compose.json +29 -0
- package/src/components/auto-release.test.ts +217 -0
- package/src/components/auto-release.ts +216 -0
- package/src/components/builders.test.ts +45 -0
- package/src/components/builders.ts +71 -0
- package/src/components/capability-plugin-loader.ts +218 -0
- package/src/components/capability-plugin-schema.ts +56 -0
- package/src/components/capability-plugin.test.ts +235 -0
- package/src/components/capability-plugin.ts +108 -0
- package/src/components/capability.ts +117 -0
- package/src/components/cli-support.test.ts +579 -0
- package/src/components/cli-support.ts +481 -0
- package/src/components/component-schema.test.ts +265 -0
- package/src/components/component.schema.json +235 -0
- package/src/components/component.test.ts +251 -0
- package/src/components/component.ts +255 -0
- package/src/components/config-defaults.test.ts +263 -0
- package/src/components/config-defaults.ts +145 -0
- package/src/components/discover.test.ts +352 -0
- package/src/components/discover.ts +167 -0
- package/src/components/driver-output.ts +71 -0
- package/src/components/driver.test.ts +638 -0
- package/src/components/driver.ts +690 -0
- package/src/components/index.ts +113 -0
- package/src/components/manifest-persistence.test.ts +152 -0
- package/src/components/manifest-persistence.ts +164 -0
- package/src/components/pilots/README.md +33 -0
- package/src/components/pilots/alb-ecs.pilot.ts +63 -0
- package/src/components/pilots/dynamodb.pilot.ts +59 -0
- package/src/components/pilots/jar-emr.pilot.ts +69 -0
- package/src/components/pilots/lambda.pilot.ts +55 -0
- package/src/components/pilots/neo4j-fanout.pilot.ts +92 -0
- package/src/components/pilots/pilots-lint-clean.test.ts +78 -0
- package/src/components/pilots/pilots.test.ts +126 -0
- package/src/components/pilots/project.ts +13 -0
- package/src/components/presets/comp007-reduction.test.ts +122 -0
- package/src/components/presets/ecs-fargate.test.ts +84 -0
- package/src/components/presets/ecs-fargate.ts +103 -0
- package/src/components/presets/index.ts +32 -0
- package/src/components/presets/lambda.test.ts +35 -0
- package/src/components/presets/lambda.ts +53 -0
- package/src/components/presets/single-host-compose.test.ts +65 -0
- package/src/components/presets/single-host-compose.ts +64 -0
- package/src/components/registry.test.ts +112 -0
- package/src/components/registry.ts +37 -0
- package/src/components/starter-plugin.ts +105 -0
- package/src/components/temporal-codegen-loader.ts +41 -0
- package/src/components/verbs/__fixtures__/package-lock.json +45 -0
- package/src/components/verbs/__fixtures__/pom.xml +37 -0
- package/src/components/verbs/__fixtures__/schemas/cyclonedx-1.5.schema.json +3800 -0
- package/src/components/verbs/__fixtures__/schemas/cyclonedx-spdx-license.schema.json +621 -0
- package/src/components/verbs/__fixtures__/schemas/jsf-0.82.schema.json +240 -0
- package/src/components/verbs/__fixtures__/schemas/spdx-2.3.schema.json +740 -0
- package/src/components/verbs/__tests__/mock-cloud-executor.ts +102 -0
- package/src/components/verbs/__tests__/mock-process-runner.ts +79 -0
- package/src/components/verbs/__tests__/mock-sbom-generator.ts +85 -0
- package/src/components/verbs/bom-writer.test.ts +331 -0
- package/src/components/verbs/bom-writer.ts +386 -0
- package/src/components/verbs/build-archive.test.ts +251 -0
- package/src/components/verbs/build-archive.ts +296 -0
- package/src/components/verbs/build.test.ts +222 -0
- package/src/components/verbs/build.ts +252 -0
- package/src/components/verbs/cloud-executor.ts +181 -0
- package/src/components/verbs/component-bom.test.ts +219 -0
- package/src/components/verbs/component-bom.ts +189 -0
- package/src/components/verbs/index.ts +49 -0
- package/src/components/verbs/license-policy.ts +115 -0
- package/src/components/verbs/lockfile-sbom-generator.test.ts +195 -0
- package/src/components/verbs/lockfile-sbom-generator.ts +236 -0
- package/src/components/verbs/process-runner.test.ts +79 -0
- package/src/components/verbs/process-runner.ts +113 -0
- package/src/components/verbs/reproducibility.test.ts +24 -0
- package/src/components/verbs/reproducibility.ts +100 -0
- package/src/components/verbs/sbom-generator.test.ts +96 -0
- package/src/components/verbs/sbom-generator.ts +209 -0
- package/src/components/verbs/sbom.test.ts +184 -0
- package/src/components/verbs/sbom.ts +152 -0
- package/src/components/verbs/shell.test.ts +36 -0
- package/src/components/verbs/shell.ts +51 -0
- package/src/components/verbs/sign.test.ts +210 -0
- package/src/components/verbs/sign.ts +350 -0
- package/src/components/verbs/stub.ts +34 -0
- package/src/components/verbs/tool-sbom-generator.test.ts +194 -0
- package/src/components/verbs/tool-sbom-generator.ts +192 -0
- package/src/components/verbs/verify.test.ts +159 -0
- package/src/components/verbs/verify.ts +179 -0
- package/src/components/verbs/vex.ts +182 -0
- package/src/components/verbs/vuln-gate.test.ts +201 -0
- package/src/components/verbs/vuln-gate.ts +170 -0
- package/src/components/verbs/vuln-scan.test.ts +145 -0
- package/src/components/verbs/vuln-scan.ts +266 -0
- package/src/components/verbs/wait-verify.test.ts +111 -0
- package/src/components/verbs/wait-verify.ts +171 -0
- package/src/config.test.ts +74 -1
- package/src/config.ts +219 -0
- package/src/index.ts +32 -0
- package/src/lexicon.ts +88 -0
- package/src/lifecycle/build-ledger-store.test.ts +217 -0
- package/src/lifecycle/build-ledger-store.ts +165 -0
- package/src/lifecycle/build-ledger.test.ts +349 -0
- package/src/lifecycle/build-ledger.ts +305 -0
- package/src/lifecycle/git.test.ts +118 -0
- package/src/lifecycle/git.ts +149 -14
- package/src/lifecycle/index.ts +5 -0
- package/src/lifecycle/oras-referrer-lookup.test.ts +116 -0
- package/src/lifecycle/oras-referrer-lookup.ts +110 -0
- package/src/lifecycle/release-ledger.test.ts +209 -0
- package/src/lifecycle/release-ledger.ts +185 -0
- package/src/lifecycle/status.test.ts +330 -0
- package/src/lifecycle/status.ts +278 -0
- package/src/lint/component-checks.ts +148 -0
- package/src/lint/config.test.ts +21 -0
- package/src/lint/engine.ts +11 -2
- package/src/lint/presets/relaxed.json +8 -1
- package/src/lint/presets/strict.json +8 -1
- package/src/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.ts +9 -0
- package/src/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.ts +9 -0
- package/src/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.ts +11 -0
- package/src/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.ts +13 -0
- package/src/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.ts +11 -0
- package/src/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.ts +27 -0
- package/src/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.ts +10 -0
- package/src/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.ts +23 -0
- package/src/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.ts +10 -0
- package/src/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.ts +19 -0
- package/src/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.ts +10 -0
- package/src/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.ts +20 -0
- package/src/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.ts +23 -0
- package/src/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.ts +10 -0
- package/src/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.ts +14 -0
- package/src/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.ts +18 -0
- package/src/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.ts +10 -0
- package/src/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.ts +14 -0
- package/src/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.ts +13 -0
- package/src/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.ts +13 -0
- package/src/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.ts +12 -0
- package/src/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.ts +18 -0
- package/src/lint/rules/comp/comp.test.ts +378 -0
- package/src/lint/rules/comp/comp001-publishes-never-applies.ts +78 -0
- package/src/lint/rules/comp/comp002-dangling-wiring-ref.ts +94 -0
- package/src/lint/rules/comp/comp003-mutating-no-rollback.ts +115 -0
- package/src/lint/rules/comp/comp004-gate-needs-temporal.ts +66 -0
- package/src/lint/rules/comp/comp005-capability-kind-is-noun.ts +113 -0
- package/src/lint/rules/comp/comp006-shell-needs-reason.ts +55 -0
- package/src/lint/rules/comp/comp007-composition-sprawl.ts +71 -0
- package/src/lint/rules/comp/index.ts +37 -0
- package/src/lint/rules/comp/support.ts +173 -0
- package/src/lsp/lexicon-providers.test.ts +55 -0
- package/src/lsp/lexicon-providers.ts +13 -3
- package/src/op/activity-registry.test.ts +38 -0
- package/src/op/activity-registry.ts +31 -12
- package/src/op/activity-runtime.ts +73 -0
- package/src/op/builders.ts +99 -0
- package/src/op/index.ts +3 -1
- package/src/ownership.test.ts +24 -26
- package/src/ownership.ts +26 -38
package/src/cli/main.test.ts
CHANGED
|
@@ -188,6 +188,51 @@ describe("parseArgs", () => {
|
|
|
188
188
|
expect(result.extraPositional).toBe(".");
|
|
189
189
|
expect(result.extraPositional2).toBe(undefined);
|
|
190
190
|
});
|
|
191
|
+
|
|
192
|
+
// ── components release/status flags (#568) ──────────────────────────────
|
|
193
|
+
|
|
194
|
+
test("parses --component, --digest, --git-sha, --run-id, --actor for components release", () => {
|
|
195
|
+
const result = parseArgs([
|
|
196
|
+
"components", "release", "prod",
|
|
197
|
+
"--component", "search-service",
|
|
198
|
+
"--digest", "sha256:abc123",
|
|
199
|
+
"--git-sha", "deadbeef",
|
|
200
|
+
"--run-id", "run-1",
|
|
201
|
+
"--actor", "alice",
|
|
202
|
+
]);
|
|
203
|
+
expect(result.command).toBe("components");
|
|
204
|
+
expect(result.path).toBe("release");
|
|
205
|
+
expect(result.extraPositional).toBe("prod");
|
|
206
|
+
expect(result.component).toBe("search-service");
|
|
207
|
+
expect(result.digest).toBe("sha256:abc123");
|
|
208
|
+
expect(result.gitSha).toBe("deadbeef");
|
|
209
|
+
expect(result.runId).toBe("run-1");
|
|
210
|
+
expect(result.actor).toBe("alice");
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
test("parses --compare-to and --live for components status", () => {
|
|
214
|
+
const result = parseArgs(["components", "status", "prod", "--compare-to", "staging", "--live", "--json"]);
|
|
215
|
+
expect(result.command).toBe("components");
|
|
216
|
+
expect(result.path).toBe("status");
|
|
217
|
+
expect(result.extraPositional).toBe("prod");
|
|
218
|
+
expect(result.compareTo).toBe("staging");
|
|
219
|
+
expect(result.live).toBe(true);
|
|
220
|
+
expect(result.json).toBe(true);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// ── --no-release-record (#597) ───────────────────────────────────────────
|
|
224
|
+
|
|
225
|
+
test("parses --no-release-record for run --components", () => {
|
|
226
|
+
const result = parseArgs(["run", "--components", "search-service", "--env", "staging", "--no-release-record"]);
|
|
227
|
+
expect(result.components).toBe(true);
|
|
228
|
+
expect(result.env).toBe("staging");
|
|
229
|
+
expect(result.noReleaseRecord).toBe(true);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
test("--no-release-record is undefined (not false) when omitted", () => {
|
|
233
|
+
const result = parseArgs(["run", "--components", "search-service"]);
|
|
234
|
+
expect(result.noReleaseRecord).toBeUndefined();
|
|
235
|
+
});
|
|
191
236
|
});
|
|
192
237
|
|
|
193
238
|
// ── resolveCommand tests ──────────────────────────────────────────
|
|
@@ -205,6 +250,9 @@ describe("resolveCommand", () => {
|
|
|
205
250
|
{ name: "dev", handler: noop },
|
|
206
251
|
{ name: "lifecycle plan", handler: noop },
|
|
207
252
|
{ name: "lifecycle", handler: noop },
|
|
253
|
+
{ name: "components status", handler: noop },
|
|
254
|
+
{ name: "components release", handler: noop },
|
|
255
|
+
{ name: "components", handler: noop },
|
|
208
256
|
];
|
|
209
257
|
|
|
210
258
|
function makeArgs(overrides: Partial<ParsedArgs>): ParsedArgs {
|
|
@@ -286,6 +334,24 @@ describe("resolveCommand", () => {
|
|
|
286
334
|
expect(result!.compound).toBe(false);
|
|
287
335
|
});
|
|
288
336
|
|
|
337
|
+
test("resolves components status as compound command", () => {
|
|
338
|
+
const result = resolveCommand(makeArgs({ command: "components", path: "status" }), testRegistry);
|
|
339
|
+
expect(result!.def.name).toBe("components status");
|
|
340
|
+
expect(result!.compound).toBe(true);
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
test("resolves components release as compound command", () => {
|
|
344
|
+
const result = resolveCommand(makeArgs({ command: "components", path: "release" }), testRegistry);
|
|
345
|
+
expect(result!.def.name).toBe("components release");
|
|
346
|
+
expect(result!.compound).toBe(true);
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
test("falls back to unknown components subcommand handler", () => {
|
|
350
|
+
const result = resolveCommand(makeArgs({ command: "components", path: "bogus" }), testRegistry);
|
|
351
|
+
expect(result!.def.name).toBe("components");
|
|
352
|
+
expect(result!.compound).toBe(false);
|
|
353
|
+
});
|
|
354
|
+
|
|
289
355
|
test("resolves run status as compound command", () => {
|
|
290
356
|
const registry: CommandDef[] = [
|
|
291
357
|
{ name: "run list", handler: noop },
|
package/src/cli/main.ts
CHANGED
|
@@ -9,13 +9,14 @@ import { ENV_VAR, unknownEnvError } from "../env";
|
|
|
9
9
|
import { initRuntime } from "../runtime-adapter";
|
|
10
10
|
import { runBuild } from "./handlers/build";
|
|
11
11
|
import { runLint } from "./handlers/lint";
|
|
12
|
-
import { runDevGenerate, runDevPublish, runDevOnboard, runDevCheckLexicon, runDevUnknown } from "./handlers/dev";
|
|
12
|
+
import { runDevGenerate, runDevPublish, runDevOnboard, runDevCheckLexicon, runDevSurfaceDiff, runDevPinnedUpgrade, runDevRollingUpgrade, runDevUnknown } from "./handlers/dev";
|
|
13
13
|
import { runServeLsp, runServeMcp, runServeUnknown } from "./handlers/serve";
|
|
14
14
|
import { runInit, runInitLexicon } from "./handlers/init";
|
|
15
15
|
import { runList, runDescribe, runImport, runAudit, runUpdate, runDoctor } from "./handlers/misc";
|
|
16
16
|
import { runVendor } from "./handlers/vendor";
|
|
17
17
|
import { runMigrate } from "./handlers/migrate";
|
|
18
18
|
import { runLifecycleSnapshot, runLifecycleShow, runLifecycleDiff, runLifecyclePlan, runLifecycleAffected, runLifecycleLog, runLifecycleUnknown } from "./handlers/lifecycle";
|
|
19
|
+
import { runComponentsStatus, runComponentsReleaseRecord, runComponentsUnknown } from "./handlers/components";
|
|
19
20
|
import { runGraph } from "./handlers/graph";
|
|
20
21
|
import { runOp, runOpList, runOpStatus, runOpSignal, runOpCancel, runOpLog } from "./handlers/run";
|
|
21
22
|
|
|
@@ -127,6 +128,14 @@ export function parseArgs(args: string[]): ParsedArgs {
|
|
|
127
128
|
result.theme = args[++i];
|
|
128
129
|
} else if (arg === "--stacks") {
|
|
129
130
|
result.stacks = true;
|
|
131
|
+
} else if (arg === "--components") {
|
|
132
|
+
result.components = true;
|
|
133
|
+
} else if (arg === "--generate") {
|
|
134
|
+
result.generate = args[++i];
|
|
135
|
+
} else if (arg === "--dump-outputs") {
|
|
136
|
+
result.dumpOutputs = args[++i];
|
|
137
|
+
} else if (arg === "--seed-outputs") {
|
|
138
|
+
(result.seedOutputs ??= []).push(args[++i]);
|
|
130
139
|
} else if (arg === "--detail") {
|
|
131
140
|
result.detail = Number(args[++i]);
|
|
132
141
|
} else if (arg === "--lens") {
|
|
@@ -151,6 +160,30 @@ export function parseArgs(args: string[]): ParsedArgs {
|
|
|
151
160
|
result.temporal = true;
|
|
152
161
|
} else if (arg === "--json") {
|
|
153
162
|
result.json = true;
|
|
163
|
+
} else if (arg === "--update-snapshot") {
|
|
164
|
+
result.updateSnapshot = true;
|
|
165
|
+
} else if (arg === "--run-examples") {
|
|
166
|
+
result.runExamples = true;
|
|
167
|
+
} else if (arg === "--pinned-digest") {
|
|
168
|
+
result.pinnedDigest = args[++i];
|
|
169
|
+
} else if (arg === "--check") {
|
|
170
|
+
result.check = true;
|
|
171
|
+
} else if (arg === "--bump") {
|
|
172
|
+
result.bump = true;
|
|
173
|
+
} else if (arg === "--component") {
|
|
174
|
+
result.component = args[++i];
|
|
175
|
+
} else if (arg === "--digest") {
|
|
176
|
+
result.digest = args[++i];
|
|
177
|
+
} else if (arg === "--git-sha") {
|
|
178
|
+
result.gitSha = args[++i];
|
|
179
|
+
} else if (arg === "--run-id") {
|
|
180
|
+
result.runId = args[++i];
|
|
181
|
+
} else if (arg === "--actor") {
|
|
182
|
+
result.actor = args[++i];
|
|
183
|
+
} else if (arg === "--compare-to") {
|
|
184
|
+
result.compareTo = args[++i];
|
|
185
|
+
} else if (arg === "--no-release-record") {
|
|
186
|
+
result.noReleaseRecord = true;
|
|
154
187
|
} else if (!arg.startsWith("-")) {
|
|
155
188
|
if (!result.command) {
|
|
156
189
|
result.command = arg;
|
|
@@ -183,6 +216,10 @@ Commands:
|
|
|
183
216
|
init Initialize a new chant project
|
|
184
217
|
init lexicon <name> Scaffold a new lexicon plugin project
|
|
185
218
|
build Build infrastructure from specification files
|
|
219
|
+
(--components --generate gitlab: generate mode (#563) —
|
|
220
|
+
synthesize a thin .gitlab-ci.yml that triggers each
|
|
221
|
+
discovered component's own deploy in wave order,
|
|
222
|
+
instead of a normal lexicon build)
|
|
186
223
|
lint Check specifications for issues
|
|
187
224
|
list List discovered entities
|
|
188
225
|
describe Show the effective config for one component
|
|
@@ -198,10 +235,21 @@ Commands:
|
|
|
198
235
|
Ops:
|
|
199
236
|
run <name> Start an Op workflow (spawns worker + submits to Temporal)
|
|
200
237
|
run list List all Ops with current run status
|
|
238
|
+
--components: list discovered Components instead (--temporal
|
|
239
|
+
also annotates each with its latest run status; #599)
|
|
201
240
|
run status <name> Show current workflow run state
|
|
241
|
+
--components: show a Component's durable run state instead (#599)
|
|
202
242
|
run signal <name> <signal> Send a named signal to unblock a gate
|
|
243
|
+
--components: signal a Component's workflow instead (#589)
|
|
203
244
|
run cancel <name> Cancel the active workflow run (requires --force)
|
|
245
|
+
--components: cancel a Component's workflow instead (#589)
|
|
204
246
|
run log <name> Show run history for an Op
|
|
247
|
+
--components: show a Component's run history instead (#599)
|
|
248
|
+
run --components <name|all> Run discovered Component(s) through the interpret
|
|
249
|
+
driver on the local executor (--env <env>; #585).
|
|
250
|
+
On success, auto-emits a release-ledger record per
|
|
251
|
+
component that published a digest (default: on;
|
|
252
|
+
--no-release-record to opt out; #597)
|
|
205
253
|
|
|
206
254
|
graph Show Op dependency graph (--stacks for cross-stack order,
|
|
207
255
|
--format ir|mermaid|dot|layout for the lint-gated graph IR,
|
|
@@ -222,11 +270,33 @@ Lifecycle (alias: lc):
|
|
|
222
270
|
--json: emit the ChangeSet as JSON
|
|
223
271
|
lifecycle log [env] History of lifecycle snapshots
|
|
224
272
|
|
|
273
|
+
Component release ledger + status:
|
|
274
|
+
components status [env] What's built vs what's deployed where, joined by
|
|
275
|
+
digest (--live: reconcile against live+ownership;
|
|
276
|
+
--json: stable machine-readable contract;
|
|
277
|
+
--compare-to <env>: cross-check the same
|
|
278
|
+
component's recorded digest against another env)
|
|
279
|
+
components release <env> Append one immutable release record
|
|
280
|
+
(--component <name> --digest <sha256:...>
|
|
281
|
+
[--git-sha <sha>] [--run-id <id>] [--actor <name>])
|
|
282
|
+
|
|
225
283
|
Lexicon development:
|
|
226
284
|
dev generate Generate lexicon artifacts (+ validate + coverage)
|
|
227
285
|
dev publish Package lexicon for distribution
|
|
228
286
|
dev onboard <name> Patch CI, Dockerfiles, and workflows for a new lexicon
|
|
229
287
|
dev check-lexicon <dir> Check lexicon completeness (tier 1/2/3)
|
|
288
|
+
dev surface-diff <dir> Regen lexicon, validate, diff API surface vs committed baseline
|
|
289
|
+
(--force: bypass spec cache; --update-snapshot: write new baseline;
|
|
290
|
+
--bump: with --update-snapshot, bump package version by drift severity;
|
|
291
|
+
--check: fail if the committed baseline drifted (never writes);
|
|
292
|
+
--run-examples: also run example build harness;
|
|
293
|
+
--pinned-digest <file>: verify spec digest before regen)
|
|
294
|
+
dev pinned-upgrade <dir> Report if a pinned lexicon (k8s|gcp|docker|gitlab) has a newer
|
|
295
|
+
upstream release; dry-run bump + regen + surface-diff, then revert
|
|
296
|
+
(reports only; --force bypasses the spec cache, -f json for JSON)
|
|
297
|
+
dev rolling-upgrade <dir> Report rolling-spec drift (aws, azure, github): regen from
|
|
298
|
+
latest, diff surface vs committed baseline, print delta + PR
|
|
299
|
+
label (dry run; --force bypasses the spec cache, --format json)
|
|
230
300
|
|
|
231
301
|
Servers:
|
|
232
302
|
serve lsp Start the LSP server (stdio)
|
|
@@ -268,12 +338,25 @@ Options:
|
|
|
268
338
|
--strict Escalate needs-review/validation to errors (migrate)
|
|
269
339
|
--validate Run external validator (glci/glab) after migrate
|
|
270
340
|
--use-composites Rewrite to composite calls when patterns match (migrate)
|
|
341
|
+
--components Target discovered Component declarations instead of
|
|
342
|
+
lexicon resources (list, describe, graph, build, run)
|
|
343
|
+
--generate <lexicon> Generate mode (build --components only): synthesize CI
|
|
344
|
+
YAML for <lexicon> instead of running a normal build.
|
|
345
|
+
Only "gitlab" is implemented for v1.
|
|
346
|
+
--no-release-record Skip auto-emitting a release-ledger record after a
|
|
347
|
+
successful \`run --components\` deploy (default: on;
|
|
348
|
+
also settable via chant.config.ts's
|
|
349
|
+
release.autoRecord: false; #597)
|
|
271
350
|
|
|
272
351
|
Examples:
|
|
273
352
|
chant build ./infra/
|
|
274
353
|
chant build ./infra/ --output stack.json
|
|
275
354
|
chant build ./infra/ --format yaml
|
|
276
355
|
chant build ./infra/ --watch
|
|
356
|
+
chant build ./infra/ --components --generate gitlab
|
|
357
|
+
chant build ./infra/ --components --generate gitlab --output .gitlab-ci.yml
|
|
358
|
+
chant run --components search-service --env staging
|
|
359
|
+
chant run --components all --env production
|
|
277
360
|
chant import template.json --output ./infra/
|
|
278
361
|
chant import --from prod --name my-bucket --output src/
|
|
279
362
|
chant lint ./infra/
|
|
@@ -332,6 +415,9 @@ const registry: CommandDef[] = [
|
|
|
332
415
|
{ name: "dev publish", requiresPlugins: true, handler: runDevPublish },
|
|
333
416
|
{ name: "dev onboard", handler: runDevOnboard },
|
|
334
417
|
{ name: "dev check-lexicon", handler: runDevCheckLexicon },
|
|
418
|
+
{ name: "dev surface-diff", handler: runDevSurfaceDiff },
|
|
419
|
+
{ name: "dev pinned-upgrade", handler: runDevPinnedUpgrade },
|
|
420
|
+
{ name: "dev rolling-upgrade", handler: runDevRollingUpgrade },
|
|
335
421
|
|
|
336
422
|
// Op / run subcommands
|
|
337
423
|
{ name: "run list", handler: runOpList },
|
|
@@ -352,6 +438,10 @@ const registry: CommandDef[] = [
|
|
|
352
438
|
{ name: "lifecycle affected", requiresPlugins: true, handler: runLifecycleAffected },
|
|
353
439
|
{ name: "lifecycle log", handler: runLifecycleLog },
|
|
354
440
|
|
|
441
|
+
// Component release ledger + status surface (#568, epic #551)
|
|
442
|
+
{ name: "components status", requiresPlugins: true, handler: runComponentsStatus },
|
|
443
|
+
{ name: "components release", handler: runComponentsReleaseRecord },
|
|
444
|
+
|
|
355
445
|
// Serve subcommands
|
|
356
446
|
{ name: "serve lsp", requiresPlugins: true, handler: runServeLsp },
|
|
357
447
|
{ name: "serve mcp", requiresPlugins: true, handler: runServeMcp },
|
|
@@ -360,6 +450,7 @@ const registry: CommandDef[] = [
|
|
|
360
450
|
{ name: "lifecycle", handler: runLifecycleUnknown },
|
|
361
451
|
{ name: "dev", handler: runDevUnknown },
|
|
362
452
|
{ name: "serve", handler: runServeUnknown },
|
|
453
|
+
{ name: "components", handler: runComponentsUnknown },
|
|
363
454
|
];
|
|
364
455
|
|
|
365
456
|
/**
|
|
@@ -414,8 +505,20 @@ async function main(): Promise<void> {
|
|
|
414
505
|
// which then fell through to import-detection on an empty file set and failed
|
|
415
506
|
// with "No lexicon detected" even though chant.config.ts lists the lexicons.
|
|
416
507
|
const projectPath = match.compound ? "." : args.path;
|
|
508
|
+
// `chant build --components --generate <lexicon>` (#563, generate mode)
|
|
509
|
+
// discovers `Component` declarations, not lexicon resources — a project
|
|
510
|
+
// made entirely of components has no reason to declare a chant lexicon
|
|
511
|
+
// plugin at all. Load plugins best-effort here instead of exiting, so
|
|
512
|
+
// generate mode works whether or not `chant.config.ts` names a lexicon.
|
|
513
|
+
// `components status` (#568) is the same shape: a components-only project
|
|
514
|
+
// may have no lexicon plugin, and `--live` reconciliation is opt-in, so
|
|
515
|
+
// missing plugins there is "no live evidence" (a warning), not a hard exit.
|
|
516
|
+
const isGenerateComponents = match.def.name === "build" && args.components && !!args.generate;
|
|
517
|
+
const isComponentsStatus = match.def.name === "components status";
|
|
417
518
|
const plugins = match.def.requiresPlugins
|
|
418
|
-
?
|
|
519
|
+
? isGenerateComponents || isComponentsStatus
|
|
520
|
+
? await loadPlugins(await resolveProjectLexicons(resolve(projectPath)).catch(() => [])).catch(() => [])
|
|
521
|
+
: await loadPluginsOrExit(projectPath)
|
|
419
522
|
: [];
|
|
420
523
|
const serializers = plugins.map((p) => p.serializer);
|
|
421
524
|
const ctx = { args, plugins, serializers };
|
package/src/cli/registry.ts
CHANGED
|
@@ -58,6 +58,13 @@ export interface ParsedArgs {
|
|
|
58
58
|
env?: string;
|
|
59
59
|
/** `chant graph --stacks` — render the cross-stack apply-ordering graph */
|
|
60
60
|
stacks?: boolean;
|
|
61
|
+
/** `chant list --components` / `chant graph --components` — surface discovered
|
|
62
|
+
* `Component` declarations (#560) instead of/alongside lexicon resources. */
|
|
63
|
+
components?: boolean;
|
|
64
|
+
/** `chant build --components --generate <lexicon>` — generate mode (#563):
|
|
65
|
+
* synthesize CI YAML from discovered components instead of running a normal
|
|
66
|
+
* lexicon build. Only "gitlab" is implemented for v1. */
|
|
67
|
+
generate?: string;
|
|
61
68
|
/** `chant graph --format ir --detail <0..3>` — graph IR detail tier */
|
|
62
69
|
detail?: number;
|
|
63
70
|
/** `chant graph --lens <kind>:<target>` — focus the graph IR on a slice */
|
|
@@ -83,6 +90,34 @@ export interface ParsedArgs {
|
|
|
83
90
|
failOn?: string;
|
|
84
91
|
/** `chant audit --theme <file>` — JSON theme knobs for the HTML report */
|
|
85
92
|
theme?: string;
|
|
93
|
+
/** `chant dev surface-diff --update-snapshot` — write the fresh snapshot as the new baseline */
|
|
94
|
+
updateSnapshot?: boolean;
|
|
95
|
+
/** `chant dev surface-diff --run-examples` — also run the example build harness */
|
|
96
|
+
runExamples?: boolean;
|
|
97
|
+
/** `chant dev surface-diff --pinned-digest <file>` — path to SHA-256 digest file for supply-chain verification */
|
|
98
|
+
pinnedDigest?: string;
|
|
99
|
+
/** `chant dev surface-diff --check` — verify the committed baseline matches a fresh regen; exit non-zero if it drifted. Never writes the snapshot. */
|
|
100
|
+
check?: boolean;
|
|
101
|
+
/** `chant dev surface-diff --update-snapshot --bump` — bump the lexicon's package.json version by the drift severity so the accepted surface is publishable (#616). */
|
|
102
|
+
bump?: boolean;
|
|
103
|
+
/** `chant components release record --component <name>` (#568) — component name for the release record being appended. */
|
|
104
|
+
component?: string;
|
|
105
|
+
/** `chant components release record --digest <sha256:...>` (#568) — artifact digest to record, joining this release to the build archive/ledger. */
|
|
106
|
+
digest?: string;
|
|
107
|
+
/** `chant components release record --git-sha <sha>` (#568) — git commit the deploy was built from. */
|
|
108
|
+
gitSha?: string;
|
|
109
|
+
/** `chant components release record --run-id <id>` (#568) — orchestrator/CI run identifier. */
|
|
110
|
+
runId?: string;
|
|
111
|
+
/** `chant components release record --actor <name>` (#568) — who/what triggered the deploy. */
|
|
112
|
+
actor?: string;
|
|
113
|
+
/** `chant components status <env> --compare-to <env>` (#568) — a second environment to cross-check the same component's recorded digest against. */
|
|
114
|
+
compareTo?: string;
|
|
115
|
+
/** `chant run --components <name> --env <env> --no-release-record` (#597) — opt out of auto-emitting a release-ledger record after a successful component deploy. Default (flag omitted): recording is ON. Also settable project-wide via `chant.config.ts`'s `release.autoRecord: false`. */
|
|
116
|
+
noReleaseRecord?: boolean;
|
|
117
|
+
/** `chant run --components <name> --dump-outputs <file>` — after the run, write the accumulated cross-component/cross-stack outputs (JSON, keyed by component name) to `<file>`, for a downstream job to `--seed-outputs`. */
|
|
118
|
+
dumpOutputs?: string;
|
|
119
|
+
/** `chant run --components <name> --seed-outputs <file>` (repeatable) — before the run, load each JSON outputs file (as written by `--dump-outputs`) and seed cross-component/cross-stack resolution with it, so a `stackOutput()`/`@<dep>.publish.*` reference to a component that ran in an earlier job resolves. */
|
|
120
|
+
seedOutputs?: string[];
|
|
86
121
|
}
|
|
87
122
|
|
|
88
123
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, test, expect, vi, afterEach } from "vitest";
|
|
2
|
-
import { extractFromTar, fetchWithRetry } from "./fetch";
|
|
2
|
+
import { extractFromTar, fetchWithRetry, TransientFetchError } from "./fetch";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Build a minimal valid tar buffer with a single file entry.
|
|
@@ -168,11 +168,16 @@ describe("fetchWithRetry", () => {
|
|
|
168
168
|
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
169
169
|
});
|
|
170
170
|
|
|
171
|
-
test("throws after exhausting retries on a transient status", async () => {
|
|
171
|
+
test("throws TransientFetchError after exhausting retries on a transient status", async () => {
|
|
172
172
|
const fetchMock = vi.fn().mockResolvedValue(status(504));
|
|
173
173
|
vi.stubGlobal("fetch", fetchMock);
|
|
174
174
|
|
|
175
|
-
await
|
|
175
|
+
const err = await fetchWithRetry("https://example.test/x", 2, 1).catch((e: unknown) => e);
|
|
176
|
+
expect(err).toBeInstanceOf(TransientFetchError);
|
|
177
|
+
expect((err as TransientFetchError).url).toBe("https://example.test/x");
|
|
178
|
+
expect((err as TransientFetchError).lastStatus).toBe(504);
|
|
179
|
+
expect((err as TransientFetchError).message).toContain("Transient fetch failure");
|
|
180
|
+
expect((err as TransientFetchError).message).toContain("HTTP 504");
|
|
176
181
|
// initial attempt + 2 retries
|
|
177
182
|
expect(fetchMock).toHaveBeenCalledTimes(3);
|
|
178
183
|
});
|
|
@@ -217,4 +222,80 @@ describe("fetchWithRetry", () => {
|
|
|
217
222
|
await expect(fetchWithRetry("https://example.test/x", 4, 1, init)).rejects.toThrow("returned 403");
|
|
218
223
|
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
219
224
|
});
|
|
225
|
+
|
|
226
|
+
test("429 then 200 succeeds after retry", async () => {
|
|
227
|
+
const fetchMock = vi
|
|
228
|
+
.fn()
|
|
229
|
+
.mockResolvedValueOnce(status(429))
|
|
230
|
+
.mockResolvedValueOnce(ok());
|
|
231
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
232
|
+
|
|
233
|
+
const resp = await fetchWithRetry("https://example.test/x", 4, 1);
|
|
234
|
+
expect(resp.ok).toBe(true);
|
|
235
|
+
expect(fetchMock).toHaveBeenCalledTimes(2);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
test("honors Retry-After header (seconds) on 429", async () => {
|
|
239
|
+
const sleepCalls: number[] = [];
|
|
240
|
+
// Intercept sleep without really waiting
|
|
241
|
+
vi.useFakeTimers();
|
|
242
|
+
|
|
243
|
+
const r429 = new Response("", {
|
|
244
|
+
status: 429,
|
|
245
|
+
headers: { "Retry-After": "2" },
|
|
246
|
+
});
|
|
247
|
+
const fetchMock = vi
|
|
248
|
+
.fn()
|
|
249
|
+
.mockResolvedValueOnce(r429)
|
|
250
|
+
.mockResolvedValueOnce(ok());
|
|
251
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
252
|
+
|
|
253
|
+
// Run with fake timers — advance all pending timers automatically
|
|
254
|
+
const resultPromise = fetchWithRetry("https://example.test/x", 4, 1);
|
|
255
|
+
await vi.runAllTimersAsync();
|
|
256
|
+
const resp = await resultPromise;
|
|
257
|
+
|
|
258
|
+
expect(resp.ok).toBe(true);
|
|
259
|
+
expect(fetchMock).toHaveBeenCalledTimes(2);
|
|
260
|
+
|
|
261
|
+
vi.useRealTimers();
|
|
262
|
+
void sleepCalls;
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
test("throws TransientFetchError with clear message on persistent 429", async () => {
|
|
266
|
+
const r429 = new Response("", { status: 429 });
|
|
267
|
+
const fetchMock = vi.fn().mockResolvedValue(r429);
|
|
268
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
269
|
+
|
|
270
|
+
const err = await fetchWithRetry("https://example.test/rate-limited", 2, 1).catch((e: unknown) => e);
|
|
271
|
+
expect(err).toBeInstanceOf(TransientFetchError);
|
|
272
|
+
const tfe = err as TransientFetchError;
|
|
273
|
+
expect(tfe.url).toBe("https://example.test/rate-limited");
|
|
274
|
+
expect(tfe.lastStatus).toBe(429);
|
|
275
|
+
expect(tfe.message).toContain("Transient fetch failure");
|
|
276
|
+
expect(tfe.message).toContain("HTTP 429");
|
|
277
|
+
expect(tfe.message).toContain("rate-limit or upstream outage");
|
|
278
|
+
expect(tfe.name).toBe("TransientFetchError");
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
test("throws TransientFetchError with clear message on persistent 5xx", async () => {
|
|
282
|
+
const fetchMock = vi.fn().mockResolvedValue(status(503));
|
|
283
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
284
|
+
|
|
285
|
+
const err = await fetchWithRetry("https://example.test/unavailable", 1, 1).catch((e: unknown) => e);
|
|
286
|
+
expect(err).toBeInstanceOf(TransientFetchError);
|
|
287
|
+
const tfe = err as TransientFetchError;
|
|
288
|
+
expect(tfe.lastStatus).toBe(503);
|
|
289
|
+
expect(tfe.message).toContain("HTTP 503");
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
test("TransientFetchError message includes attempt count", async () => {
|
|
293
|
+
const fetchMock = vi.fn().mockResolvedValue(status(500));
|
|
294
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
295
|
+
|
|
296
|
+
// 0 retries → exactly 1 attempt
|
|
297
|
+
const err = await fetchWithRetry("https://example.test/x", 0, 1).catch((e: unknown) => e);
|
|
298
|
+
expect(err).toBeInstanceOf(TransientFetchError);
|
|
299
|
+
expect((err as TransientFetchError).message).toContain("1 attempt");
|
|
300
|
+
});
|
|
220
301
|
});
|
package/src/codegen/fetch.ts
CHANGED
|
@@ -30,11 +30,38 @@ const RETRYABLE_STATUSES = new Set([408, 425, 429, 500, 502, 503, 504]);
|
|
|
30
30
|
|
|
31
31
|
const DEFAULT_RETRIES = 4;
|
|
32
32
|
const DEFAULT_BACKOFF_MS = 1000;
|
|
33
|
+
/** Hard cap on Retry-After delays so a rogue header cannot stall CI indefinitely. */
|
|
34
|
+
const MAX_RETRY_AFTER_MS = 60_000;
|
|
33
35
|
|
|
34
36
|
function sleep(ms: number): Promise<void> {
|
|
35
37
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
36
38
|
}
|
|
37
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Parse the `Retry-After` response header and return a delay in milliseconds.
|
|
42
|
+
*
|
|
43
|
+
* The header value may be an integer number of seconds or an HTTP-date.
|
|
44
|
+
* Returns `null` when the header is absent or unparseable.
|
|
45
|
+
* The returned value is capped at {@link MAX_RETRY_AFTER_MS}.
|
|
46
|
+
*/
|
|
47
|
+
function parseRetryAfter(response: Response): number | null {
|
|
48
|
+
const raw = response.headers.get("retry-after");
|
|
49
|
+
if (!raw) return null;
|
|
50
|
+
|
|
51
|
+
const seconds = Number(raw.trim());
|
|
52
|
+
if (!Number.isNaN(seconds) && seconds >= 0) {
|
|
53
|
+
return Math.min(Math.ceil(seconds * 1000), MAX_RETRY_AFTER_MS);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// HTTP-date format: "Wed, 01 Jul 2026 12:00:00 GMT"
|
|
57
|
+
const date = new Date(raw);
|
|
58
|
+
if (!Number.isNaN(date.getTime())) {
|
|
59
|
+
return Math.min(Math.max(0, date.getTime() - Date.now()), MAX_RETRY_AFTER_MS);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
38
65
|
/**
|
|
39
66
|
* Fetch a URL, retrying on transient failures (network errors and
|
|
40
67
|
* retryable HTTP statuses) with exponential backoff.
|
|
@@ -42,9 +69,16 @@ function sleep(ms: number): Promise<void> {
|
|
|
42
69
|
* Permanent failures (e.g. 404, 403) are not retried — they throw on the
|
|
43
70
|
* first response. The returned response is guaranteed `ok`.
|
|
44
71
|
*
|
|
72
|
+
* When a `Retry-After` header is present on a 429 or 503 response the delay
|
|
73
|
+
* from that header is used instead of the exponential back-off for that
|
|
74
|
+
* specific retry, capped at {@link MAX_RETRY_AFTER_MS}.
|
|
75
|
+
*
|
|
45
76
|
* `init` is passed through to `fetch` on every attempt, so callers that
|
|
46
77
|
* need request headers (e.g. the GitHub API `Accept` header) or an abort
|
|
47
78
|
* signal get retries without duplicating the loop.
|
|
79
|
+
*
|
|
80
|
+
* On exhaustion a descriptive {@link TransientFetchError} is thrown rather
|
|
81
|
+
* than the raw last error so the caller can surface a human-readable message.
|
|
48
82
|
*/
|
|
49
83
|
export async function fetchWithRetry(
|
|
50
84
|
url: string,
|
|
@@ -52,12 +86,17 @@ export async function fetchWithRetry(
|
|
|
52
86
|
backoffMs = DEFAULT_BACKOFF_MS,
|
|
53
87
|
init?: RequestInit,
|
|
54
88
|
): Promise<Response> {
|
|
89
|
+
let lastStatus: number | undefined;
|
|
55
90
|
let lastError: Error | undefined;
|
|
91
|
+
// When a response carries a Retry-After header, the indicated delay replaces
|
|
92
|
+
// the exponential back-off for that specific next retry.
|
|
93
|
+
let retryAfterOverride: number | null = null;
|
|
56
94
|
|
|
57
95
|
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
58
96
|
if (attempt > 0) {
|
|
59
|
-
const delay = backoffMs * 2 ** (attempt - 1);
|
|
97
|
+
const delay = retryAfterOverride ?? backoffMs * 2 ** (attempt - 1);
|
|
60
98
|
debug(`retrying ${url} (attempt ${attempt}/${retries}) after ${delay}ms: ${lastError?.message}`);
|
|
99
|
+
retryAfterOverride = null;
|
|
61
100
|
await sleep(delay);
|
|
62
101
|
}
|
|
63
102
|
|
|
@@ -67,6 +106,7 @@ export async function fetchWithRetry(
|
|
|
67
106
|
} catch (e) {
|
|
68
107
|
// Network-level failure (DNS, connection reset, timeout). Transient.
|
|
69
108
|
lastError = e instanceof Error ? e : new Error(String(e));
|
|
109
|
+
lastStatus = undefined;
|
|
70
110
|
continue;
|
|
71
111
|
}
|
|
72
112
|
|
|
@@ -74,10 +114,44 @@ export async function fetchWithRetry(
|
|
|
74
114
|
|
|
75
115
|
const err = new Error(`Download from ${url} returned ${response.status}`);
|
|
76
116
|
if (!RETRYABLE_STATUSES.has(response.status)) throw err;
|
|
117
|
+
|
|
77
118
|
lastError = err;
|
|
119
|
+
lastStatus = response.status;
|
|
120
|
+
|
|
121
|
+
// Capture Retry-After so the next loop iteration uses it instead of backoff
|
|
122
|
+
const retryAfterMs = parseRetryAfter(response);
|
|
123
|
+
if (retryAfterMs !== null) {
|
|
124
|
+
debug(`Retry-After for ${url}: ${retryAfterMs}ms`);
|
|
125
|
+
retryAfterOverride = retryAfterMs;
|
|
126
|
+
}
|
|
78
127
|
}
|
|
79
128
|
|
|
80
|
-
throw
|
|
129
|
+
throw new TransientFetchError(url, retries, lastStatus, lastError);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Thrown when {@link fetchWithRetry} exhausts all retry attempts on a
|
|
134
|
+
* transient failure (429 / 5xx / network error).
|
|
135
|
+
*
|
|
136
|
+
* The message is human-readable and actionable: it names the URL, the number
|
|
137
|
+
* of attempts made, and the last HTTP status (if any) so that an upstream Op
|
|
138
|
+
* can route it to a report/issue without exposing a raw stack trace.
|
|
139
|
+
*/
|
|
140
|
+
export class TransientFetchError extends Error {
|
|
141
|
+
constructor(
|
|
142
|
+
public readonly url: string,
|
|
143
|
+
public readonly retries: number,
|
|
144
|
+
public readonly lastStatus: number | undefined,
|
|
145
|
+
public readonly cause?: Error,
|
|
146
|
+
) {
|
|
147
|
+
const attempts = retries + 1;
|
|
148
|
+
const statusPart = lastStatus !== undefined ? ` (HTTP ${lastStatus})` : "";
|
|
149
|
+
super(
|
|
150
|
+
`Transient fetch failure for ${url}${statusPart} — failed after ${attempts} attempt${attempts === 1 ? "" : "s"}. ` +
|
|
151
|
+
`This is typically a rate-limit or upstream outage. Retry later or check upstream status.`,
|
|
152
|
+
);
|
|
153
|
+
this.name = "TransientFetchError";
|
|
154
|
+
}
|
|
81
155
|
}
|
|
82
156
|
|
|
83
157
|
// ── Fetch with cache ───────────────────────────────────────────────
|