@intentius/chant 0.100.0 → 0.102.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/checks.d.ts.map +1 -1
- package/dist/attrref.d.ts.map +1 -1
- package/dist/audit/discover.d.ts.map +1 -1
- package/dist/audit/nginx.d.ts.map +1 -1
- package/dist/audit/prior-art.d.ts +48 -0
- package/dist/audit/prior-art.d.ts.map +1 -1
- package/dist/behaviour-kinds.d.ts.map +1 -1
- package/dist/build.d.ts +6 -0
- package/dist/build.d.ts.map +1 -1
- package/dist/builder.d.ts.map +1 -1
- package/dist/cli/build-options.d.ts +2 -0
- package/dist/cli/build-options.d.ts.map +1 -1
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/carve-emit.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon.d.ts +16 -0
- package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
- package/dist/cli/commands/import.d.ts +8 -0
- package/dist/cli/commands/import.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
- package/dist/cli/commands/init.d.ts +19 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/onboard.d.ts +9 -0
- package/dist/cli/commands/onboard.d.ts.map +1 -1
- package/dist/cli/commands/pinned-upgrade.d.ts +19 -5
- package/dist/cli/commands/pinned-upgrade.d.ts.map +1 -1
- package/dist/cli/handlers/dev.d.ts.map +1 -1
- package/dist/cli/handlers/fan-out.d.ts.map +1 -1
- package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
- package/dist/cli/handlers/misc.d.ts.map +1 -1
- package/dist/cli/handlers/operator.d.ts +9 -0
- package/dist/cli/handlers/operator.d.ts.map +1 -1
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/lsp/server.d.ts.map +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/mcp/server.d.ts.map +1 -1
- package/dist/cli/mcp/tools/build.d.ts.map +1 -1
- package/dist/cli/mcp/tools/composites.d.ts.map +1 -1
- package/dist/cli/mcp/tools/explain.d.ts.map +1 -1
- package/dist/cli/mcp/tools/import.d.ts.map +1 -1
- package/dist/cli/mcp/tools/lint.d.ts.map +1 -1
- package/dist/cli/mcp/tools/scaffold.d.ts.map +1 -1
- package/dist/cli/mcp/tools/search.d.ts.map +1 -1
- package/dist/cli/mcp/workspace-tools.d.ts +9 -1
- package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +33 -2
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/codegen/fetch.d.ts.map +1 -1
- package/dist/codegen/naming.d.ts.map +1 -1
- package/dist/codegen/pinned-upgrade.d.ts +67 -3
- package/dist/codegen/pinned-upgrade.d.ts.map +1 -1
- package/dist/codegen/registry.d.ts.map +1 -1
- package/dist/components/capability-plugin-loader.d.ts.map +1 -1
- package/dist/components/capability.d.ts.map +1 -1
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/fan-out.d.ts.map +1 -1
- package/dist/components/starter-plugin.d.ts.map +1 -1
- package/dist/components/verbs/process-runner.d.ts.map +1 -1
- package/dist/components/verbs/r2-sync.d.ts.map +1 -1
- package/dist/components/verbs/run-agent.d.ts.map +1 -1
- package/dist/components/verbs/sbom-generator.d.ts.map +1 -1
- package/dist/components/verbs/sign.d.ts.map +1 -1
- package/dist/components/verbs/verify.d.ts.map +1 -1
- package/dist/components/verbs/vuln-gate.d.ts.map +1 -1
- package/dist/components/verbs/vuln-scan.d.ts.map +1 -1
- package/dist/components/verbs/wrangler.d.ts.map +1 -1
- package/dist/composite.d.ts.map +1 -1
- package/dist/config.d.ts +30 -7
- package/dist/config.d.ts.map +1 -1
- package/dist/declarable.d.ts +16 -0
- package/dist/declarable.d.ts.map +1 -1
- package/dist/discovery/cache.d.ts.map +1 -1
- package/dist/discovery/fold-import.d.ts +15 -5
- package/dist/discovery/fold-import.d.ts.map +1 -1
- package/dist/discovery/param-deps.d.ts +16 -0
- package/dist/discovery/param-deps.d.ts.map +1 -1
- package/dist/discovery/sandbox/policy-wire.d.ts.map +1 -1
- package/dist/discovery/specifier-resolve.d.ts +37 -0
- package/dist/discovery/specifier-resolve.d.ts.map +1 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/fold/fold.d.ts +3 -1
- package/dist/fold/fold.d.ts.map +1 -1
- package/dist/graph-detail.d.ts.map +1 -1
- package/dist/graph-ir.d.ts.map +1 -1
- package/dist/graph-layout.d.ts.map +1 -1
- package/dist/import/base-parser.d.ts.map +1 -1
- package/dist/import/embedded.d.ts +7 -0
- package/dist/import/embedded.d.ts.map +1 -1
- package/dist/import/parser-options.d.ts +14 -0
- package/dist/import/parser-options.d.ts.map +1 -0
- package/dist/import/parser.d.ts +17 -0
- package/dist/import/parser.d.ts.map +1 -1
- package/dist/kubectl-context.d.ts.map +1 -1
- package/dist/lexicon-output.d.ts.map +1 -1
- package/dist/lexicon-schema.d.ts +3 -3
- package/dist/lexicon.d.ts +78 -3
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/assert-live.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.d.ts +15 -0
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lifecycle/member-ledger.d.ts.map +1 -1
- package/dist/lifecycle/observe.d.ts.map +1 -1
- package/dist/lifecycle/plan-digest.d.ts +26 -5
- package/dist/lifecycle/plan-digest.d.ts.map +1 -1
- package/dist/lifecycle/plan-ledger.d.ts.map +1 -1
- package/dist/lifecycle/release-ledger.d.ts.map +1 -1
- package/dist/lifecycle/scenario.d.ts.map +1 -1
- package/dist/lifecycle/status.d.ts.map +1 -1
- package/dist/lifecycle/work-lease.d.ts +61 -2
- package/dist/lifecycle/work-lease.d.ts.map +1 -1
- package/dist/lint/config.d.ts +4 -4
- package/dist/lint/engine.d.ts +6 -0
- package/dist/lint/engine.d.ts.map +1 -1
- package/dist/lsp/lexicon-providers.d.ts.map +1 -1
- package/dist/op/activities/activity-contracts.d.ts +12 -11
- package/dist/op/activities/activity-contracts.d.ts.map +1 -1
- package/dist/op/activities/apply.d.ts +79 -9
- package/dist/op/activities/apply.d.ts.map +1 -1
- package/dist/op/activities/decide.d.ts.map +1 -1
- package/dist/op/activities/index.d.ts +1 -1
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/activities/lexicon-upgrade.d.ts +44 -12
- package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -1
- package/dist/op/activities/propose-upgrade.d.ts +2 -0
- package/dist/op/activities/propose-upgrade.d.ts.map +1 -1
- package/dist/op/activity-contract.d.ts +1 -1
- package/dist/op/activity-failure.d.ts.map +1 -1
- package/dist/op/activity-profiles.d.ts.map +1 -1
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/composites/apply-op.d.ts +12 -5
- package/dist/op/composites/apply-op.d.ts.map +1 -1
- package/dist/op/composites/lexicon-upgrade-op.d.ts +22 -6
- package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -1
- package/dist/op/decide-backend.d.ts.map +1 -1
- package/dist/op/decide-read-inputs.d.ts.map +1 -1
- package/dist/op/emulator-lifecycle.d.ts +21 -2
- package/dist/op/emulator-lifecycle.d.ts.map +1 -1
- package/dist/op/gate-approval.d.ts +5 -1
- package/dist/op/gate-approval.d.ts.map +1 -1
- package/dist/op/gate-wait.d.ts.map +1 -1
- package/dist/op/gate.d.ts +19 -3
- package/dist/op/gate.d.ts.map +1 -1
- package/dist/op/index.d.ts +3 -1
- package/dist/op/index.d.ts.map +1 -1
- package/dist/op/local-executor.d.ts +6 -0
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/operator.d.ts.map +1 -1
- package/dist/op/run-context.d.ts +39 -0
- package/dist/op/run-context.d.ts.map +1 -0
- package/dist/op/run-live.d.ts.map +1 -1
- package/dist/op/runtimes/local.d.ts.map +1 -1
- package/dist/op/source-archive.d.ts.map +1 -1
- package/dist/op/steward-beside.d.ts.map +1 -1
- package/dist/op/steward-points.d.ts.map +1 -1
- package/dist/op/steward.d.ts.map +1 -1
- package/dist/op/types.d.ts +8 -3
- package/dist/op/types.d.ts.map +1 -1
- package/dist/op/work-lease-run.d.ts +24 -4
- package/dist/op/work-lease-run.d.ts.map +1 -1
- package/dist/project-root.d.ts.map +1 -1
- package/dist/provenance.d.ts +21 -0
- package/dist/provenance.d.ts.map +1 -1
- package/dist/pseudo-parameter.d.ts.map +1 -1
- package/dist/reconcile.d.ts.map +1 -1
- package/dist/secret-materialization.d.ts.map +1 -1
- package/dist/serializer.d.ts +8 -0
- package/dist/serializer.d.ts.map +1 -1
- package/dist/telemetry-attribution.d.ts +77 -0
- package/dist/telemetry-attribution.d.ts.map +1 -0
- package/dist/terraform/emit-source.d.ts.map +1 -1
- package/dist/terraform/parse.d.ts.map +1 -1
- package/dist/testing.d.ts.map +1 -1
- package/dist/workspace/__fixtures__/contract-repo.d.ts.map +1 -1
- package/dist/workspace/__fixtures__/decide-workspace.d.ts +1 -1
- package/dist/workspace/__fixtures__/decide-workspace.d.ts.map +1 -1
- package/dist/workspace/agent-cli.d.ts +88 -0
- package/dist/workspace/agent-cli.d.ts.map +1 -0
- package/dist/workspace/box-factory.d.ts +73 -0
- package/dist/workspace/box-factory.d.ts.map +1 -0
- package/dist/workspace/changes-cli.d.ts.map +1 -1
- package/dist/workspace/changes.d.ts +8 -1
- package/dist/workspace/changes.d.ts.map +1 -1
- package/dist/workspace/chant-migrations/chud-lexicon-exit.d.ts.map +1 -1
- package/dist/workspace/checks/boxes.d.ts.map +1 -1
- package/dist/workspace/checks/links.d.ts +1 -0
- package/dist/workspace/checks/links.d.ts.map +1 -1
- package/dist/workspace/checks/live.d.ts +40 -0
- package/dist/workspace/checks/live.d.ts.map +1 -0
- package/dist/workspace/checks.d.ts +26 -2
- package/dist/workspace/checks.d.ts.map +1 -1
- package/dist/workspace/compose-graph.d.ts +73 -0
- package/dist/workspace/compose-graph.d.ts.map +1 -1
- package/dist/workspace/conformance/index.d.ts +67 -6
- package/dist/workspace/conformance/index.d.ts.map +1 -1
- package/dist/workspace/conformance/vitest.d.ts +12 -3
- package/dist/workspace/conformance/vitest.d.ts.map +1 -1
- package/dist/workspace/conformance/writer.d.ts +368 -0
- package/dist/workspace/conformance/writer.d.ts.map +1 -0
- package/dist/workspace/decide.d.ts +1 -1
- package/dist/workspace/decide.d.ts.map +1 -1
- package/dist/workspace/declaration.d.ts +119 -0
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.schema.json +368 -4
- package/dist/workspace/export-cli.d.ts +12 -0
- package/dist/workspace/export-cli.d.ts.map +1 -0
- package/dist/workspace/export.d.ts +145 -0
- package/dist/workspace/export.d.ts.map +1 -0
- package/dist/workspace/generated-files.d.ts.map +1 -1
- package/dist/workspace/graph-cache.d.ts.map +1 -1
- package/dist/workspace/graph-cli.d.ts +2 -0
- package/dist/workspace/graph-cli.d.ts.map +1 -1
- package/dist/workspace/identity.d.ts +111 -0
- package/dist/workspace/identity.d.ts.map +1 -0
- package/dist/workspace/import.d.ts +73 -0
- package/dist/workspace/import.d.ts.map +1 -0
- package/dist/workspace/intent-cli.d.ts +7 -4
- package/dist/workspace/intent-cli.d.ts.map +1 -1
- package/dist/workspace/intent-record.d.ts +8 -1
- package/dist/workspace/intent-record.d.ts.map +1 -1
- package/dist/workspace/intent.d.ts +149 -5
- package/dist/workspace/intent.d.ts.map +1 -1
- package/dist/workspace/kinds.d.ts +24 -6
- package/dist/workspace/kinds.d.ts.map +1 -1
- package/dist/workspace/lineage-adopt-cli.d.ts +15 -0
- package/dist/workspace/lineage-adopt-cli.d.ts.map +1 -0
- package/dist/workspace/lineage-adopt.d.ts +106 -0
- package/dist/workspace/lineage-adopt.d.ts.map +1 -0
- package/dist/workspace/lineage-check.d.ts +9 -2
- package/dist/workspace/lineage-check.d.ts.map +1 -1
- package/dist/workspace/lineage-cli.d.ts +6 -1
- package/dist/workspace/lineage-cli.d.ts.map +1 -1
- package/dist/workspace/lineage-hash-index.d.ts +110 -0
- package/dist/workspace/lineage-hash-index.d.ts.map +1 -0
- package/dist/workspace/lineage-init.d.ts +10 -0
- package/dist/workspace/lineage-init.d.ts.map +1 -1
- package/dist/workspace/lineage-lock.d.ts +149 -2
- package/dist/workspace/lineage-lock.d.ts.map +1 -1
- package/dist/workspace/lineage-migrations.d.ts +15 -3
- package/dist/workspace/lineage-migrations.d.ts.map +1 -1
- package/dist/workspace/lineage-provenance.d.ts +18 -0
- package/dist/workspace/lineage-provenance.d.ts.map +1 -0
- package/dist/workspace/lineage-upgrade-cli.d.ts +2 -0
- package/dist/workspace/lineage-upgrade-cli.d.ts.map +1 -1
- package/dist/workspace/lineage-upgrade.d.ts +30 -1
- package/dist/workspace/lineage-upgrade.d.ts.map +1 -1
- package/dist/workspace/lineage-versions.d.ts +116 -0
- package/dist/workspace/lineage-versions.d.ts.map +1 -0
- package/dist/workspace/links.d.ts +31 -5
- package/dist/workspace/links.d.ts.map +1 -1
- package/dist/workspace/ls-generated.d.ts +37 -0
- package/dist/workspace/ls-generated.d.ts.map +1 -0
- package/dist/workspace/ls.d.ts +4 -0
- package/dist/workspace/ls.d.ts.map +1 -1
- package/dist/workspace/member-commands.d.ts.map +1 -1
- package/dist/workspace/nested-graph.d.ts +56 -0
- package/dist/workspace/nested-graph.d.ts.map +1 -0
- package/dist/workspace/nesting.d.ts +21 -0
- package/dist/workspace/nesting.d.ts.map +1 -0
- package/dist/workspace/pin-cli.d.ts +10 -0
- package/dist/workspace/pin-cli.d.ts.map +1 -0
- package/dist/workspace/pin-integrity.d.ts +51 -0
- package/dist/workspace/pin-integrity.d.ts.map +1 -0
- package/dist/workspace/points.d.ts.map +1 -1
- package/dist/workspace/principal-classes.d.ts +114 -0
- package/dist/workspace/principal-classes.d.ts.map +1 -0
- package/dist/workspace/reason-codes.d.ts +47 -3
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/record-assets.d.ts.map +1 -1
- package/dist/workspace/record-sessions.d.ts +7 -11
- package/dist/workspace/record-sessions.d.ts.map +1 -1
- package/dist/workspace/records-checkout.d.ts +54 -0
- package/dist/workspace/records-checkout.d.ts.map +1 -0
- package/dist/workspace/records-cli.d.ts +57 -2
- package/dist/workspace/records-cli.d.ts.map +1 -1
- package/dist/workspace/records-close.d.ts +5 -2
- package/dist/workspace/records-close.d.ts.map +1 -1
- package/dist/workspace/records-since.d.ts.map +1 -1
- package/dist/workspace/records-write.d.ts +23 -4
- package/dist/workspace/records-write.d.ts.map +1 -1
- package/dist/workspace/records.d.ts +58 -5
- package/dist/workspace/records.d.ts.map +1 -1
- package/dist/workspace/returns.d.ts +129 -0
- package/dist/workspace/returns.d.ts.map +1 -0
- package/dist/workspace/runs-cli.d.ts +164 -0
- package/dist/workspace/runs-cli.d.ts.map +1 -0
- package/dist/workspace/runs.d.ts +423 -0
- package/dist/workspace/runs.d.ts.map +1 -0
- package/dist/workspace/source-block.d.ts +1 -1
- package/dist/workspace/source-block.d.ts.map +1 -1
- package/dist/workspace/status-gates.d.ts +15 -3
- package/dist/workspace/status-gates.d.ts.map +1 -1
- package/dist/workspace/status.d.ts +10 -0
- package/dist/workspace/status.d.ts.map +1 -1
- package/dist/workspace/symbols.d.ts +52 -0
- package/dist/workspace/symbols.d.ts.map +1 -0
- package/dist/workspace/template-manifest.d.ts +11 -3
- package/dist/workspace/template-manifest.d.ts.map +1 -1
- package/dist/workspace/trailer-joins.d.ts +46 -0
- package/dist/workspace/trailer-joins.d.ts.map +1 -0
- package/dist/workspace/trailers.d.ts +89 -0
- package/dist/workspace/trailers.d.ts.map +1 -0
- package/dist/workspace/trust/attestor.d.ts +8 -0
- package/dist/workspace/trust/attestor.d.ts.map +1 -1
- package/dist/workspace/trust/dsse.d.ts +58 -0
- package/dist/workspace/trust/dsse.d.ts.map +1 -0
- package/dist/workspace/trust/evidence-cli.d.ts +66 -0
- package/dist/workspace/trust/evidence-cli.d.ts.map +1 -0
- package/dist/workspace/trust/evidence.d.ts +93 -0
- package/dist/workspace/trust/evidence.d.ts.map +1 -0
- package/dist/workspace/trust/policy.d.ts +54 -1
- package/dist/workspace/trust/policy.d.ts.map +1 -1
- package/dist/workspace/trust/provenance.d.ts +21 -1
- package/dist/workspace/trust/provenance.d.ts.map +1 -1
- package/dist/workspace/trust/rotation.d.ts +132 -0
- package/dist/workspace/trust/rotation.d.ts.map +1 -0
- package/dist/workspace/trust/seal.d.ts +33 -0
- package/dist/workspace/trust/seal.d.ts.map +1 -1
- package/dist/workspace/trust/signers-cli.d.ts +49 -0
- package/dist/workspace/trust/signers-cli.d.ts.map +1 -0
- package/dist/workspace/trust/ssh-commit.d.ts +12 -0
- package/dist/workspace/trust/ssh-commit.d.ts.map +1 -1
- package/dist/workspace/trust/test-repo.d.ts +13 -0
- package/dist/workspace/trust/test-repo.d.ts.map +1 -1
- package/dist/workspace/trust/verify.d.ts +15 -0
- package/dist/workspace/trust/verify.d.ts.map +1 -1
- package/dist/workspace/work-cli.d.ts +39 -3
- package/dist/workspace/work-cli.d.ts.map +1 -1
- package/dist/workspace/work-evidence.d.ts +1 -1
- package/dist/workspace/work-evidence.d.ts.map +1 -1
- package/dist/workspace/work.d.ts +26 -1
- package/dist/workspace/work.d.ts.map +1 -1
- package/dist/workspace/workspace-principals.schema.json +60 -0
- package/dist/workspace/write-scope.d.ts +259 -0
- package/dist/workspace/write-scope.d.ts.map +1 -0
- package/dist/yaml.d.ts +21 -39
- package/dist/yaml.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/audit/prior-art.ts +15 -0
- package/src/build.ts +8 -0
- package/src/cli/build-options.ts +4 -1
- package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +1 -1
- package/src/cli/commands/build.ts +2 -0
- package/src/cli/commands/carve-emit-state.test.ts +4 -0
- package/src/cli/commands/carve-emit.ts +5 -19
- package/src/cli/commands/check-lexicon.test.ts +62 -1
- package/src/cli/commands/check-lexicon.ts +36 -6
- package/src/cli/commands/import-live.test.ts +87 -1
- package/src/cli/commands/import-parser-options.test.ts +133 -0
- package/src/cli/commands/import.ts +69 -25
- package/src/cli/commands/init-lexicon/templates/project.ts +1 -1
- package/src/cli/commands/init.test.ts +8 -1
- package/src/cli/commands/init.ts +23 -8
- package/src/cli/commands/lint.test.ts +37 -0
- package/src/cli/commands/onboard.test.ts +53 -3
- package/src/cli/commands/onboard.ts +52 -4
- package/src/cli/commands/pinned-upgrade.ts +73 -33
- package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +2 -2
- package/src/cli/handlers/components.ts +2 -2
- package/src/cli/handlers/dev.ts +8 -6
- package/src/cli/handlers/fan-out.test.ts +6 -6
- package/src/cli/handlers/fan-out.ts +2 -1
- package/src/cli/handlers/graph.test.ts +42 -0
- package/src/cli/handlers/graph.ts +22 -0
- package/src/cli/handlers/lifecycle.test.ts +67 -0
- package/src/cli/handlers/lifecycle.ts +6 -5
- package/src/cli/handlers/misc.ts +2 -0
- package/src/cli/handlers/operator.ts +88 -4
- package/src/cli/handlers/run.test.ts +111 -0
- package/src/cli/handlers/run.ts +85 -24
- package/src/cli/handlers/scenario.ts +2 -2
- package/src/cli/main.test.ts +33 -0
- package/src/cli/main.ts +168 -17
- package/src/cli/mcp/workspace-tools.test.ts +5 -2
- package/src/cli/mcp/workspace-tools.ts +62 -4
- package/src/cli/registry.ts +33 -2
- package/src/cli/serve-mcp-workspace.test.ts +1 -1
- package/src/codegen/pinned-upgrade-multi.test.ts +157 -0
- package/src/codegen/pinned-upgrade-tags.test.ts +112 -0
- package/src/codegen/pinned-upgrade.test.ts +104 -0
- package/src/codegen/pinned-upgrade.ts +250 -56
- package/src/codegen/release-wiring.test.ts +5 -1
- package/src/codegen/testdata/postgres-tags.json +242 -0
- package/src/components/fan-out-output.test.ts +1 -1
- package/src/components/fan-out.test.ts +1 -1
- package/src/components/promote.test.ts +1 -1
- package/src/config.test.ts +21 -0
- package/src/config.ts +27 -0
- package/src/content-digest.test.ts +2 -2
- package/src/declarable.test.ts +21 -0
- package/src/declarable.ts +19 -0
- package/src/discovery/fold-composite.test.ts +41 -5
- package/src/discovery/fold-import.test.ts +129 -0
- package/src/discovery/fold-import.ts +643 -131
- package/src/discovery/fold-package-composite.test.ts +264 -0
- package/src/discovery/fold-specifiers.test.ts +191 -0
- package/src/discovery/param-deps.test.ts +66 -1
- package/src/discovery/param-deps.ts +45 -0
- package/src/discovery/specifier-resolve.ts +344 -0
- package/src/fold/fold.test.ts +39 -1
- package/src/fold/fold.ts +83 -9
- package/src/fold-provenance.test.ts +140 -0
- package/src/graph-ir.test.ts +83 -0
- package/src/graph-ir.ts +29 -0
- package/src/import/embedded.test.ts +20 -0
- package/src/import/embedded.ts +13 -0
- package/src/import/parser-options.ts +46 -0
- package/src/import/parser.ts +20 -0
- package/src/lexicon.ts +79 -3
- package/src/lifecycle/gate-ledger.test.ts +14 -0
- package/src/lifecycle/gate-ledger.ts +18 -1
- package/src/lifecycle/observe.test.ts +18 -0
- package/src/lifecycle/observe.ts +6 -4
- package/src/lifecycle/plan-digest.test.ts +54 -3
- package/src/lifecycle/plan-digest.ts +38 -8
- package/src/lifecycle/snapshot.ts +2 -2
- package/src/lifecycle/work-lease.test.ts +1 -1
- package/src/lifecycle/work-lease.ts +93 -2
- package/src/lint/engine.test.ts +55 -0
- package/src/lint/engine.ts +30 -4
- package/src/lint/output-docs.test.ts +59 -56
- package/src/op/activities/activity-contracts.ts +1 -0
- package/src/op/activities/apply.test.ts +189 -5
- package/src/op/activities/apply.ts +230 -8
- package/src/op/activities/index.ts +3 -0
- package/src/op/activities/lexicon-upgrade.test.ts +160 -6
- package/src/op/activities/lexicon-upgrade.ts +154 -51
- package/src/op/activities/propose-upgrade.ts +8 -5
- package/src/op/composites/apply-op.ts +12 -5
- package/src/op/composites/composites.test.ts +30 -3
- package/src/op/composites/lexicon-upgrade-op.test.ts +7 -2
- package/src/op/composites/lexicon-upgrade-op.ts +29 -8
- package/src/op/emulator-lifecycle.test.ts +23 -0
- package/src/op/emulator-lifecycle.ts +52 -14
- package/src/op/gate-approval.test.ts +91 -0
- package/src/op/gate-approval.ts +5 -1
- package/src/op/gate.ts +34 -8
- package/src/op/index.ts +3 -1
- package/src/op/local-executor.test.ts +15 -0
- package/src/op/local-executor.ts +40 -12
- package/src/op/local-output.ts +1 -1
- package/src/op/operator.ts +4 -0
- package/src/op/run-context.test.ts +141 -0
- package/src/op/run-context.ts +51 -0
- package/src/op/runtimes/local.test.ts +14 -0
- package/src/op/runtimes/local.ts +2 -0
- package/src/op/steward-beside.ts +2 -0
- package/src/op/types.ts +8 -3
- package/src/op/work-lease-run.test.ts +47 -0
- package/src/op/work-lease-run.ts +73 -11
- package/src/provenance.ts +35 -0
- package/src/serializer.ts +9 -0
- package/src/telemetry-attribution.test.ts +91 -0
- package/src/telemetry-attribution.ts +145 -0
- package/src/workspace/__fixtures__/studio-template-84c8b21.json +1 -1
- package/src/workspace/agent-cli.ts +138 -0
- package/src/workspace/agent.schema.json +378 -0
- package/src/workspace/behold-kinds.test.ts +1 -1
- package/src/workspace/box-factory.test.ts +320 -0
- package/src/workspace/box-factory.ts +103 -0
- package/src/workspace/changes-cli.ts +5 -0
- package/src/workspace/changes.schema.json +171 -1
- package/src/workspace/changes.ts +61 -4
- package/src/workspace/check-live.test.ts +192 -0
- package/src/workspace/check.schema.json +64 -0
- package/src/workspace/checks/boxes.test.ts +2 -0
- package/src/workspace/checks/links.ts +23 -2
- package/src/workspace/checks/live.ts +113 -0
- package/src/workspace/checks.test.ts +2 -2
- package/src/workspace/checks.ts +49 -8
- package/src/workspace/compose-graph.test.ts +47 -0
- package/src/workspace/compose-graph.ts +127 -3
- package/src/workspace/conformance/__fixture__/decisions/decision.kind.mjs +7 -1
- package/src/workspace/conformance/__fixture__/decisions/decision.schema.json +5 -0
- package/src/workspace/conformance/__writer_fixture__/answers/answer.kind.mjs +27 -0
- package/src/workspace/conformance/__writer_fixture__/answers/answer.schema.json +95 -0
- package/src/workspace/conformance/__writer_fixture__/decisions/points.json +132 -0
- package/src/workspace/conformance/__writer_fixture__/sessions/session.kind.mjs +48 -0
- package/src/workspace/conformance/__writer_fixture__/sessions/session.schema.json +108 -0
- package/src/workspace/conformance/__writer_fixture__/work/W-001-the-writer-suite-works-this-item.md +25 -0
- package/src/workspace/conformance/__writer_fixture__/work/work.kind.mjs +60 -0
- package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +578 -0
- package/src/workspace/conformance/conformance.e2e.test.ts +35 -3
- package/src/workspace/conformance/index.mjs +30 -3
- package/src/workspace/conformance/index.ts +103 -15
- package/src/workspace/conformance/vitest.ts +44 -2
- package/src/workspace/conformance/writer-conformance.e2e.test.ts +131 -0
- package/src/workspace/conformance/writer.test.ts +156 -0
- package/src/workspace/conformance/writer.ts +880 -0
- package/src/workspace/decide.ts +7 -1
- package/src/workspace/declaration.schema.json +368 -4
- package/src/workspace/declaration.ts +270 -1
- package/src/workspace/declared-kinds.test.ts +33 -0
- package/src/workspace/evidence.schema.json +279 -0
- package/src/workspace/export-cli.ts +180 -0
- package/src/workspace/export-import.test.ts +282 -0
- package/src/workspace/export.ts +486 -0
- package/src/workspace/graph-cli.ts +51 -2
- package/src/workspace/graph-contract.test.ts +89 -4
- package/src/workspace/graph.schema.json +453 -1
- package/src/workspace/identity.test.ts +196 -0
- package/src/workspace/identity.ts +186 -0
- package/src/workspace/import.ts +325 -0
- package/src/workspace/intent-cli.ts +64 -10
- package/src/workspace/intent-record.schema.json +208 -0
- package/src/workspace/intent-record.ts +35 -1
- package/src/workspace/intent-why.test.ts +274 -0
- package/src/workspace/intent.schema.json +718 -7
- package/src/workspace/intent.test.ts +11 -2
- package/src/workspace/intent.ts +495 -32
- package/src/workspace/kinds.test.ts +5 -5
- package/src/workspace/kinds.ts +62 -33
- package/src/workspace/lineage-adopt-cli.ts +103 -0
- package/src/workspace/lineage-adopt.test.ts +552 -0
- package/src/workspace/lineage-adopt.ts +452 -0
- package/src/workspace/lineage-check.ts +26 -5
- package/src/workspace/lineage-cli.ts +12 -2
- package/src/workspace/lineage-hash-index.ts +305 -0
- package/src/workspace/lineage-init.test.ts +9 -0
- package/src/workspace/lineage-init.ts +29 -9
- package/src/workspace/lineage-lock.ts +54 -0
- package/src/workspace/lineage-migrations.test.ts +27 -0
- package/src/workspace/lineage-migrations.ts +44 -14
- package/src/workspace/lineage-provenance.ts +40 -0
- package/src/workspace/lineage-upgrade-cli.ts +9 -5
- package/src/workspace/lineage-upgrade.test.ts +92 -1
- package/src/workspace/lineage-upgrade.ts +111 -16
- package/src/workspace/lineage-versions.ts +348 -0
- package/src/workspace/links.test.ts +121 -2
- package/src/workspace/links.ts +97 -6
- package/src/workspace/ls-contract.test.ts +84 -1
- package/src/workspace/ls-generated.ts +111 -0
- package/src/workspace/ls.schema.json +19 -0
- package/src/workspace/ls.ts +8 -1
- package/src/workspace/member-commands.ts +3 -1
- package/src/workspace/nested-graph.test.ts +176 -0
- package/src/workspace/nested-graph.ts +169 -0
- package/src/workspace/nesting.ts +37 -0
- package/src/workspace/pin-cli.test.ts +71 -0
- package/src/workspace/pin-cli.ts +57 -0
- package/src/workspace/pin-integrity.test.ts +121 -0
- package/src/workspace/pin-integrity.ts +104 -0
- package/src/workspace/points-write.schema.json +2 -0
- package/src/workspace/principal-classes.test.ts +175 -0
- package/src/workspace/principal-classes.ts +307 -0
- package/src/workspace/read-contract.test.ts +24 -0
- package/src/workspace/reason-codes.test.ts +20 -2
- package/src/workspace/reason-codes.ts +53 -3
- package/src/workspace/record-sessions.ts +12 -14
- package/src/workspace/records-amend.schema.json +6 -0
- package/src/workspace/records-checkout.ts +106 -0
- package/src/workspace/records-cli.ts +195 -22
- package/src/workspace/records-close.schema.json +7 -2
- package/src/workspace/records-close.ts +10 -2
- package/src/workspace/records-formats.test.ts +13 -5
- package/src/workspace/records-new.schema.json +6 -0
- package/src/workspace/records-review.schema.json +6 -0
- package/src/workspace/records-sessions.test.ts +23 -6
- package/src/workspace/records-uncommitted.test.ts +171 -0
- package/src/workspace/records-write.test.ts +65 -8
- package/src/workspace/records-write.ts +92 -6
- package/src/workspace/records.schema.json +127 -4
- package/src/workspace/records.ts +123 -5
- package/src/workspace/returns.ts +328 -0
- package/src/workspace/runs-cli.ts +381 -0
- package/src/workspace/runs-write.schema.json +583 -0
- package/src/workspace/runs.schema.json +810 -0
- package/src/workspace/runs.test.ts +242 -0
- package/src/workspace/runs.ts +709 -0
- package/src/workspace/signers.schema.json +206 -0
- package/src/workspace/status-contract.test.ts +5 -0
- package/src/workspace/status-gates.ts +24 -9
- package/src/workspace/status.schema.json +127 -2
- package/src/workspace/status.ts +21 -1
- package/src/workspace/symbols.ts +180 -0
- package/src/workspace/template-manifest.ts +22 -4
- package/src/workspace/trailer-joins.test.ts +171 -0
- package/src/workspace/trailer-joins.ts +82 -0
- package/src/workspace/trailers.ts +148 -0
- package/src/workspace/trust/attestor.ts +15 -0
- package/src/workspace/trust/dsse.ts +134 -0
- package/src/workspace/trust/evidence-cli.ts +195 -0
- package/src/workspace/trust/evidence.test.ts +241 -0
- package/src/workspace/trust/evidence.ts +207 -0
- package/src/workspace/trust/policy.ts +110 -3
- package/src/workspace/trust/provenance.ts +41 -4
- package/src/workspace/trust/record-seal.test.ts +1 -1
- package/src/workspace/trust/rotation.test.ts +258 -0
- package/src/workspace/trust/rotation.ts +336 -0
- package/src/workspace/trust/seal.ts +63 -1
- package/src/workspace/trust/signers-cli.ts +178 -0
- package/src/workspace/trust/ssh-commit.ts +53 -4
- package/src/workspace/trust/test-repo.ts +18 -0
- package/src/workspace/trust/trust.test.ts +8 -2
- package/src/workspace/trust/verify-cli.ts +1 -0
- package/src/workspace/trust/verify.ts +22 -0
- package/src/workspace/work-cli.e2e.test.ts +28 -1
- package/src/workspace/work-cli.ts +133 -8
- package/src/workspace/work-evidence.schema.json +6 -0
- package/src/workspace/work-history.schema.json +73 -1
- package/src/workspace/work-history.test.ts +48 -5
- package/src/workspace/work-kind-fields.test.ts +154 -0
- package/src/workspace/work-lease.schema.json +14 -1
- package/src/workspace/work.ts +82 -0
- package/src/workspace/workspace-principals.schema.json +60 -0
- package/src/workspace/write-scope.test.ts +466 -0
- package/src/workspace/write-scope.ts +573 -0
- package/src/yaml.test.ts +111 -1
- package/src/yaml.ts +141 -549
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Principal classes (#2524 D5; #3080, ws-079).
|
|
3
|
+
*
|
|
4
|
+
* A principal class names a set of principals so the declaration can scope
|
|
5
|
+
* what they write. Four are core: `agent`, `runner` and `service`, each the
|
|
6
|
+
* holders of the role of that name in the trust policy at base, and `human`,
|
|
7
|
+
* everyone else. A plugin adds domain classes as data, the way it adds member
|
|
8
|
+
* kinds: a JSON file at its `./workspace-principals` subpath, read through
|
|
9
|
+
* the package's `package.json` and never imported. Each class it supplies
|
|
10
|
+
* names the role whose grant puts a principal in it.
|
|
11
|
+
*
|
|
12
|
+
* A principal's classes are read only from role grants at base, through
|
|
13
|
+
* {@link classesOf}. Core classes are tried first, then the domain classes
|
|
14
|
+
* in pin order and file order; the first that holds is the class write scope
|
|
15
|
+
* judges the principal as, and `human` is the rest. A gate or a record that
|
|
16
|
+
* asks whether a principal is in a class (#3163) asks {@link classesOf},
|
|
17
|
+
* which lists every class the principal's grants put it in.
|
|
18
|
+
*
|
|
19
|
+
* A path-pinned plugin's classes are read from the base revision when the
|
|
20
|
+
* caller has it (write scope does), so a change can't remap a class by
|
|
21
|
+
* editing its own copy of the plugin. A package pin is read from the
|
|
22
|
+
* installed package, which must be at the version the base pins.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { readFileSync } from "node:fs";
|
|
26
|
+
import { createRequire } from "node:module";
|
|
27
|
+
import { join, posix } from "node:path";
|
|
28
|
+
import { kindsExportTarget, pinnedPackageDir, type KindLoadProblem, type PinLike } from "./kinds";
|
|
29
|
+
import { normalisePrincipal } from "./records";
|
|
30
|
+
import schema from "./workspace-principals.schema.json";
|
|
31
|
+
import type { TrustPolicy } from "./trust/policy";
|
|
32
|
+
import { joinPath, type WorkspaceTree } from "./tree";
|
|
33
|
+
|
|
34
|
+
export const PRINCIPALS_SCHEMA_ID = schema.$id;
|
|
35
|
+
|
|
36
|
+
/** The subpath a package publishes its principal classes at. */
|
|
37
|
+
export const PRINCIPALS_SUBPATH = "./workspace-principals";
|
|
38
|
+
|
|
39
|
+
/** The core classes, in the order a principal's roles are tried; `human` holds no role and is the rest. */
|
|
40
|
+
export const CORE_PRINCIPAL_CLASSES = ["human", "agent", "runner", "service"] as const;
|
|
41
|
+
export type CorePrincipalClass = (typeof CORE_PRINCIPAL_CLASSES)[number];
|
|
42
|
+
|
|
43
|
+
/** A class name: a core class, or a domain class a pinned package supplies. */
|
|
44
|
+
export type PrincipalClassName = string;
|
|
45
|
+
|
|
46
|
+
/** The grammar of a class name, as `workspace-principals.schema.json` and the declaration's writeScope keys say it. */
|
|
47
|
+
export const CLASS_NAME = /^(?!x-)[a-z][a-z0-9-]{0,39}$/;
|
|
48
|
+
|
|
49
|
+
export interface PrincipalClass {
|
|
50
|
+
name: string;
|
|
51
|
+
/** One line saying who is in the class. */
|
|
52
|
+
description: string;
|
|
53
|
+
/** The role whose grant at base puts a principal in the class, or null for `human`, the rest. */
|
|
54
|
+
role: string | null;
|
|
55
|
+
/** `core`, or the pin (package name or path) that supplies the class. */
|
|
56
|
+
source: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const CORE_CLASSES: readonly PrincipalClass[] = [
|
|
60
|
+
{ name: "human", description: "a principal holding none of the roles of another class", role: null, source: "core" },
|
|
61
|
+
{ name: "agent", description: "a principal holding the agent role, or a write naming an agent session", role: "agent", source: "core" },
|
|
62
|
+
{ name: "runner", description: "a principal holding the runner role, such as a CI job's signing identity", role: "runner", source: "core" },
|
|
63
|
+
{ name: "service", description: "a principal holding the service role", role: "service", source: "core" },
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
const CORE_ROLES = new Set(CORE_CLASSES.map((c) => c.role).filter((r): r is string => r !== null));
|
|
67
|
+
|
|
68
|
+
export interface ClassRegistry {
|
|
69
|
+
get(name: string): PrincipalClass | undefined;
|
|
70
|
+
/** Every class name, core first, for "unknown class" messages. */
|
|
71
|
+
names(): string[];
|
|
72
|
+
/** Every class, core first, then the domain classes in pin order and file order. */
|
|
73
|
+
all(): readonly PrincipalClass[];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function createClassRegistry(extra: readonly PrincipalClass[] = []): ClassRegistry {
|
|
77
|
+
const all = [...CORE_CLASSES, ...extra];
|
|
78
|
+
const byName = new Map(all.map((c) => [c.name, c]));
|
|
79
|
+
return {
|
|
80
|
+
get: (name) => byName.get(name),
|
|
81
|
+
names: () => all.map((c) => c.name),
|
|
82
|
+
all: () => all,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** The four core classes and nothing else: what a workspace whose pins supply no class has. */
|
|
87
|
+
export function coreClassRegistry(): ClassRegistry {
|
|
88
|
+
return createClassRegistry();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* The role grants a class is read from. Every read of roles for a class goes
|
|
93
|
+
* through here, so where the grants live (`.chant/trust.json` today,
|
|
94
|
+
* possibly the declaration, #2547) is decided in one place: the policy.
|
|
95
|
+
*/
|
|
96
|
+
export function roleGrants(policy: TrustPolicy): Record<string, string[]> {
|
|
97
|
+
return policy.roles;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Every class `principal`'s role grants at base put it in, in registry order
|
|
102
|
+
* (core first). Empty for a principal in no class but `human`, and for null.
|
|
103
|
+
* Names compare as {@link normalisePrincipal} folds them.
|
|
104
|
+
*/
|
|
105
|
+
export function classesOf(classes: ClassRegistry, policy: TrustPolicy, principal: string | null): string[] {
|
|
106
|
+
if (principal === null) return [];
|
|
107
|
+
const name = normalisePrincipal(principal);
|
|
108
|
+
const grants = roleGrants(policy);
|
|
109
|
+
return classes
|
|
110
|
+
.all()
|
|
111
|
+
.filter((c) => c.role !== null && (grants[c.role] ?? []).some((p) => normalisePrincipal(p) === name))
|
|
112
|
+
.map((c) => c.name);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** The class write scope judges `principal` as: the first class its grants put it in, or `human`. */
|
|
116
|
+
export function principalClass(policy: TrustPolicy, principal: string | null, classes: ClassRegistry = coreClassRegistry()): string {
|
|
117
|
+
return classesOf(classes, policy, principal)[0] ?? "human";
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// ── Reading a plugin's classes ───────────────────────────────────────────────
|
|
121
|
+
|
|
122
|
+
interface AjvError {
|
|
123
|
+
instancePath: string;
|
|
124
|
+
message?: string;
|
|
125
|
+
}
|
|
126
|
+
type Validate = ((data: unknown) => boolean) & { errors?: AjvError[] | null };
|
|
127
|
+
|
|
128
|
+
let compiled: Validate | undefined;
|
|
129
|
+
function validator(): Validate {
|
|
130
|
+
if (compiled) return compiled;
|
|
131
|
+
const require = createRequire(import.meta.url);
|
|
132
|
+
// ajv is CommonJS; its class is the default export, or that export's own default.
|
|
133
|
+
const mod = require("ajv/dist/2020") as { default?: unknown };
|
|
134
|
+
const Ajv = (mod.default ?? mod) as new (opts: object) => { compile(s: object): Validate };
|
|
135
|
+
compiled = new Ajv({ allErrors: true, strict: true }).compile(schema);
|
|
136
|
+
return compiled;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface ClassData {
|
|
140
|
+
classes: PrincipalClass[];
|
|
141
|
+
/** Why some of the data can't be used, one line each. Empty when all of it can. */
|
|
142
|
+
problems: string[];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Check the text of a principals file against
|
|
147
|
+
* `workspace-principals.schema.json` and the rules the schema can't say: no
|
|
148
|
+
* core name or core role, and no name or role twice. `source` names the pin
|
|
149
|
+
* in the classes and in the messages.
|
|
150
|
+
*/
|
|
151
|
+
export function parseClassData(text: string, source: string): ClassData {
|
|
152
|
+
let raw: unknown;
|
|
153
|
+
try {
|
|
154
|
+
raw = JSON.parse(text);
|
|
155
|
+
} catch (err) {
|
|
156
|
+
return { classes: [], problems: [`${source}: the principals file is not JSON (${(err as Error).message})`] };
|
|
157
|
+
}
|
|
158
|
+
const validate = validator();
|
|
159
|
+
if (!validate(raw)) {
|
|
160
|
+
const problems = (validate.errors ?? []).map((e) => `${source}: ${e.instancePath || "the principals file"} ${e.message ?? "is invalid"}`);
|
|
161
|
+
return { classes: [], problems: [...new Set(problems)] };
|
|
162
|
+
}
|
|
163
|
+
const problems: string[] = [];
|
|
164
|
+
const classes: PrincipalClass[] = [];
|
|
165
|
+
const names = new Set<string>();
|
|
166
|
+
const roles = new Set<string>();
|
|
167
|
+
for (const c of (raw as { classes: { name: string; description: string; role: string }[] }).classes) {
|
|
168
|
+
if ((CORE_PRINCIPAL_CLASSES as readonly string[]).includes(c.name)) {
|
|
169
|
+
problems.push(`${source}: class ${c.name} is a core class and can't be supplied by a package`);
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
if (CORE_ROLES.has(c.role)) {
|
|
173
|
+
problems.push(`${source}: class ${c.name} names the role ${c.role}, which puts a principal in the core ${c.role} class`);
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (names.has(c.name)) {
|
|
177
|
+
problems.push(`${source}: class ${c.name} is listed twice`);
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
if (roles.has(c.role)) {
|
|
181
|
+
problems.push(`${source}: class ${c.name} names the role ${c.role}, which another class in the file names; a role puts a principal in one class`);
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
names.add(c.name);
|
|
185
|
+
roles.add(c.role);
|
|
186
|
+
classes.push({ name: c.name, description: c.description, role: c.role, source });
|
|
187
|
+
}
|
|
188
|
+
return { classes, problems };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** A package's files, by a `/`-separated path inside it, or undefined when one is not there. */
|
|
192
|
+
export type PackageFiles = (path: string) => string | undefined;
|
|
193
|
+
|
|
194
|
+
/** A package directory on disk. */
|
|
195
|
+
export function diskFiles(dir: string): PackageFiles {
|
|
196
|
+
return (path) => {
|
|
197
|
+
try {
|
|
198
|
+
return readFileSync(join(dir, ...path.split("/")), "utf-8");
|
|
199
|
+
} catch {
|
|
200
|
+
return undefined;
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** A package directory at `dir` in `tree`, such as the workspace at the base revision. */
|
|
206
|
+
export function treeFiles(tree: WorkspaceTree, dir: string): PackageFiles {
|
|
207
|
+
return (path) => {
|
|
208
|
+
const full = joinPath(dir, path);
|
|
209
|
+
if (tree.stat(full) !== "file") return undefined;
|
|
210
|
+
try {
|
|
211
|
+
return tree.read(full);
|
|
212
|
+
} catch {
|
|
213
|
+
return undefined;
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** Read the classes a package publishes at `./workspace-principals`. Reads files only; imports nothing. A package that publishes none supplies none. */
|
|
219
|
+
export function readPackageClasses(files: PackageFiles, source: string): ClassData {
|
|
220
|
+
const manifest = files("package.json");
|
|
221
|
+
if (manifest === undefined) return { classes: [], problems: [`${source}: no readable package.json`] };
|
|
222
|
+
let pkg: Record<string, unknown>;
|
|
223
|
+
try {
|
|
224
|
+
pkg = JSON.parse(manifest) as Record<string, unknown>;
|
|
225
|
+
} catch {
|
|
226
|
+
return { classes: [], problems: [`${source}: package.json is not JSON`] };
|
|
227
|
+
}
|
|
228
|
+
const target = kindsExportTarget(pkg, PRINCIPALS_SUBPATH);
|
|
229
|
+
if (target === undefined) return { classes: [], problems: [] };
|
|
230
|
+
if (typeof target !== "string") return { classes: [], problems: [`${source}: ${target.problem}`] };
|
|
231
|
+
const inside = posix.normalize(target.slice(2));
|
|
232
|
+
if (inside.startsWith("../") || inside === "..") return { classes: [], problems: [`${source}: exports["${PRINCIPALS_SUBPATH}"] points outside the package`] };
|
|
233
|
+
const text = files(inside);
|
|
234
|
+
if (text === undefined) return { classes: [], problems: [`${source}: exports["${PRINCIPALS_SUBPATH}"] names ${target}, which does not exist`] };
|
|
235
|
+
return parseClassData(text, source);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export interface LoadedClasses {
|
|
239
|
+
registry: ClassRegistry;
|
|
240
|
+
problems: KindLoadProblem[];
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* The classes a workspace knows: the core four plus every class its pins
|
|
245
|
+
* supply. A package pin is read from the installed package, looked up from
|
|
246
|
+
* `workspaceRoot`, and must be at the pinned version. A path pin is read
|
|
247
|
+
* through `tree` when given (the base revision, for write scope), else from
|
|
248
|
+
* `workspaceRoot` on disk, checked against its integrity digest. A class
|
|
249
|
+
* name, or a role, two pins both supply is a problem, and every class
|
|
250
|
+
* involved is left out, so a writeScope entry for it reads as unknown and
|
|
251
|
+
* fails closed. Never throws.
|
|
252
|
+
*/
|
|
253
|
+
export function loadClassRegistry(pins: readonly PinLike[], workspaceRoot: string, opts: { tree?: WorkspaceTree } = {}): LoadedClasses {
|
|
254
|
+
const problems: KindLoadProblem[] = [];
|
|
255
|
+
const extra: PrincipalClass[] = [];
|
|
256
|
+
const byName = new Map<string, string>();
|
|
257
|
+
const byRole = new Map<string, string>();
|
|
258
|
+
const clashing = new Set<string>();
|
|
259
|
+
pins.forEach((pin, i) => {
|
|
260
|
+
let files: PackageFiles;
|
|
261
|
+
let source: string;
|
|
262
|
+
if (pin.path && opts.tree) {
|
|
263
|
+
files = treeFiles(opts.tree, pin.path);
|
|
264
|
+
source = pin.path;
|
|
265
|
+
} else {
|
|
266
|
+
const found = pinnedPackageDir(pin, workspaceRoot);
|
|
267
|
+
if (found === null) return;
|
|
268
|
+
if ("problem" in found) {
|
|
269
|
+
problems.push({ pin: i, message: found.problem });
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
files = diskFiles(found.dir);
|
|
273
|
+
source = found.source;
|
|
274
|
+
}
|
|
275
|
+
const read = readPackageClasses(files, source);
|
|
276
|
+
for (const p of read.problems) problems.push({ pin: i, message: p });
|
|
277
|
+
for (const c of read.classes) {
|
|
278
|
+
const named = byName.get(c.name);
|
|
279
|
+
const roled = byRole.get(c.role!);
|
|
280
|
+
if (named !== undefined || roled !== undefined) {
|
|
281
|
+
clashing.add(c.name);
|
|
282
|
+
if (named !== undefined) {
|
|
283
|
+
problems.push({ pin: i, message: `class ${c.name} is supplied by both ${named} and ${source}; a class name has one source` });
|
|
284
|
+
} else {
|
|
285
|
+
const other = extra.find((e) => e.role === c.role)!;
|
|
286
|
+
clashing.add(other.name);
|
|
287
|
+
problems.push({ pin: i, message: `class ${c.name} (${source}) names the role ${c.role}, which class ${other.name} (${roled}) names; a role puts a principal in one class` });
|
|
288
|
+
}
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
byName.set(c.name, source);
|
|
292
|
+
byRole.set(c.role!, source);
|
|
293
|
+
extra.push(c);
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
// A name or role two pins both supply is left out altogether: neither reading is safe.
|
|
297
|
+
return { registry: createClassRegistry(extra.filter((c) => !clashing.has(c.name))), problems };
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* The writeScope keys no class in `classes` has, in file order. A writer
|
|
302
|
+
* judged `human` may be in such a class, since nothing says which role puts
|
|
303
|
+
* a principal in it, so write scope refuses that writer (fail closed).
|
|
304
|
+
*/
|
|
305
|
+
export function unknownScopeClasses(writeScope: Record<string, unknown> | null, classes: ClassRegistry): string[] {
|
|
306
|
+
return Object.keys(writeScope ?? {}).filter((name) => classes.get(name) === undefined);
|
|
307
|
+
}
|
|
@@ -110,6 +110,30 @@ describe("every schema against the reference workspace (#2543)", () => {
|
|
|
110
110
|
TIMEOUT,
|
|
111
111
|
);
|
|
112
112
|
|
|
113
|
+
test(
|
|
114
|
+
"graph from the chant repo expands the nested reference workspace read-only, with outer/inner/id ids (#2551)",
|
|
115
|
+
async () => {
|
|
116
|
+
const { expectValid } = contract(graphSchema);
|
|
117
|
+
const before = git(REPO, "status", "--porcelain", "--untracked-files=all", "--", "reference-workspace");
|
|
118
|
+
for (const at of [undefined, "HEAD"]) {
|
|
119
|
+
const { doc, failed } = await workspaceGraph({ cwd: REPO, at, members: ["reference-workspace"], reader });
|
|
120
|
+
expectValid(doc);
|
|
121
|
+
if ("error" in doc) throw new Error(doc.error.message);
|
|
122
|
+
expect(failed, JSON.stringify(doc.members)).toBe(false);
|
|
123
|
+
const nested = doc.members.find((m) => m.name === "reference-workspace")!;
|
|
124
|
+
expect(nested).toMatchObject({ kind: "workspace", status: "composed", reason: null });
|
|
125
|
+
expect(nested.nested?.name).toBe("reference");
|
|
126
|
+
expect(nested.nested?.members.find((m) => m.name === "delivery")).toMatchObject({ status: "composed", dir: "delivery" });
|
|
127
|
+
expect(doc.nodes.length).toBeGreaterThan(0);
|
|
128
|
+
expect(doc.nodes.every((n) => n.id.startsWith("reference-workspace/delivery/") && n.member === "reference-workspace" && n.nested === "delivery")).toBe(true);
|
|
129
|
+
expect(doc.groups.byMember["reference-workspace"]).toEqual(doc.nodes.map((n) => n.id).sort());
|
|
130
|
+
}
|
|
131
|
+
// The outer read never writes inside the nested workspace.
|
|
132
|
+
expect(git(REPO, "status", "--porcelain", "--untracked-files=all", "--", "reference-workspace")).toBe(before);
|
|
133
|
+
},
|
|
134
|
+
TIMEOUT,
|
|
135
|
+
);
|
|
136
|
+
|
|
113
137
|
test("check, in the working tree and at HEAD", async () => {
|
|
114
138
|
const { expectValid } = contract(checkSchema);
|
|
115
139
|
for (const at of [undefined, "HEAD"]) {
|
|
@@ -14,7 +14,7 @@ import { MEMBER_RUN_REASON_CODES } from "./compose-graph";
|
|
|
14
14
|
import { COMPOSITES_ENVIRONMENT_REASON_CODES, COMPOSITES_ERROR_CODES, COMPOSITES_REASON_CODES, COMPOSITES_RUNTIME_REASON_CODES } from "./composites";
|
|
15
15
|
import { WORKSPACE_ERROR_CODES } from "./declaration";
|
|
16
16
|
import { GRAPH_ERROR_CODES } from "./graph-cli";
|
|
17
|
-
import { INTENT_ERROR_CODES, INTENT_FINDING_CODES, INTENT_REASON_CODES } from "./intent";
|
|
17
|
+
import { INTENT_ERROR_CODES, INTENT_FINDING_CODES, INTENT_REASON_CODES, INTENT_WHY_CODES } from "./intent";
|
|
18
18
|
import { CHECK_CODES, CHECK_ERROR_CODES } from "./lineage-check";
|
|
19
19
|
import { GROUP_REASON_CODES, MEMBER_REASON_CODES } from "./ls";
|
|
20
20
|
import intentSchema from "./intent.schema.json";
|
|
@@ -29,12 +29,19 @@ import { WORK_WARNING_CODES } from "./work";
|
|
|
29
29
|
import { BOX_FINDING_CODES } from "./checks/boxes";
|
|
30
30
|
import { DIAGRAM_FINDING_CODES } from "./checks/diagrams";
|
|
31
31
|
import { WORK_ERROR_CODES, WORK_HISTORY_ERROR_CODES, WORK_LEASE_REFUSALS } from "./work-cli";
|
|
32
|
+
import { RUNS_ERROR_CODES, RUNS_REASON_CODES, RUNS_WRITE_ERROR_CODES } from "./runs-cli";
|
|
32
33
|
import { WORK_EVIDENCE_ERROR_CODES } from "./work-evidence";
|
|
33
34
|
import { RECORD_FINDING_CODES } from "./checks/records";
|
|
34
35
|
import { ANSWER_WARNING_CODES } from "./points";
|
|
35
36
|
import { POINTS_ERROR_CODES, POINTS_SOURCE_REASON_CODES } from "./points-cli";
|
|
36
37
|
import { POINTS_WRITE_ERROR_CODES } from "./decide";
|
|
37
38
|
import { PATCH_ERROR_CODES } from "./patch";
|
|
39
|
+
import { AGENT_ERROR_CODES } from "./agent-cli";
|
|
40
|
+
import { SCOPE_FINDING_CODES, WRITE_SCOPE_CODES } from "./write-scope";
|
|
41
|
+
import { PLANTABLE_REASON_CODES } from "./box-factory";
|
|
42
|
+
import { ROTATION_REFUSAL_CODES } from "./trust/rotation";
|
|
43
|
+
import { SIGNERS_ERROR_CODES } from "./trust/signers-cli";
|
|
44
|
+
import { EVIDENCE_ERROR_CODES } from "./trust/evidence";
|
|
38
45
|
|
|
39
46
|
const HERE = import.meta.dirname;
|
|
40
47
|
|
|
@@ -68,6 +75,7 @@ const PER_COMMAND: Record<string, readonly string[]> = {
|
|
|
68
75
|
INTENT_ERROR_CODES,
|
|
69
76
|
INTENT_FINDING_CODES,
|
|
70
77
|
INTENT_REASON_CODES,
|
|
78
|
+
INTENT_WHY_CODES,
|
|
71
79
|
CHANGES_FINDING_CODES,
|
|
72
80
|
CHANGES_ERROR_CODES,
|
|
73
81
|
COMPOSITES_ERROR_CODES,
|
|
@@ -77,6 +85,9 @@ const PER_COMMAND: Record<string, readonly string[]> = {
|
|
|
77
85
|
WORK_ERROR_CODES,
|
|
78
86
|
WORK_HISTORY_ERROR_CODES,
|
|
79
87
|
WORK_LEASE_REFUSALS,
|
|
88
|
+
RUNS_ERROR_CODES,
|
|
89
|
+
RUNS_REASON_CODES,
|
|
90
|
+
RUNS_WRITE_ERROR_CODES,
|
|
80
91
|
WORK_EVIDENCE_ERROR_CODES,
|
|
81
92
|
RECORD_FINDING_CODES,
|
|
82
93
|
ANSWER_WARNING_CODES,
|
|
@@ -84,6 +95,13 @@ const PER_COMMAND: Record<string, readonly string[]> = {
|
|
|
84
95
|
POINTS_SOURCE_REASON_CODES,
|
|
85
96
|
POINTS_WRITE_ERROR_CODES,
|
|
86
97
|
PATCH_ERROR_CODES,
|
|
98
|
+
AGENT_ERROR_CODES,
|
|
99
|
+
WRITE_SCOPE_CODES,
|
|
100
|
+
SCOPE_FINDING_CODES,
|
|
101
|
+
PLANTABLE_REASON_CODES,
|
|
102
|
+
ROTATION_REFUSAL_CODES,
|
|
103
|
+
SIGNERS_ERROR_CODES,
|
|
104
|
+
EVIDENCE_ERROR_CODES,
|
|
87
105
|
};
|
|
88
106
|
|
|
89
107
|
/** Every string in an `enum` under a property named `code`, anywhere in a schema. */
|
|
@@ -135,7 +153,7 @@ describe("the closed list of reason codes", () => {
|
|
|
135
153
|
|
|
136
154
|
test("the output schemas name exactly these codes", () => {
|
|
137
155
|
const named = new Set<string>();
|
|
138
|
-
for (const f of readdirSync(HERE).filter((f) => f.endsWith(".schema.json") && !f.startsWith("declaration") && !f.startsWith("workspace-kinds"))) {
|
|
156
|
+
for (const f of readdirSync(HERE).filter((f) => f.endsWith(".schema.json") && !f.startsWith("declaration") && !f.startsWith("workspace-kinds") && !f.startsWith("workspace-principals"))) {
|
|
139
157
|
for (const c of schemaCodes(JSON.parse(readFileSync(join(HERE, f), "utf-8")))) {
|
|
140
158
|
expect(isReasonCode(c), `${f} names ${c}, which is not in reason-codes.ts`).toBe(true);
|
|
141
159
|
named.add(c);
|
|
@@ -70,8 +70,9 @@ export const REASONS = {
|
|
|
70
70
|
"record-supersedes-conflict": "A second closed record supersedes a record another one already superseded.",
|
|
71
71
|
"record-remediates-unknown": "A remediates link names an id no record has.",
|
|
72
72
|
"record-remediates-not-closed": "A remediates link names a record that isn't closed; a record still open is amended instead.",
|
|
73
|
+
"record-seal-mismatch": "A closed record's seal is not the whole-file seal of its text now: the record changed after it closed.",
|
|
73
74
|
// A review session that isn't valid (records, #2673).
|
|
74
|
-
"session-seal-mismatch": "A closed session's seal is not the
|
|
75
|
+
"session-seal-mismatch": "A closed session's seal is not the whole-file seal of its text now: the session changed after it closed, or was sealed by the rule before #2546.",
|
|
75
76
|
"session-verdict-unknown-record": "A session's verdict names a record that none of the session kind's subject records has.",
|
|
76
77
|
// A record that is valid but warned about (records, #2549).
|
|
77
78
|
"asset-drift": "A file the record pins by hash has changed: its bytes no longer hash to the pinned sha256.",
|
|
@@ -91,6 +92,9 @@ export const REASONS = {
|
|
|
91
92
|
"work-done-gap-open": "A work record is done, and the finding it came from still fires on its region. graph --intent raises it, and records does by walking that region.",
|
|
92
93
|
"work-acceptance-unmet": "A work record is done, and one of its acceptance criteria has no passing evidence of the verification it expects. check fails on it (WSP117).",
|
|
93
94
|
"work-acceptance-self-verified": "A passing manual verdict on a work record's criterion names the record's implementer, so it does not count: a manual verdict comes from someone else.",
|
|
95
|
+
"work-contract-unknown": "A work record names a contract that no record of its kind's contract kind has.",
|
|
96
|
+
"work-contract-undecided": "A work record names a contract whose state is not approved, such as a draft.",
|
|
97
|
+
"work-tier-unknown": "A work record names a builder tier that its kind's work.tier.tiers does not list.",
|
|
94
98
|
// An answer to a decision point that is valid but warned about (records, points, ws-058, #2739).
|
|
95
99
|
"answer-points-unreadable": "The points file the answer kind names can't be read, or is not valid.",
|
|
96
100
|
"answer-point-unknown": "The answer's point is not declared in the points file the answer kind names.",
|
|
@@ -105,7 +109,7 @@ export const REASONS = {
|
|
|
105
109
|
"seal-missing": "The verdict, or the record, carries no seal.",
|
|
106
110
|
"seal-signer-unlisted": "The reviewer, or the record's author, has no key in the signers file at base, so the seal can't count.",
|
|
107
111
|
"seal-signature-invalid": "The seal is malformed, names a signer other than the reviewer or author, or its signature does not verify over the verdict or record.",
|
|
108
|
-
"seal-unverifiable": "Nothing here can say whose seal it is: there is no signers file at base,
|
|
112
|
+
"seal-unverifiable": "Nothing here can say whose seal it is: there is no signers file at base, ssh-keygen is not installed, or the record came back in a return sealed by a signer no admission lists yet.",
|
|
109
113
|
// A record whose author seal is not attested under a signers file at base (records, #2688). A warning: the record is still read.
|
|
110
114
|
"record-unattested": "A signers file is active at base, and the record names an author whose seal does not verify: it has none, the author has no key in the file, or the signature fails.",
|
|
111
115
|
// A records read that fails (records).
|
|
@@ -132,6 +136,13 @@ export const REASONS = {
|
|
|
132
136
|
"source-harvest-not-proposed": "A harvested record (source.via harvest) was written in a state other than the kind's first: a harvest proposes, and a person decides.",
|
|
133
137
|
"ratify-quorum-not-met": "The write puts a record in its kind's ratified state (reviews.ratified), and the record's quorum is not met: too few agreeing verdicts count.",
|
|
134
138
|
"record-sign-failed": "--sign was given and no author seal could be made: the record names no author, the key can't be read or used, git names no ssh signing key, or ssh-keygen is not installed.",
|
|
139
|
+
// Write scope (#2548): a records write that is refused, and a commit check --changes reports, outside the writer's scope.
|
|
140
|
+
"write-scope-member": "The write is to a file, or to a record kind, of a member outside the writer's scope: an agent session writes only its own member, and writeScope.<class>.members leaves the member out.",
|
|
141
|
+
"write-scope-kind": "The write is to a record kind writeScope.<class>.records does not list, with a verb it does not list for the kind, or deletes a record.",
|
|
142
|
+
"write-scope-protected": "The write is to a file writeScope.<class>.protected lists, or one under a directory it lists, outside any top-level keys the entry's except allows (#3146).",
|
|
143
|
+
"write-scope-class-unknown": "The declaration's writeScope at base names a principal class no pinned package supplies, and the writer is judged human, so it may be in that class; the write is refused until the package is installed at the pinned version or the entry removed (#3080).",
|
|
144
|
+
"agent-unknown": "CHANT_AGENT, or a commit's Chant-Agent trailer, names an agent session the declaration at base does not declare.",
|
|
145
|
+
"principal-unidentified": "chant.workspace.json at base sets identity.attribution to identified, and the write names a person by a bare name: --by, an author field or a decision point's answerer must be a forge identity (github:<login>, gitlab:<login>, <forge>@<host>:<login>), a principal the signers file at base lists, or an agent, runner or service principal (#3163).",
|
|
135
146
|
// A review given in a session (records review --session, #2693).
|
|
136
147
|
"session-unknown": "--session names no session of a session kind whose subjects are the record's kind.",
|
|
137
148
|
"session-not-open": "--session names a session in a closed state, which takes no more verdicts.",
|
|
@@ -151,12 +162,15 @@ export const REASONS = {
|
|
|
151
162
|
// The intent graph (graph --intent, #2651): a read that fails.
|
|
152
163
|
"intent-region-invalid": "The region's path, or its line range, does not exist in the tree read.",
|
|
153
164
|
"intent-record-unknown": "graph --intent --record names an id that no record of a decision kind read has.",
|
|
165
|
+
"intent-symbol-unsupported": "The region names a symbol, path#symbol, in a file no symbol resolver reads; a line range still works.",
|
|
166
|
+
"intent-symbol-unknown": "The region names a symbol the file does not declare in the tree read.",
|
|
167
|
+
"intent-symbol-ambiguous": "The region names a symbol that matches more than one declaration in the file; its qualified name picks one.",
|
|
154
168
|
// The intent graph: part of the walk that can't be read. The document is still printed.
|
|
155
169
|
"intent-history-shallow": "The repository is a shallow clone, so the region's history stops at the clone's boundary.",
|
|
156
170
|
"intent-plugin-failed": "A kind file's commitJoins, which joins commits to units, contracts and evidence, failed for a commit.",
|
|
157
171
|
// The intent graph: findings, each a node in the graph.
|
|
158
172
|
"intent-commit-undecided": "A commit changed the region when no decision constrained it at path granularity.",
|
|
159
|
-
"intent-commit-bare": "A commit names no unit, no pull request and no decision covering the region at its time.",
|
|
173
|
+
"intent-commit-bare": "A commit names no unit, carries no record through its Chant-Record or Chant-Lease trailer, and has no pull request and no decision covering the region at its time.",
|
|
160
174
|
"intent-pin-drifted": "A decision's pinned artifact no longer hashes to the pin.",
|
|
161
175
|
"intent-pin-missing": "A decision's pinned artifact does not exist in the tree read.",
|
|
162
176
|
"intent-pin-stale": "A current decision pins an artifact at the hash a record it supersedes pinned, and the artifact has not changed since: the decision moved on and the artifact did not.",
|
|
@@ -172,6 +186,11 @@ export const REASONS = {
|
|
|
172
186
|
"intent-decision-unimplemented": "A decided decision constrains the region, no work item that is not dropped implements it, and no commit falls in its window.",
|
|
173
187
|
"intent-work-blocked": "A work item constraining the region has commits in its window while a work item it needs is not done.",
|
|
174
188
|
"intent-work-open-decided-code": "Commits in the region are a decision's own work while the work item implementing that decision is still open.",
|
|
189
|
+
// The intent graph's answer to why the region is like this (#3034): what it can't account for.
|
|
190
|
+
"intent-why-no-decision": "No current decision governs the region at any granularity, and none is carried out by the commits or runs that made its current lines.",
|
|
191
|
+
"intent-why-no-run": "None of the region's current lines was made by a commit an agent run is joined to.",
|
|
192
|
+
"intent-why-uncommitted": "Some of the region's lines are not committed yet.",
|
|
193
|
+
"intent-why-run-ambiguous": "Some lines come from a commit several agent runs made, and no run's recorded hunks say which wrote them.",
|
|
175
194
|
// The forward coverage check (check --changes, #2773): findings, one per changed path.
|
|
176
195
|
"change-uncovered": "A path the diff changes is covered by no current decided record and no open work item, by path or by its member.",
|
|
177
196
|
"change-out-of-scope": "A record in hand for the change, such as the work item it is for or a decision that item implements, lists a path the diff changes in its out_of_scope.",
|
|
@@ -200,6 +219,9 @@ export const REASONS = {
|
|
|
200
219
|
// A box's intent, the decision record its box block names (check, #2850). Each is also a WSP finding.
|
|
201
220
|
"box-intent-unknown": "A box block names an intent, and no record of a declared kind named decision has that id.",
|
|
202
221
|
"box-intent-unconstrained": "The decision record a box names as its intent constrains no member or path of this workspace: no member: entry for a declared member and no path: entry at, above or inside one's directory.",
|
|
222
|
+
// Why a workspace isn't plantable (status and graph, #3146): not a finding, since a workspace need not be.
|
|
223
|
+
"box-none": "No member's box block declares services, so the workspace has no box for a host to plant.",
|
|
224
|
+
"box-several": "More than one member's box block declares services, and a planted workspace runs one box.",
|
|
203
225
|
// The work lease (chant workspace work claim|renew|release, #2732): why the command could not run.
|
|
204
226
|
"work-kind-missing": "No work kind to find the item in: --kind names a kind with no work block, or the declaration names no work kind.",
|
|
205
227
|
"work-kind-ambiguous": "More than one declared work kind has a record with the id, so --kind must name one.",
|
|
@@ -213,9 +235,37 @@ export const REASONS = {
|
|
|
213
235
|
"lease-token-mismatch": "The live lease on the work item carries another fencing token than the one given.",
|
|
214
236
|
"lease-race": "Another writer changed the lease between this command's read and its write.",
|
|
215
237
|
"lease-push-rejected": "The remote refused the lease push: another clone claimed the item first, or the remote could not be reached.",
|
|
238
|
+
// The agent run record (chant workspace runs, #3033): why a write was refused, and what a read could not see. Nothing is written on a refusal.
|
|
239
|
+
"run-exists": "runs start or runs record was given a run id the ledger already has.",
|
|
240
|
+
"run-unknown": "runs end names a run the ledger has no start for.",
|
|
241
|
+
"run-ended": "runs end names a run whose end is already recorded.",
|
|
242
|
+
"runs-no-ledger": "The checkout has no chant/lifecycle branch, so there are no agent runs to read.",
|
|
243
|
+
"runs-ledger-malformed": "Some lines of the agent run ledger aren't run events; the rest are read.",
|
|
216
244
|
// A box whose isolation fails (check, #2727). Each is also a WSP finding.
|
|
217
245
|
"box-isolation-collision": "Two boxes on one host resolve to the same port, state path or cookie name, or two ports in one box share an offset.",
|
|
218
246
|
"box-isolation-literal": "A host's stateRoot or a box's state entry is a literal machine path instead of one derived from an environment reference and the box's name.",
|
|
247
|
+
// The signer set's history (signers and verify, #2553): why a version is not a valid rotation of the one before. Nothing verifies past it.
|
|
248
|
+
"signers-file-missing": "There is no signers file at the base revision, so there is no signer history to read.",
|
|
249
|
+
"signers-removed": "The signers file was removed. Commits merged before the removal keep the set they were judged by; nothing after it verifies.",
|
|
250
|
+
"rotation-unparseable": "The rotation file beside the signers file is not JSON.",
|
|
251
|
+
"rotation-invalid": "The rotation file does not match its shape: schema 1, a version, the previous set's digest, a threshold and signatures.",
|
|
252
|
+
"rotation-first-version": "The first signer set's rotation file names a version other than 1, or a previous digest.",
|
|
253
|
+
"rotation-missing": "The signer set or its threshold changed and no rotation file signed by the set before it came with the change.",
|
|
254
|
+
"rotation-version-skew": "The rotation names a version other than the one after the set it replaces, as a replayed or skipped rotation does.",
|
|
255
|
+
"rotation-previous-mismatch": "The rotation names a previous digest other than the set it replaces, as a rollback to an older set does.",
|
|
256
|
+
"rotation-threshold-unsatisfiable": "The new threshold is more than the number of distinct signers in the new set, so no later rotation could meet it.",
|
|
257
|
+
"rotation-threshold-not-met": "Fewer distinct signers of the set before signed the rotation, in the chant-signers namespace, than that set's threshold.",
|
|
258
|
+
// Runner evidence (evidence sign and verify, #2553): why evidence is refused.
|
|
259
|
+
"trust-policy-unreadable": "The trust policy at base can't be read, or its signer history is broken, so no runner key is trusted.",
|
|
260
|
+
"envelope-unreadable": "The --envelope file can't be read, or is not JSON.",
|
|
261
|
+
"envelope-invalid": "The file is not a DSSE envelope: payloadType, payload in canonical base64, and signatures with keyid and sig.",
|
|
262
|
+
"envelope-untrusted": "No signature in the envelope verifies against a runner key the policy at base lists.",
|
|
263
|
+
"evidence-payload-type": "The envelope's payload type is not application/vnd.in-toto+json.",
|
|
264
|
+
"evidence-statement-invalid": "The payload is not an in-toto Statement v1 with chant's runner-evidence predicate, or has a field the predicate does not define.",
|
|
265
|
+
"evidence-runner-mismatch": "The statement names a runner other than the one whose key signed it.",
|
|
266
|
+
"runner-key-invalid": "The key given to evidence sign is not an Ed25519 private key in PEM.",
|
|
267
|
+
"runner-key-is-signer": "The key given to evidence sign is a person's key in the signers file. Evidence is signed by a service or CI identity.",
|
|
268
|
+
"runner-key-unlisted": "The policy at base lists no runner with the key given to evidence sign.",
|
|
219
269
|
// The lineage lock (check).
|
|
220
270
|
"lock-invalid": "The lineage lock can't be read.",
|
|
221
271
|
"manual-step-open": "A scope in the lineage lock has an open manual step.",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* `citedBy`. This module only reads; nothing here writes a seal into a file.
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import {
|
|
15
|
+
import { recordSeal, type RecordEntry, type RecordFormat, type RecordKind } from "./records";
|
|
16
16
|
|
|
17
17
|
/** A subject record's review entry that names a session in its `session` field. */
|
|
18
18
|
export interface SessionCitation {
|
|
@@ -29,19 +29,15 @@ export interface SessionCitation {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
|
-
* The seal of a session record: {@link
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* `awk 'NR==1&&/^---$/{f=1;print;next} f&&/^---$/{f=0} f&&/^closed_digest:/{next} {print}' S-0001.md | shasum -a 256`
|
|
39
|
-
* gives the same value for a file with LF line endings that ends in one.
|
|
40
|
-
* For a session kind of format json (ws-053), the seal member is removed by
|
|
41
|
-
* the JSON rule of {@link recordTextDigest} instead.
|
|
32
|
+
* The seal of a session record: {@link recordSeal} with the seal field, the
|
|
33
|
+
* whole-file JCS/SHA-256 every closed record of a sealed kind carries
|
|
34
|
+
* (#2546, ws-063). Until #2546 it was the SHA-256 of the file's text without
|
|
35
|
+
* the seal line; a session sealed by that rule holds a bare hex value and
|
|
36
|
+
* reads as `session-seal-mismatch` now. Null when the front matter can't be
|
|
37
|
+
* parsed.
|
|
42
38
|
*/
|
|
43
|
-
export function sessionSeal(text: string, field: string, format: RecordFormat = "markdown-front-matter"): string {
|
|
44
|
-
return
|
|
39
|
+
export function sessionSeal(text: string, field: string, format: RecordFormat = "markdown-front-matter"): string | null {
|
|
40
|
+
return recordSeal(text, field, format);
|
|
45
41
|
}
|
|
46
42
|
|
|
47
43
|
/**
|
|
@@ -86,7 +82,9 @@ export function joinSessions(kind: RecordKind, entries: RecordEntry[], texts: Ma
|
|
|
86
82
|
if (actual !== seal) {
|
|
87
83
|
e.reasons.push({
|
|
88
84
|
code: "session-seal-mismatch",
|
|
89
|
-
message:
|
|
85
|
+
message: /^[0-9a-f]{64}$/.test(seal)
|
|
86
|
+
? `${decl.seal} is ${seal}, a seal by the text rule chant used before #2546, and the session seals to ${actual} now: seal it again by hand, since a closed session is never rewritten by chant`
|
|
87
|
+
: `${decl.seal} is ${seal}, but the session seals to ${actual}: the session changed after it closed`,
|
|
90
88
|
});
|
|
91
89
|
}
|
|
92
90
|
}
|
|
@@ -176,6 +176,11 @@
|
|
|
176
176
|
"amend-supersede-instead",
|
|
177
177
|
"record-sign-failed",
|
|
178
178
|
"ratify-quorum-not-met",
|
|
179
|
+
"write-scope-member",
|
|
180
|
+
"write-scope-kind",
|
|
181
|
+
"write-scope-class-unknown",
|
|
182
|
+
"agent-unknown",
|
|
183
|
+
"principal-unidentified",
|
|
179
184
|
"record-unparseable",
|
|
180
185
|
"record-schema-invalid",
|
|
181
186
|
"record-id-duplicate",
|
|
@@ -183,6 +188,7 @@
|
|
|
183
188
|
"record-supersedes-conflict",
|
|
184
189
|
"record-remediates-unknown",
|
|
185
190
|
"record-remediates-not-closed",
|
|
191
|
+
"record-seal-mismatch",
|
|
186
192
|
"session-seal-mismatch",
|
|
187
193
|
"session-verdict-unknown-record"
|
|
188
194
|
]
|