@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
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lexicon regen-validate pipeline.
|
|
3
|
+
*
|
|
4
|
+
* Given a lexicon root directory, this module:
|
|
5
|
+
* 1. Runs the prepack chain (generate -> bundle -> validate -> build)
|
|
6
|
+
* by invoking `npm run <script>` in the lexicon directory.
|
|
7
|
+
* 2. Runs `chant lint` on any examples found under `examples/`.
|
|
8
|
+
* 3. Extracts the generated public API surface.
|
|
9
|
+
* 4. Diffs the fresh surface against the committed per-lexicon baseline
|
|
10
|
+
* (`surface.snapshot.json` at the lexicon root).
|
|
11
|
+
* 5. Returns { ok, changed, severity, delta, failures } — never throws.
|
|
12
|
+
*
|
|
13
|
+
* Supply-chain guarantee:
|
|
14
|
+
* All spec fetching happens through the lexicon's own `generate` script,
|
|
15
|
+
* which is pinned to the lexicon's existing fetch layer (cached, TTL-based).
|
|
16
|
+
* When `force` is true, the cache is bypassed and the spec is re-downloaded.
|
|
17
|
+
* This module never executes spec-provided content — it only reads the
|
|
18
|
+
* artifacts that the generate script produced.
|
|
19
|
+
*
|
|
20
|
+
* Never auto-fix:
|
|
21
|
+
* Any failure is captured into `failures` and returned. This module never
|
|
22
|
+
* rewrites examples, skips checks, or masks errors.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { existsSync, readFileSync, writeFileSync, readdirSync, type Dirent } from "fs";
|
|
26
|
+
import { join } from "path";
|
|
27
|
+
import { execSync } from "child_process";
|
|
28
|
+
import {
|
|
29
|
+
extractSurface,
|
|
30
|
+
diffSurface,
|
|
31
|
+
serializeSnapshot,
|
|
32
|
+
parseSnapshot,
|
|
33
|
+
formatDelta,
|
|
34
|
+
type SurfaceDelta,
|
|
35
|
+
type ChangeSeverity,
|
|
36
|
+
type SurfaceSnapshot,
|
|
37
|
+
} from "./surface-snapshot";
|
|
38
|
+
|
|
39
|
+
// ── Public types ─────────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
export interface RegenFailure {
|
|
42
|
+
/**
|
|
43
|
+
* Which step failed:
|
|
44
|
+
* "setup" | "digest-verify" | "generate" | "bundle" | "validate"
|
|
45
|
+
* | "build" | "lint" | "examples" | "surface-extract" | "surface-diff"
|
|
46
|
+
*/
|
|
47
|
+
step: string;
|
|
48
|
+
/** Exit code from the subprocess, if applicable. */
|
|
49
|
+
exitCode?: number;
|
|
50
|
+
/** Combined stdout+stderr output captured from the subprocess. */
|
|
51
|
+
output: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface RegenResult {
|
|
55
|
+
/** True only when all steps passed and (if a baseline exists) the diff completed. */
|
|
56
|
+
ok: boolean;
|
|
57
|
+
/** True when the surface changed versus the baseline. */
|
|
58
|
+
changed: boolean;
|
|
59
|
+
/** Rolled-up severity of the surface delta. "none" when unchanged. */
|
|
60
|
+
severity: ChangeSeverity;
|
|
61
|
+
/** Structured delta: what was added, changed, or removed. */
|
|
62
|
+
delta: SurfaceDelta;
|
|
63
|
+
/** Human-readable delta text (empty string when no changes). */
|
|
64
|
+
deltaText: string;
|
|
65
|
+
/** Step failures captured during the run. */
|
|
66
|
+
failures: RegenFailure[];
|
|
67
|
+
/** Fresh surface snapshot — caller can write this as the new baseline. */
|
|
68
|
+
freshSnapshot: SurfaceSnapshot | null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface RegenOptions {
|
|
72
|
+
/**
|
|
73
|
+
* Root of the lexicon package (e.g. `/path/to/lexicons/aws`).
|
|
74
|
+
* Must contain a `package.json` with `generate`, `bundle`, `validate`, `build` scripts.
|
|
75
|
+
*/
|
|
76
|
+
lexiconDir: string;
|
|
77
|
+
/**
|
|
78
|
+
* When true, pass `CHANT_FORCE_FETCH=1` to the generate step so the spec is
|
|
79
|
+
* re-downloaded from upstream even if the cache is fresh.
|
|
80
|
+
*/
|
|
81
|
+
force?: boolean;
|
|
82
|
+
/** Print subprocess output as it runs. Default: false. */
|
|
83
|
+
verbose?: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Skip the `bundle` step. Useful when testing without a full dist build.
|
|
86
|
+
* Default: false.
|
|
87
|
+
*/
|
|
88
|
+
skipBundle?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Skip the `build` (tsc) step. Useful in test contexts where tsc is not available.
|
|
91
|
+
* Default: false.
|
|
92
|
+
*/
|
|
93
|
+
skipBuild?: boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Skip running `chant lint` on examples.
|
|
96
|
+
* Default: false.
|
|
97
|
+
*/
|
|
98
|
+
skipLint?: boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Skip running example deploy harness (npm run deploy / npm run build in each example).
|
|
101
|
+
* Default: true (examples require live cloud credentials; opt-in only).
|
|
102
|
+
*/
|
|
103
|
+
skipExamples?: boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Path to a SHA-256 digest file pinning the spec cache file.
|
|
106
|
+
*
|
|
107
|
+
* When provided, this module verifies the digest of the cached spec file
|
|
108
|
+
* before invoking `generate`. This is the supply-chain choke point:
|
|
109
|
+
* untrusted upstream content is verified here before any downstream processing.
|
|
110
|
+
* The spec file is never executed — only checksummed and then passed to the
|
|
111
|
+
* lexicon's own generator as data.
|
|
112
|
+
*
|
|
113
|
+
* File format (shasum -a 256 style):
|
|
114
|
+
* sha256:<64-hex-chars> <relative-path-to-spec-file>
|
|
115
|
+
*/
|
|
116
|
+
pinnedDigestPath?: string;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ── Pipeline ──────────────────────────────────────────────────────────
|
|
120
|
+
|
|
121
|
+
export const SNAPSHOT_FILENAME = "surface.snapshot.json";
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Run the full regen-validate pipeline for a lexicon and return the result.
|
|
125
|
+
*/
|
|
126
|
+
export async function regenLexicon(opts: RegenOptions): Promise<RegenResult> {
|
|
127
|
+
const {
|
|
128
|
+
lexiconDir,
|
|
129
|
+
force = false,
|
|
130
|
+
verbose = false,
|
|
131
|
+
skipBundle = false,
|
|
132
|
+
skipBuild = false,
|
|
133
|
+
skipLint = false,
|
|
134
|
+
skipExamples = true,
|
|
135
|
+
} = opts;
|
|
136
|
+
|
|
137
|
+
const failures: RegenFailure[] = [];
|
|
138
|
+
|
|
139
|
+
// Verify lexicon directory
|
|
140
|
+
if (!existsSync(join(lexiconDir, "package.json"))) {
|
|
141
|
+
failures.push({
|
|
142
|
+
step: "setup",
|
|
143
|
+
output: `No package.json found at ${lexiconDir}`,
|
|
144
|
+
});
|
|
145
|
+
return makeResult(false, failures, null, null);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Step 1: Verify pinned digest (supply-chain gate, runs before fetch)
|
|
149
|
+
if (opts.pinnedDigestPath) {
|
|
150
|
+
const digestFailure = await verifyPinnedDigest(lexiconDir, opts.pinnedDigestPath);
|
|
151
|
+
if (digestFailure) {
|
|
152
|
+
failures.push(digestFailure);
|
|
153
|
+
return makeResult(false, failures, null, null);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Step 2: generate
|
|
158
|
+
// Pass CHANT_FORCE_FETCH=1 so lexicons that check this env var will bypass cache.
|
|
159
|
+
const genEnv: NodeJS.ProcessEnv = force
|
|
160
|
+
? { ...process.env, CHANT_FORCE_FETCH: "1" }
|
|
161
|
+
: { ...process.env };
|
|
162
|
+
|
|
163
|
+
const genFail = runScript(lexiconDir, "generate", genEnv, verbose);
|
|
164
|
+
if (genFail) {
|
|
165
|
+
failures.push(genFail);
|
|
166
|
+
// Cannot proceed without generated artifacts
|
|
167
|
+
return makeResult(false, failures, null, null);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Step 3: bundle (optional)
|
|
171
|
+
if (!skipBundle) {
|
|
172
|
+
const bundleFail = runScript(lexiconDir, "bundle", process.env, verbose);
|
|
173
|
+
if (bundleFail) {
|
|
174
|
+
failures.push(bundleFail);
|
|
175
|
+
// Continue to extract surface even if bundle fails
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Step 4: validate
|
|
180
|
+
const validateFail = runScript(lexiconDir, "validate", process.env, verbose);
|
|
181
|
+
if (validateFail) {
|
|
182
|
+
failures.push(validateFail);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Step 5: build (tsc)
|
|
186
|
+
if (!skipBuild) {
|
|
187
|
+
const buildFail = runScript(lexiconDir, "build", process.env, verbose);
|
|
188
|
+
if (buildFail) {
|
|
189
|
+
failures.push(buildFail);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Step 6: lint examples
|
|
194
|
+
if (!skipLint) {
|
|
195
|
+
const lintFail = runLintOnExamples(lexiconDir, verbose);
|
|
196
|
+
if (lintFail) {
|
|
197
|
+
failures.push(lintFail);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Step 7: example harness (opt-in only; requires cloud credentials)
|
|
202
|
+
if (!skipExamples) {
|
|
203
|
+
const exFail = runExampleHarness(lexiconDir, verbose);
|
|
204
|
+
if (exFail) {
|
|
205
|
+
failures.push(exFail);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Step 8: extract surface from generated artifacts
|
|
210
|
+
const freshSnapshot = extractFreshSurface(lexiconDir);
|
|
211
|
+
if (!freshSnapshot) {
|
|
212
|
+
failures.push({
|
|
213
|
+
step: "surface-extract",
|
|
214
|
+
output: `Could not read generated artifacts in ${join(lexiconDir, "src", "generated")}. The generate step should have produced them.`,
|
|
215
|
+
});
|
|
216
|
+
return makeResult(false, failures, null, null);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Step 9: diff against baseline
|
|
220
|
+
const baselinePath = join(lexiconDir, SNAPSHOT_FILENAME);
|
|
221
|
+
let delta: SurfaceDelta;
|
|
222
|
+
|
|
223
|
+
if (existsSync(baselinePath)) {
|
|
224
|
+
try {
|
|
225
|
+
const baselineJSON = readFileSync(baselinePath, "utf-8");
|
|
226
|
+
const baseline = parseSnapshot(baselineJSON);
|
|
227
|
+
delta = diffSurface(baseline, freshSnapshot);
|
|
228
|
+
} catch (err) {
|
|
229
|
+
failures.push({
|
|
230
|
+
step: "surface-diff",
|
|
231
|
+
output: `Failed to read or parse baseline snapshot at ${baselinePath}: ${String(err)}`,
|
|
232
|
+
});
|
|
233
|
+
return makeResult(false, failures, freshSnapshot, null);
|
|
234
|
+
}
|
|
235
|
+
} else {
|
|
236
|
+
// No baseline — treat entire current surface as "added"
|
|
237
|
+
const emptyBaseline: SurfaceSnapshot = {
|
|
238
|
+
schemaVersion: 1,
|
|
239
|
+
generatedAt: new Date(0).toISOString(),
|
|
240
|
+
entries: {},
|
|
241
|
+
};
|
|
242
|
+
delta = diffSurface(emptyBaseline, freshSnapshot);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const ok = failures.length === 0;
|
|
246
|
+
return makeResult(ok, failures, freshSnapshot, delta);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Write the fresh surface snapshot to the lexicon's committed baseline file.
|
|
251
|
+
* Call this after a successful regen when the snapshot should be updated.
|
|
252
|
+
*/
|
|
253
|
+
export function writeSurfaceSnapshot(lexiconDir: string, snapshot: SurfaceSnapshot): void {
|
|
254
|
+
const path = join(lexiconDir, SNAPSHOT_FILENAME);
|
|
255
|
+
writeFileSync(path, serializeSnapshot(snapshot), "utf-8");
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// ── Subprocess helpers ────────────────────────────────────────────────
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Run one npm script in the lexicon directory.
|
|
262
|
+
* Returns a RegenFailure on non-zero exit; null on success.
|
|
263
|
+
*/
|
|
264
|
+
function runScript(
|
|
265
|
+
cwd: string,
|
|
266
|
+
script: string,
|
|
267
|
+
env: NodeJS.ProcessEnv,
|
|
268
|
+
verbose: boolean,
|
|
269
|
+
): RegenFailure | null {
|
|
270
|
+
try {
|
|
271
|
+
const out = execSync(`npm run --silent ${script}`, {
|
|
272
|
+
cwd,
|
|
273
|
+
env,
|
|
274
|
+
stdio: verbose ? "inherit" : "pipe",
|
|
275
|
+
encoding: "utf-8",
|
|
276
|
+
timeout: 10 * 60 * 1000, // 10 minutes
|
|
277
|
+
});
|
|
278
|
+
if (verbose && typeof out === "string" && out) process.stderr.write(out);
|
|
279
|
+
return null;
|
|
280
|
+
} catch (err: unknown) {
|
|
281
|
+
const e = err as { stdout?: string; stderr?: string; status?: number; message?: string };
|
|
282
|
+
const captured = [e.stdout ?? "", e.stderr ?? ""].filter(Boolean).join("\n");
|
|
283
|
+
return {
|
|
284
|
+
step: script,
|
|
285
|
+
exitCode: e.status ?? 1,
|
|
286
|
+
output: captured || e.message || String(err),
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Run `chant lint` on each example subdirectory.
|
|
293
|
+
*/
|
|
294
|
+
function runLintOnExamples(lexiconDir: string, verbose: boolean): RegenFailure | null {
|
|
295
|
+
const examplesDir = join(lexiconDir, "examples");
|
|
296
|
+
if (!existsSync(examplesDir)) return null;
|
|
297
|
+
|
|
298
|
+
let entries: Dirent<string>[];
|
|
299
|
+
try {
|
|
300
|
+
entries = readdirSync(examplesDir, { withFileTypes: true, encoding: "utf-8" });
|
|
301
|
+
} catch {
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const exampleDirs = entries
|
|
306
|
+
.filter((e) => e.isDirectory())
|
|
307
|
+
.map((e) => join(examplesDir, e.name))
|
|
308
|
+
.filter((d) => existsSync(join(d, "chant.config.ts")) || existsSync(join(d, "src")));
|
|
309
|
+
|
|
310
|
+
if (exampleDirs.length === 0) return null;
|
|
311
|
+
|
|
312
|
+
const chantBin = resolveChantBin(lexiconDir);
|
|
313
|
+
const outputs: string[] = [];
|
|
314
|
+
let failed = false;
|
|
315
|
+
|
|
316
|
+
for (const exDir of exampleDirs) {
|
|
317
|
+
try {
|
|
318
|
+
const out = execSync(`${chantBin} lint ${exDir}`, {
|
|
319
|
+
stdio: verbose ? "inherit" : "pipe",
|
|
320
|
+
encoding: "utf-8",
|
|
321
|
+
timeout: 60 * 1000,
|
|
322
|
+
});
|
|
323
|
+
if (verbose && typeof out === "string" && out) process.stderr.write(out);
|
|
324
|
+
} catch (err: unknown) {
|
|
325
|
+
const e = err as { stdout?: string; stderr?: string; status?: number };
|
|
326
|
+
const captured = [e.stdout ?? "", e.stderr ?? ""].filter(Boolean).join(" ").trim();
|
|
327
|
+
outputs.push(`[${exDir}] exit ${e.status ?? 1}: ${captured}`);
|
|
328
|
+
failed = true;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (failed) {
|
|
333
|
+
return { step: "lint", output: outputs.join("\n") };
|
|
334
|
+
}
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Run `npm run build --if-present` in each example directory.
|
|
340
|
+
* Opt-in only — requires cloud credentials in most cases.
|
|
341
|
+
*/
|
|
342
|
+
function runExampleHarness(lexiconDir: string, verbose: boolean): RegenFailure | null {
|
|
343
|
+
const examplesDir = join(lexiconDir, "examples");
|
|
344
|
+
if (!existsSync(examplesDir)) return null;
|
|
345
|
+
|
|
346
|
+
let entries: Dirent<string>[];
|
|
347
|
+
try {
|
|
348
|
+
entries = readdirSync(examplesDir, { withFileTypes: true, encoding: "utf-8" });
|
|
349
|
+
} catch {
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const exampleDirs = entries
|
|
354
|
+
.filter((e) => e.isDirectory())
|
|
355
|
+
.map((e) => join(examplesDir, e.name))
|
|
356
|
+
.filter((d) => existsSync(join(d, "package.json")));
|
|
357
|
+
|
|
358
|
+
const outputs: string[] = [];
|
|
359
|
+
let failed = false;
|
|
360
|
+
|
|
361
|
+
for (const exDir of exampleDirs) {
|
|
362
|
+
try {
|
|
363
|
+
const out = execSync("npm run build --if-present", {
|
|
364
|
+
cwd: exDir,
|
|
365
|
+
stdio: verbose ? "inherit" : "pipe",
|
|
366
|
+
encoding: "utf-8",
|
|
367
|
+
timeout: 5 * 60 * 1000,
|
|
368
|
+
});
|
|
369
|
+
if (verbose && typeof out === "string" && out) process.stderr.write(out);
|
|
370
|
+
} catch (err: unknown) {
|
|
371
|
+
const e = err as { stdout?: string; stderr?: string; status?: number };
|
|
372
|
+
const captured = [e.stdout ?? "", e.stderr ?? ""].filter(Boolean).join(" ").trim();
|
|
373
|
+
outputs.push(`[${exDir}] exit ${e.status ?? 1}: ${captured}`);
|
|
374
|
+
failed = true;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (failed) {
|
|
379
|
+
return { step: "examples", output: outputs.join("\n") };
|
|
380
|
+
}
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Extract the fresh surface from the generated artifacts in the lexicon directory.
|
|
386
|
+
*/
|
|
387
|
+
function extractFreshSurface(lexiconDir: string): SurfaceSnapshot | null {
|
|
388
|
+
const generatedDir = join(lexiconDir, "src", "generated");
|
|
389
|
+
if (!existsSync(generatedDir)) return null;
|
|
390
|
+
|
|
391
|
+
let files: string[];
|
|
392
|
+
try {
|
|
393
|
+
files = readdirSync(generatedDir, { encoding: "utf-8" });
|
|
394
|
+
} catch {
|
|
395
|
+
return null;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
const lexiconFile = files.find((f) => f.startsWith("lexicon-") && f.endsWith(".json"));
|
|
399
|
+
if (!lexiconFile) return null;
|
|
400
|
+
|
|
401
|
+
let lexiconJSON: string;
|
|
402
|
+
try {
|
|
403
|
+
lexiconJSON = readFileSync(join(generatedDir, lexiconFile), "utf-8");
|
|
404
|
+
} catch {
|
|
405
|
+
return null;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
let typesDTS = "";
|
|
409
|
+
const dtsPath = join(generatedDir, "index.d.ts");
|
|
410
|
+
if (existsSync(dtsPath)) {
|
|
411
|
+
try {
|
|
412
|
+
typesDTS = readFileSync(dtsPath, "utf-8");
|
|
413
|
+
} catch {
|
|
414
|
+
// Proceed without .d.ts — props won't be extracted
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
try {
|
|
419
|
+
return extractSurface(lexiconJSON, typesDTS);
|
|
420
|
+
} catch {
|
|
421
|
+
return null;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Verify the spec cache file against a pinned SHA-256 digest.
|
|
427
|
+
*
|
|
428
|
+
* Digest file format (shasum -a 256 style):
|
|
429
|
+
* sha256:<64-hex-chars> <relative-path-to-spec-file>
|
|
430
|
+
*/
|
|
431
|
+
async function verifyPinnedDigest(
|
|
432
|
+
lexiconDir: string,
|
|
433
|
+
digestPath: string,
|
|
434
|
+
): Promise<RegenFailure | null> {
|
|
435
|
+
if (!existsSync(digestPath)) {
|
|
436
|
+
return {
|
|
437
|
+
step: "digest-verify",
|
|
438
|
+
output: `Pinned digest file not found: ${digestPath}`,
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
let digestContent: string;
|
|
443
|
+
try {
|
|
444
|
+
digestContent = readFileSync(digestPath, "utf-8").trim();
|
|
445
|
+
} catch (err) {
|
|
446
|
+
return {
|
|
447
|
+
step: "digest-verify",
|
|
448
|
+
output: `Cannot read digest file ${digestPath}: ${String(err)}`,
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
const digestMatch = /^sha256:([a-f0-9]{64})\s+(.+)$/.exec(digestContent);
|
|
453
|
+
if (!digestMatch) {
|
|
454
|
+
return {
|
|
455
|
+
step: "digest-verify",
|
|
456
|
+
output: `Malformed digest file (expected "sha256:<hex> <filename>"): ${digestPath}`,
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
const [, expectedHex, relFilename] = digestMatch;
|
|
461
|
+
const specPath = join(lexiconDir, relFilename);
|
|
462
|
+
|
|
463
|
+
if (!existsSync(specPath)) {
|
|
464
|
+
return {
|
|
465
|
+
step: "digest-verify",
|
|
466
|
+
output: `Spec file referenced in digest not found: ${specPath}. Run generate first or check the digest file path.`,
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
try {
|
|
471
|
+
const { createHash } = await import("crypto");
|
|
472
|
+
const data = readFileSync(specPath);
|
|
473
|
+
const actualHex = createHash("sha256").update(data).digest("hex");
|
|
474
|
+
|
|
475
|
+
if (actualHex !== expectedHex) {
|
|
476
|
+
return {
|
|
477
|
+
step: "digest-verify",
|
|
478
|
+
output: [
|
|
479
|
+
`Spec digest mismatch for ${relFilename}:`,
|
|
480
|
+
` expected: ${expectedHex}`,
|
|
481
|
+
` actual: ${actualHex}`,
|
|
482
|
+
"",
|
|
483
|
+
"The cached spec does not match the pinned digest.",
|
|
484
|
+
"Re-fetch with --force to update the cache, then update the digest file.",
|
|
485
|
+
].join("\n"),
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
return null;
|
|
490
|
+
} catch (err) {
|
|
491
|
+
return {
|
|
492
|
+
step: "digest-verify",
|
|
493
|
+
output: `Digest computation failed: ${String(err)}`,
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Resolve the chant binary path from the lexicon's workspace node_modules.
|
|
500
|
+
*/
|
|
501
|
+
function resolveChantBin(lexiconDir: string): string {
|
|
502
|
+
// Try workspace root node_modules (two levels up from lexicons/<name>)
|
|
503
|
+
const rootBin = join(lexiconDir, "..", "..", "node_modules", ".bin", "chant");
|
|
504
|
+
if (existsSync(rootBin)) return rootBin;
|
|
505
|
+
|
|
506
|
+
// Try lexicon-local node_modules
|
|
507
|
+
const localBin = join(lexiconDir, "node_modules", ".bin", "chant");
|
|
508
|
+
if (existsSync(localBin)) return localBin;
|
|
509
|
+
|
|
510
|
+
// Fall back to npx
|
|
511
|
+
return "npx chant";
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* Build the final RegenResult.
|
|
516
|
+
*/
|
|
517
|
+
function makeResult(
|
|
518
|
+
ok: boolean,
|
|
519
|
+
failures: RegenFailure[],
|
|
520
|
+
freshSnapshot: SurfaceSnapshot | null,
|
|
521
|
+
delta: SurfaceDelta | null,
|
|
522
|
+
): RegenResult {
|
|
523
|
+
const emptyDelta: SurfaceDelta = {
|
|
524
|
+
added: [],
|
|
525
|
+
changed: [],
|
|
526
|
+
removed: [],
|
|
527
|
+
severity: "none",
|
|
528
|
+
};
|
|
529
|
+
const effectiveDelta = delta ?? emptyDelta;
|
|
530
|
+
const changed =
|
|
531
|
+
effectiveDelta.added.length > 0 ||
|
|
532
|
+
effectiveDelta.changed.length > 0 ||
|
|
533
|
+
effectiveDelta.removed.length > 0;
|
|
534
|
+
const deltaText = changed ? formatDelta(effectiveDelta) : "";
|
|
535
|
+
|
|
536
|
+
return {
|
|
537
|
+
ok,
|
|
538
|
+
changed,
|
|
539
|
+
severity: effectiveDelta.severity,
|
|
540
|
+
delta: effectiveDelta,
|
|
541
|
+
deltaText,
|
|
542
|
+
failures,
|
|
543
|
+
freshSnapshot,
|
|
544
|
+
};
|
|
545
|
+
}
|