@intentius/chant 0.101.0 → 0.104.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/core.d.ts +2 -0
- package/dist/audit/core.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/builder.d.ts.map +1 -1
- package/dist/change-set.d.ts +232 -0
- package/dist/change-set.d.ts.map +1 -0
- package/dist/cli/commands/audit.d.ts +7 -0
- package/dist/cli/commands/audit.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/build.d.ts.map +1 -1
- package/dist/cli/handlers/change-set.d.ts +11 -0
- package/dist/cli/handlers/change-set.d.ts.map +1 -0
- package/dist/cli/handlers/dev.d.ts.map +1 -1
- package/dist/cli/handlers/fan-out.d.ts +33 -0
- 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 +16 -0
- package/dist/cli/handlers/operator.d.ts.map +1 -1
- package/dist/cli/handlers/pr.d.ts +31 -0
- package/dist/cli/handlers/pr.d.ts.map +1 -0
- 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/op-tools.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 +4 -3
- package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +74 -3
- 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/auto-release.d.ts +16 -0
- package/dist/components/auto-release.d.ts.map +1 -1
- package/dist/components/capability-plugin-loader.d.ts.map +1 -1
- package/dist/components/capability.d.ts +53 -0
- package/dist/components/capability.d.ts.map +1 -1
- package/dist/components/changed-files.d.ts +31 -0
- package/dist/components/changed-files.d.ts.map +1 -0
- package/dist/components/cli-support.d.ts +9 -1
- package/dist/components/cli-support.d.ts.map +1 -1
- package/dist/components/component.d.ts +24 -0
- package/dist/components/component.d.ts.map +1 -1
- package/dist/components/deploy-units.d.ts.map +1 -1
- package/dist/components/driver.d.ts +13 -0
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/fan-out-output.d.ts +6 -0
- package/dist/components/fan-out-output.d.ts.map +1 -1
- package/dist/components/fan-out-record.d.ts +41 -0
- package/dist/components/fan-out-record.d.ts.map +1 -0
- package/dist/components/fan-out-run.d.ts +65 -0
- package/dist/components/fan-out-run.d.ts.map +1 -1
- package/dist/components/fan-out-support.d.ts +2 -0
- package/dist/components/fan-out-support.d.ts.map +1 -1
- package/dist/components/fan-out.d.ts +6 -0
- package/dist/components/fan-out.d.ts.map +1 -1
- package/dist/components/gated-wave-pipeline.d.ts +50 -0
- package/dist/components/gated-wave-pipeline.d.ts.map +1 -0
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/layers.d.ts +25 -0
- package/dist/components/layers.d.ts.map +1 -0
- package/dist/components/pr-pipeline.d.ts +61 -0
- package/dist/components/pr-pipeline.d.ts.map +1 -0
- package/dist/components/pr-run.d.ts +119 -0
- package/dist/components/pr-run.d.ts.map +1 -0
- package/dist/components/promote.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/shell.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/components/wave-plan.d.ts +49 -0
- package/dist/components/wave-plan.d.ts.map +1 -0
- package/dist/composite.d.ts.map +1 -1
- package/dist/config.d.ts +19 -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/gated-waves.d.ts +147 -0
- package/dist/gated-waves.d.ts.map +1 -0
- 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/index.d.ts +1 -0
- package/dist/index.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 +103 -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 +22 -0
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/git.d.ts +46 -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-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 +8 -8
- package/dist/lint/engine.d.ts +6 -0
- package/dist/lint/engine.d.ts.map +1 -1
- package/dist/lint/post-synth.d.ts +18 -0
- package/dist/lint/post-synth.d.ts.map +1 -1
- package/dist/lsp/lexicon-providers.d.ts.map +1 -1
- package/dist/op/activities/activity-contracts.d.ts +137 -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/change-set.d.ts +62 -0
- package/dist/op/activities/change-set.d.ts.map +1 -0
- package/dist/op/activities/decide.d.ts +2 -0
- package/dist/op/activities/decide.d.ts.map +1 -1
- package/dist/op/activities/factory.d.ts +137 -0
- package/dist/op/activities/factory.d.ts.map +1 -0
- package/dist/op/activities/index.d.ts +5 -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/activity-contract.d.ts +1 -1
- package/dist/op/activity-contract.d.ts.map +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 +11 -0
- 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 +5 -1
- package/dist/op/decide-backend.d.ts.map +1 -1
- package/dist/op/decide-read-inputs.d.ts +4 -2
- 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/factory.d.ts +83 -0
- package/dist/op/factory.d.ts.map +1 -0
- 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 +6 -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/op-ir.d.ts +2 -0
- package/dist/op/op-ir.d.ts.map +1 -1
- package/dist/op/op-verb-class.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 +16 -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/plan-summary.d.ts +207 -0
- package/dist/plan-summary.d.ts.map +1 -0
- package/dist/pr-forge.d.ts +105 -0
- package/dist/pr-forge.d.ts.map +1 -0
- package/dist/pr-loop.d.ts +178 -0
- package/dist/pr-loop.d.ts.map +1 -0
- 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/telemetry-attribution.d.ts +31 -0
- package/dist/telemetry-attribution.d.ts.map +1 -1
- package/dist/terraform/emit-source.d.ts.map +1 -1
- package/dist/terraform/hcl2json.d.ts +45 -0
- package/dist/terraform/hcl2json.d.ts.map +1 -0
- package/dist/terraform/parse.d.ts +4 -40
- 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 +5 -0
- package/dist/workspace/agent-cli.d.ts.map +1 -1
- package/dist/workspace/box-cli.d.ts +12 -0
- package/dist/workspace/box-cli.d.ts.map +1 -0
- package/dist/workspace/box-factory.d.ts +97 -0
- package/dist/workspace/box-factory.d.ts.map +1 -0
- package/dist/workspace/box-listing.d.ts +85 -0
- package/dist/workspace/box-listing.d.ts.map +1 -0
- package/dist/workspace/box-publish.d.ts +147 -0
- package/dist/workspace/box-publish.d.ts.map +1 -0
- package/dist/workspace/broker-protocol.d.ts +190 -0
- package/dist/workspace/broker-protocol.d.ts.map +1 -0
- 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.d.ts +5 -0
- package/dist/workspace/checks.d.ts.map +1 -1
- package/dist/workspace/compose-graph.d.ts +10 -0
- package/dist/workspace/compose-graph.d.ts.map +1 -1
- package/dist/workspace/composites.d.ts +2 -2
- package/dist/workspace/composites.d.ts.map +1 -1
- package/dist/workspace/conformance/__fixtures__/reference-broker.d.ts +17 -0
- package/dist/workspace/conformance/__fixtures__/reference-broker.d.ts.map +1 -0
- package/dist/workspace/conformance/broker.d.ts +202 -0
- package/dist/workspace/conformance/broker.d.ts.map +1 -0
- package/dist/workspace/conformance/index.d.ts +68 -6
- package/dist/workspace/conformance/index.d.ts.map +1 -1
- package/dist/workspace/conformance/vitest.d.ts +19 -3
- package/dist/workspace/conformance/vitest.d.ts.map +1 -1
- package/dist/workspace/conformance/writer.d.ts +462 -0
- package/dist/workspace/conformance/writer.d.ts.map +1 -0
- package/dist/workspace/decide.d.ts +126 -12
- package/dist/workspace/decide.d.ts.map +1 -1
- package/dist/workspace/decision-points.schema.json +11 -4
- package/dist/workspace/declaration.d.ts +156 -4
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.schema.json +383 -5
- package/dist/workspace/environments.d.ts +36 -10
- package/dist/workspace/environments.d.ts.map +1 -1
- package/dist/workspace/factory-rules.d.ts +180 -0
- package/dist/workspace/factory-rules.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/init.d.ts +21 -0
- package/dist/workspace/init.d.ts.map +1 -1
- 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 +36 -2
- package/dist/workspace/intent-record.d.ts.map +1 -1
- package/dist/workspace/intent.d.ts +249 -8
- package/dist/workspace/intent.d.ts.map +1 -1
- package/dist/workspace/json-edit.d.ts +24 -0
- package/dist/workspace/json-edit.d.ts.map +1 -0
- package/dist/workspace/jsonc.d.ts +11 -0
- package/dist/workspace/jsonc.d.ts.map +1 -1
- package/dist/workspace/kinds.d.ts +66 -4
- package/dist/workspace/kinds.d.ts.map +1 -1
- package/dist/workspace/lexicon-symbols.d.ts +29 -0
- package/dist/workspace/lexicon-symbols.d.ts.map +1 -0
- package/dist/workspace/lineage-hash-index.d.ts.map +1 -1
- package/dist/workspace/lineage-lock.d.ts +2 -2
- package/dist/workspace/lineage-lock.d.ts.map +1 -1
- package/dist/workspace/lineage-upgrade.d.ts +31 -2
- package/dist/workspace/lineage-upgrade.d.ts.map +1 -1
- package/dist/workspace/links.d.ts.map +1 -1
- package/dist/workspace/point-answer.schema.json +42 -2
- package/dist/workspace/points-cli.d.ts +10 -3
- package/dist/workspace/points-cli.d.ts.map +1 -1
- package/dist/workspace/points.d.ts +66 -5
- 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 +53 -4
- 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 +5 -7
- 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 +34 -1
- package/dist/workspace/records-cli.d.ts.map +1 -1
- package/dist/workspace/records-close.d.ts +7 -3
- 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 +68 -7
- package/dist/workspace/records-write.d.ts.map +1 -1
- package/dist/workspace/records.d.ts +43 -9
- package/dist/workspace/records.d.ts.map +1 -1
- package/dist/workspace/runs-cli.d.ts +296 -0
- package/dist/workspace/runs-cli.d.ts.map +1 -0
- package/dist/workspace/runs.d.ts +544 -0
- package/dist/workspace/runs.d.ts.map +1 -0
- package/dist/workspace/session-kinds.d.ts +1 -1
- package/dist/workspace/session-kinds.d.ts.map +1 -1
- package/dist/workspace/source-block.d.ts +1 -1
- package/dist/workspace/source-block.d.ts.map +1 -1
- package/dist/workspace/squash.d.ts +80 -0
- package/dist/workspace/squash.d.ts.map +1 -0
- package/dist/workspace/status-gates.d.ts +17 -3
- package/dist/workspace/status-gates.d.ts.map +1 -1
- package/dist/workspace/status.d.ts +64 -0
- package/dist/workspace/status.d.ts.map +1 -1
- package/dist/workspace/symbols.d.ts +63 -0
- package/dist/workspace/symbols.d.ts.map +1 -0
- 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.map +1 -1
- package/dist/workspace/trust/rotation.d.ts.map +1 -1
- package/dist/workspace/trust/run-commits.d.ts +46 -0
- package/dist/workspace/trust/run-commits.d.ts.map +1 -0
- package/dist/workspace/trust/run-statement.d.ts +128 -0
- package/dist/workspace/trust/run-statement.d.ts.map +1 -0
- package/dist/workspace/trust/seal.d.ts +38 -0
- package/dist/workspace/trust/seal.d.ts.map +1 -1
- package/dist/workspace/trust/test-repo.d.ts.map +1 -1
- package/dist/workspace/trust/verify-cli.d.ts +1 -1
- package/dist/workspace/trust/verify.d.ts +16 -2
- package/dist/workspace/trust/verify.d.ts.map +1 -1
- package/dist/workspace/wip-cli.d.ts +21 -0
- package/dist/workspace/wip-cli.d.ts.map +1 -0
- package/dist/workspace/wip.d.ts +268 -0
- package/dist/workspace/wip.d.ts.map +1 -0
- 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-size.d.ts +55 -0
- package/dist/workspace/work-size.d.ts.map +1 -0
- package/dist/workspace/work.d.ts +26 -1
- package/dist/workspace/work.d.ts.map +1 -1
- package/dist/workspace/workspace-kinds.schema.json +122 -0
- package/dist/workspace/workspace-principals.schema.json +60 -0
- package/dist/workspace/write-lock-cli.d.ts +60 -0
- package/dist/workspace/write-lock-cli.d.ts.map +1 -0
- package/dist/workspace/write-lock.d.ts +152 -0
- package/dist/workspace/write-lock.d.ts.map +1 -0
- package/dist/workspace/write-scope.d.ts +83 -19
- package/dist/workspace/write-scope.d.ts.map +1 -1
- package/dist/yaml.d.ts +21 -39
- package/dist/yaml.d.ts.map +1 -1
- package/package.json +7 -2
- package/src/__fixtures__/change-set/lifecycle-plan.floci.json +59 -0
- package/src/__fixtures__/change-set/lifecycle-v1.ts.txt +4 -0
- package/src/__fixtures__/change-set/lifecycle-v2.ts.txt +4 -0
- package/src/__fixtures__/change-set/lifecycle.change-set.golden.json +95 -0
- package/src/__fixtures__/change-set/warden.change-set.golden.json +106 -0
- package/src/__fixtures__/change-set/warden.plan.json +44 -0
- package/src/__fixtures__/plan-summary/normalization-vectors.json +1593 -0
- package/src/__fixtures__/pr-loop/pr-apply-applied.note.golden.md +31 -0
- package/src/__fixtures__/pr-loop/pr-apply-refused.note.golden.md +31 -0
- package/src/__fixtures__/pr-loop/pr-plan.golden.json +127 -0
- package/src/__fixtures__/pr-loop/pr-plan.note.golden.md +37 -0
- package/src/audit/core.test.ts +15 -0
- package/src/audit/core.ts +8 -2
- package/src/audit/discover.test.ts +11 -0
- package/src/audit/discover.ts +7 -2
- package/src/audit/prior-art.ts +15 -0
- package/src/change-set-bundle.test.ts +57 -0
- package/src/change-set.test.ts +215 -0
- package/src/change-set.ts +445 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +1 -1
- package/src/cli/commands/audit-opt-in.test.ts +54 -0
- package/src/cli/commands/audit.ts +29 -2
- package/src/cli/commands/build.test.ts +19 -0
- package/src/cli/commands/build.ts +3 -2
- 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 +18 -0
- package/src/cli/commands/import-parser-options.test.ts +133 -0
- package/src/cli/commands/import.ts +21 -3
- 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/build.ts +13 -1
- package/src/cli/handlers/change-set.test.ts +56 -0
- package/src/cli/handlers/change-set.ts +44 -0
- package/src/cli/handlers/components.ts +2 -2
- package/src/cli/handlers/dev.ts +8 -6
- package/src/cli/handlers/fan-out.test.ts +221 -2
- package/src/cli/handlers/fan-out.ts +165 -75
- package/src/cli/handlers/graph.ts +3 -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.test.ts +21 -0
- package/src/cli/handlers/operator.ts +121 -6
- package/src/cli/handlers/pr.ts +373 -0
- package/src/cli/handlers/run.test.ts +111 -0
- package/src/cli/handlers/run.ts +86 -24
- package/src/cli/handlers/scenario.ts +2 -2
- package/src/cli/main.test.ts +21 -0
- package/src/cli/main.ts +246 -30
- package/src/cli/mcp/never-over-mcp.test.ts +101 -0
- package/src/cli/mcp/op-tools.ts +24 -2
- package/src/cli/mcp/workspace-tools.test.ts +5 -2
- package/src/cli/mcp/workspace-tools.ts +62 -7
- package/src/cli/registry.ts +74 -3
- 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/testdata/postgres-tags.json +242 -0
- package/src/components/auto-release.ts +1 -1
- package/src/components/capability.ts +55 -0
- package/src/components/changed-files.ts +66 -0
- package/src/components/cli-support.ts +28 -5
- package/src/components/component.schema.json +17 -0
- package/src/components/component.ts +25 -0
- package/src/components/deploy-units.ts +3 -0
- package/src/components/driver.test.ts +52 -0
- package/src/components/driver.ts +31 -13
- package/src/components/fan-out-output.ts +42 -1
- package/src/components/fan-out-record.ts +69 -0
- package/src/components/fan-out-run.test.ts +17 -0
- package/src/components/fan-out-run.ts +304 -1
- package/src/components/fan-out-support.ts +3 -0
- package/src/components/fan-out-waves.test.ts +375 -0
- package/src/components/fan-out.ts +18 -17
- package/src/components/gated-wave-pipeline.ts +82 -0
- package/src/components/index.ts +1 -0
- package/src/components/layers.ts +30 -0
- package/src/components/pr-pipeline.ts +91 -0
- package/src/components/pr-run.test.ts +205 -0
- package/src/components/pr-run.ts +280 -0
- package/src/components/promote.ts +5 -0
- package/src/components/verbs/shell.test.ts +11 -0
- package/src/components/verbs/shell.ts +7 -3
- package/src/components/wave-plan.ts +124 -0
- package/src/config.test.ts +21 -0
- package/src/config.ts +15 -0
- 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/sandbox/bundle.ts +1 -1
- 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/gated-waves-bundle.test.ts +62 -0
- package/src/gated-waves.test.ts +118 -0
- package/src/gated-waves.ts +240 -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/index.ts +1 -0
- package/src/lexicon.ts +106 -3
- package/src/lifecycle/gate-ledger.ts +23 -0
- package/src/lifecycle/git.ts +102 -16
- package/src/lifecycle/observe.test.ts +18 -0
- package/src/lifecycle/observe.ts +6 -4
- 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/lint/post-synth.test.ts +19 -0
- package/src/lint/post-synth.ts +19 -1
- package/src/meta/declared-imports.test.ts +1 -1
- package/src/op/activities/activity-contracts.ts +84 -0
- package/src/op/activities/apply.test.ts +189 -5
- package/src/op/activities/apply.ts +230 -8
- package/src/op/activities/change-set.ts +114 -0
- package/src/op/activities/decide.ts +3 -0
- package/src/op/activities/factory.ts +675 -0
- package/src/op/activities/index.ts +9 -0
- package/src/op/activities/lexicon-upgrade.test.ts +160 -6
- package/src/op/activities/lexicon-upgrade.ts +154 -51
- package/src/op/activity-contract.test.ts +21 -1
- package/src/op/activity-contract.ts +19 -9
- package/src/op/builders.ts +23 -0
- 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/decide-backend.ts +5 -1
- package/src/op/decide-read-inputs.ts +33 -5
- package/src/op/emulator-lifecycle.test.ts +23 -0
- package/src/op/emulator-lifecycle.ts +52 -14
- package/src/op/factory.e2e.test.ts +232 -0
- package/src/op/factory.ts +118 -0
- package/src/op/gate-approval.test.ts +74 -0
- package/src/op/gate-approval.ts +5 -1
- package/src/op/gate.ts +31 -5
- package/src/op/index.ts +11 -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/op-ir.test.ts +9 -0
- package/src/op/op-ir.ts +4 -0
- package/src/op/op-verb-class.ts +3 -0
- 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 +16 -3
- package/src/op/work-lease-run.test.ts +47 -0
- package/src/op/work-lease-run.ts +76 -11
- package/src/plan-summary.test.ts +263 -0
- package/src/plan-summary.ts +845 -0
- package/src/pr-forge.test.ts +237 -0
- package/src/pr-forge.ts +332 -0
- package/src/pr-loop-bundle.test.ts +46 -0
- package/src/pr-loop.test.ts +171 -0
- package/src/pr-loop.ts +324 -0
- package/src/provenance.ts +35 -0
- package/src/telemetry-attribution.test.ts +23 -1
- package/src/telemetry-attribution.ts +51 -0
- package/src/terraform/hcl2json.test.ts +21 -0
- package/src/terraform/hcl2json.ts +81 -0
- package/src/terraform/parse.ts +11 -74
- package/src/workspace/agent-cli.ts +7 -3
- package/src/workspace/agent.schema.json +22 -0
- package/src/workspace/app-kind.test.ts +196 -0
- package/src/workspace/box-cli.ts +113 -0
- package/src/workspace/box-factory.test.ts +323 -0
- package/src/workspace/box-factory.ts +136 -0
- package/src/workspace/box-listing-write.schema.json +204 -0
- package/src/workspace/box-listing.test.ts +234 -0
- package/src/workspace/box-listing.ts +324 -0
- package/src/workspace/box-publish.schema.json +498 -0
- package/src/workspace/box-publish.test.ts +204 -0
- package/src/workspace/box-publish.ts +420 -0
- package/src/workspace/box-ship.test.ts +96 -0
- package/src/workspace/broker-protocol.schema.json +186 -0
- package/src/workspace/broker-protocol.test.ts +122 -0
- package/src/workspace/broker-protocol.ts +317 -0
- package/src/workspace/builder-tiers.test.ts +146 -0
- package/src/workspace/change-set.schema.json +460 -0
- package/src/workspace/changes.schema.json +12 -20
- package/src/workspace/changes.ts +4 -1
- package/src/workspace/chant-migrations.e2e.test.ts +17 -5
- package/src/workspace/checks/boxes.test.ts +5 -0
- package/src/workspace/checks.ts +39 -8
- package/src/workspace/component-environments.test.ts +105 -0
- package/src/workspace/compose-graph.ts +7 -0
- package/src/workspace/composites.schema.json +23 -4
- package/src/workspace/composites.test.ts +8 -8
- package/src/workspace/composites.ts +13 -2
- package/src/workspace/conformance/__fixture__/decisions/decision.schema.json +2 -2
- package/src/workspace/conformance/__fixtures__/reference-broker.ts +207 -0
- package/src/workspace/conformance/__writer_fixture__/answers/answer.kind.mjs +32 -0
- package/src/workspace/conformance/__writer_fixture__/answers/answer.schema.json +135 -0
- package/src/workspace/conformance/__writer_fixture__/contracts/contract.kind.mjs +37 -0
- package/src/workspace/conformance/__writer_fixture__/contracts/contract.schema.json +213 -0
- package/src/workspace/conformance/__writer_fixture__/decisions/points.json +228 -0
- package/src/workspace/conformance/__writer_fixture__/drivers/driver.kind.mjs +15 -0
- package/src/workspace/conformance/__writer_fixture__/drivers/driver.schema.json +38 -0
- package/src/workspace/conformance/__writer_fixture__/sessions/session.kind.mjs +54 -0
- package/src/workspace/conformance/__writer_fixture__/sessions/session.schema.json +289 -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 +603 -0
- package/src/workspace/conformance/broker.test.ts +122 -0
- package/src/workspace/conformance/broker.ts +792 -0
- package/src/workspace/conformance/conformance.e2e.test.ts +36 -3
- package/src/workspace/conformance/index.mjs +51 -3
- package/src/workspace/conformance/index.ts +107 -15
- package/src/workspace/conformance/vitest.ts +76 -2
- package/src/workspace/conformance/writer-conformance.e2e.test.ts +177 -0
- package/src/workspace/conformance/writer.test.ts +186 -0
- package/src/workspace/conformance/writer.ts +1191 -0
- package/src/workspace/decide.test.ts +208 -4
- package/src/workspace/decide.ts +433 -73
- package/src/workspace/decision-points.schema.json +11 -4
- package/src/workspace/declaration.schema.json +383 -5
- package/src/workspace/declaration.ts +315 -10
- package/src/workspace/environments.ts +66 -14
- package/src/workspace/factory-rules.test.ts +62 -0
- package/src/workspace/factory-rules.ts +218 -0
- package/src/workspace/graph-cli.ts +6 -3
- package/src/workspace/graph.schema.json +314 -0
- package/src/workspace/identity.test.ts +219 -0
- package/src/workspace/identity.ts +186 -0
- package/src/workspace/init.ts +82 -2
- package/src/workspace/intent-cli.ts +84 -13
- package/src/workspace/intent-patch-id.test.ts +162 -0
- package/src/workspace/intent-record.schema.json +336 -1
- package/src/workspace/intent-record.ts +96 -16
- package/src/workspace/intent-reviews.test.ts +76 -0
- package/src/workspace/intent-squash.test.ts +213 -0
- package/src/workspace/intent-why.test.ts +274 -0
- package/src/workspace/intent.schema.json +950 -9
- package/src/workspace/intent.test.ts +11 -2
- package/src/workspace/intent.ts +722 -65
- package/src/workspace/json-edit.test.ts +121 -0
- package/src/workspace/json-edit.ts +142 -0
- package/src/workspace/jsonc.ts +20 -0
- package/src/workspace/kinds.ts +201 -39
- package/src/workspace/lexicon-symbols.test.ts +148 -0
- package/src/workspace/lexicon-symbols.ts +125 -0
- package/src/workspace/lineage-upgrade.test.ts +63 -0
- package/src/workspace/lineage-upgrade.ts +146 -5
- package/src/workspace/plan-summary.schema.json +155 -0
- package/src/workspace/point-answer.schema.json +42 -2
- package/src/workspace/points-cli.ts +42 -16
- package/src/workspace/points-write.schema.json +163 -4
- package/src/workspace/points.schema.json +157 -2
- package/src/workspace/points.test.ts +13 -1
- package/src/workspace/points.ts +118 -12
- package/src/workspace/pr-report.schema.json +95 -0
- package/src/workspace/principal-classes.test.ts +175 -0
- package/src/workspace/principal-classes.ts +307 -0
- package/src/workspace/profiles.test.ts +159 -0
- package/src/workspace/read-contract.test.ts +2 -2
- package/src/workspace/reason-codes.test.ts +23 -3
- package/src/workspace/reason-codes.ts +61 -4
- package/src/workspace/record-sessions.ts +9 -8
- package/src/workspace/records-amend.schema.json +80 -0
- package/src/workspace/records-checkout.ts +106 -0
- package/src/workspace/records-cli.ts +123 -17
- package/src/workspace/records-close.schema.json +79 -0
- package/src/workspace/records-close.ts +31 -7
- package/src/workspace/records-concurrent.e2e.test.ts +135 -0
- package/src/workspace/records-concurrent.test.ts +145 -0
- package/src/workspace/records-formats.test.ts +46 -10
- package/src/workspace/records-new.schema.json +9 -0
- package/src/workspace/records-review.schema.json +80 -0
- package/src/workspace/records-sessions-write.test.ts +69 -0
- package/src/workspace/records-sessions.test.ts +22 -0
- package/src/workspace/records-uncommitted.test.ts +171 -0
- package/src/workspace/records-write.ts +219 -30
- package/src/workspace/records.schema.json +88 -1
- package/src/workspace/records.ts +76 -8
- package/src/workspace/reference-kinds/app/package.json +10 -0
- package/src/workspace/reference-kinds/app/workspace-kinds.json +45 -0
- package/src/workspace/run-statement.schema.json +622 -0
- package/src/workspace/runs-cli.ts +710 -0
- package/src/workspace/runs-statement.test.ts +239 -0
- package/src/workspace/runs-write.schema.json +994 -0
- package/src/workspace/runs.schema.json +1257 -0
- package/src/workspace/runs.test.ts +281 -0
- package/src/workspace/runs.ts +970 -0
- package/src/workspace/session-kinds.ts +3 -3
- package/src/workspace/squash.ts +198 -0
- package/src/workspace/status-contract.test.ts +10 -2
- package/src/workspace/status-gates.ts +25 -9
- package/src/workspace/status.schema.json +252 -4
- package/src/workspace/status.ts +110 -1
- package/src/workspace/symbols.ts +191 -0
- 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/run-commits.ts +115 -0
- package/src/workspace/trust/run-statement.ts +226 -0
- package/src/workspace/trust/seal.ts +58 -1
- package/src/workspace/trust/verify-cli.ts +6 -5
- package/src/workspace/trust/verify.ts +39 -6
- package/src/workspace/wip-cli.ts +97 -0
- package/src/workspace/wip-write.schema.json +504 -0
- package/src/workspace/wip.schema.json +334 -0
- package/src/workspace/wip.test.ts +294 -0
- package/src/workspace/wip.ts +753 -0
- package/src/workspace/work-cli.e2e.test.ts +28 -1
- package/src/workspace/work-cli.ts +136 -8
- package/src/workspace/work-evidence.schema.json +5 -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-size.test.ts +77 -0
- package/src/workspace/work-size.ts +93 -0
- package/src/workspace/work.ts +82 -0
- package/src/workspace/workspace-kinds.schema.json +122 -0
- package/src/workspace/workspace-principals.schema.json +60 -0
- package/src/workspace/write-lock-cli.ts +131 -0
- package/src/workspace/write-lock.schema.json +172 -0
- package/src/workspace/write-lock.test.ts +189 -0
- package/src/workspace/write-lock.ts +474 -0
- package/src/workspace/write-scope.test.ts +144 -3
- package/src/workspace/write-scope.ts +192 -45
- package/src/yaml.test.ts +111 -1
- package/src/yaml.ts +141 -549
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #3146, ws-077: the factory and listing on a box block, the protected paths
|
|
3
|
+
* in writeScope, and whether a workspace is plantable.
|
|
4
|
+
*
|
|
5
|
+
* The declaration reads the fields with their defaults filled in, and a
|
|
6
|
+
* factory that names an undeclared member, or a second factory, fails the
|
|
7
|
+
* read (declaration-invalid, so check fails with WSP001). Everything is
|
|
8
|
+
* opt-in: a records-only workspace and an infra workspace that declares a
|
|
9
|
+
* factory with no box services both read and check cleanly. `status --json`
|
|
10
|
+
* and `graph --json` print the factory, the listing (with the cover's hash)
|
|
11
|
+
* and `plantable`; `check --changes` reports a write to a protected path with
|
|
12
|
+
* write-scope-protected, unless the entry's except allows the change.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { createHash } from "node:crypto";
|
|
16
|
+
import { writeFileSync } from "node:fs";
|
|
17
|
+
import { afterAll, beforeAll, describe, expect, test } from "vitest";
|
|
18
|
+
import { cleanScratch, commitAll, contract, git, repo, writeFiles } from "./__fixtures__/contract-repo";
|
|
19
|
+
import { agentSession } from "./agent-cli";
|
|
20
|
+
import agentSchema from "./agent.schema.json";
|
|
21
|
+
import { plantability } from "./box-factory";
|
|
22
|
+
import { checkChanges, type ChangesDocument } from "./changes";
|
|
23
|
+
import changesSchema from "./changes.schema.json";
|
|
24
|
+
import { runDeclarationChecks } from "./checks";
|
|
25
|
+
import { parseDeclaration, WorkspaceReadError, type Declaration } from "./declaration";
|
|
26
|
+
import { workspaceGraph } from "./graph-cli";
|
|
27
|
+
import graphSchema from "./graph.schema.json";
|
|
28
|
+
import { workspaceStatus } from "./status";
|
|
29
|
+
import statusSchema from "./status.schema.json";
|
|
30
|
+
import { judgePath, onlyKeysChanged, protectedEntry, resolveWriter } from "./write-scope";
|
|
31
|
+
import { emptyPolicy } from "./trust/policy";
|
|
32
|
+
|
|
33
|
+
afterAll(cleanScratch);
|
|
34
|
+
|
|
35
|
+
type Json = Record<string, unknown>;
|
|
36
|
+
|
|
37
|
+
const FACTORY = {
|
|
38
|
+
builds: ["studio"],
|
|
39
|
+
check: "npm run --silent check && npm test --silent",
|
|
40
|
+
checks: "checks",
|
|
41
|
+
builders: "steward",
|
|
42
|
+
publish: { repo: "arugula-salad/studio", branchPrefix: "box/" },
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const SERVICES = [{ name: "app", cmd: "node app.mjs", health: "http://127.0.0.1:5173/health" }];
|
|
46
|
+
|
|
47
|
+
function declaration(over: { box?: Json; members?: Json[]; writeScope?: Json; agents?: Json[] } = {}): Json {
|
|
48
|
+
return {
|
|
49
|
+
name: "studio",
|
|
50
|
+
schema: 1,
|
|
51
|
+
members: over.members ?? [
|
|
52
|
+
{ name: "studio", dir: ".", kind: "other", because: "the repo itself" },
|
|
53
|
+
{ name: "steward", dir: "steward", kind: "other", because: "the box's steward", box: over.box ?? { services: SERVICES, factory: FACTORY } },
|
|
54
|
+
],
|
|
55
|
+
...(over.writeScope ? { writeScope: over.writeScope } : {}),
|
|
56
|
+
...(over.agents ? { agents: over.agents } : {}),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const parse = (doc: Json): Declaration => parseDeclaration(JSON.stringify(doc, null, 2), "chant.workspace.json");
|
|
61
|
+
|
|
62
|
+
/** The error a declaration's read fails with, and the line of the file it points at. */
|
|
63
|
+
function readFailure(doc: Json): { code: string; message: string; at: string | undefined } {
|
|
64
|
+
const text = JSON.stringify(doc, null, 2);
|
|
65
|
+
try {
|
|
66
|
+
parseDeclaration(text, "chant.workspace.json");
|
|
67
|
+
} catch (err) {
|
|
68
|
+
if (err instanceof WorkspaceReadError) return { code: err.code, message: err.message, at: err.location ? text.split("\n")[err.location.line - 1]?.trim() : undefined };
|
|
69
|
+
throw err;
|
|
70
|
+
}
|
|
71
|
+
throw new Error("the declaration read");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
describe("the factory on a box block (#3146)", () => {
|
|
75
|
+
test("reads with its defaults filled in", () => {
|
|
76
|
+
const box = parse(declaration()).members[1].box!;
|
|
77
|
+
expect(box.factory).toEqual({
|
|
78
|
+
builds: ["studio"],
|
|
79
|
+
check: { run: "npm run --silent check && npm test --silent", kind: "test" },
|
|
80
|
+
checks: "checks",
|
|
81
|
+
builders: "steward",
|
|
82
|
+
tiers: [],
|
|
83
|
+
publish: { forge: "github", repo: "arugula-salad/studio", base: null, branchPrefix: "box/", head: null },
|
|
84
|
+
pointer: "/members/1/box/factory",
|
|
85
|
+
});
|
|
86
|
+
expect(box.listing).toBeNull();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("a check says what it is, a publish target names a base and a fork, and the branch prefix defaults to the work branch", () => {
|
|
90
|
+
const f = parse(
|
|
91
|
+
declaration({
|
|
92
|
+
box: { factory: { builds: ["studio", "steward"], check: { run: "chant build && chant lint", kind: "lint" }, publish: { repo: "acme/infra", base: "main", head: "alex/infra" } } },
|
|
93
|
+
}),
|
|
94
|
+
).members[1].box!.factory!;
|
|
95
|
+
expect(f.builds).toEqual(["studio", "steward"]);
|
|
96
|
+
expect(f.check).toEqual({ run: "chant build && chant lint", kind: "lint" });
|
|
97
|
+
expect(f.publish).toEqual({ forge: "github", repo: "acme/infra", base: "main", branchPrefix: "chant/work/", head: "alex/infra" });
|
|
98
|
+
expect(f.checks).toBeNull();
|
|
99
|
+
expect(f.builders).toBeNull();
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("builds must name a declared member", () => {
|
|
103
|
+
const failure = readFailure(declaration({ box: { factory: { builds: ["app"] } } }));
|
|
104
|
+
expect(failure.code).toBe("declaration-invalid");
|
|
105
|
+
expect(failure.message).toContain('the factory builds "app", which is not a declared member');
|
|
106
|
+
expect(failure.at).toBe('"app"');
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test("builders must name a declared member", () => {
|
|
110
|
+
const failure = readFailure(declaration({ box: { factory: { builds: ["studio"], builders: "delivery" } } }));
|
|
111
|
+
expect(failure.message).toContain('the factory\'s builders names "delivery"');
|
|
112
|
+
expect(failure.at).toBe('"builders": "delivery"');
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("a workspace has one factory", () => {
|
|
116
|
+
const failure = readFailure(
|
|
117
|
+
declaration({
|
|
118
|
+
members: [
|
|
119
|
+
{ name: "a", dir: "a", kind: "other", because: "a", box: { factory: { builds: ["a"] } } },
|
|
120
|
+
{ name: "b", dir: "b", kind: "other", because: "b", box: { factory: { builds: ["b"] } } },
|
|
121
|
+
],
|
|
122
|
+
}),
|
|
123
|
+
);
|
|
124
|
+
expect(failure.message).toContain("members a and b both declare a factory");
|
|
125
|
+
expect(failure.at).toBe('"factory": {');
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test("the schema refuses a factory without builds, an unknown check kind, a bad repo and an unknown field", () => {
|
|
129
|
+
expect(readFailure(declaration({ box: { factory: {} } })).code).toBe("declaration-invalid");
|
|
130
|
+
expect(readFailure(declaration({ box: { factory: { builds: ["studio"], check: { run: "x", kind: "smoke" } } } })).code).toBe("declaration-invalid");
|
|
131
|
+
expect(readFailure(declaration({ box: { factory: { builds: ["studio"], publish: { repo: "not a repo" } } } })).code).toBe("declaration-invalid");
|
|
132
|
+
expect(readFailure(declaration({ box: { factory: { builds: ["studio"], app: "studio" } } })).message).toContain('unknown field "app"');
|
|
133
|
+
// An x- field is still allowed, so a runtime can carry its own knobs beside chant's.
|
|
134
|
+
expect(parse(declaration({ box: { factory: { builds: ["studio"], "x-studio": { budget: 3 } } } })).members[1].box!.factory!.builds).toEqual(["studio"]);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
describe("the listing on a box block (#3146)", () => {
|
|
139
|
+
test("reads with its defaults: listed, empty title and line, no cover", () => {
|
|
140
|
+
expect(parse(declaration({ box: { listing: {} } })).members[1].box!.listing).toEqual({ published: true, title: "", line: "", cover: null });
|
|
141
|
+
expect(parse(declaration({ box: { listing: { published: false, title: "Fern", line: "A garden planner", cover: "steward/cover.png" } } })).members[1].box!.listing).toEqual({
|
|
142
|
+
published: false,
|
|
143
|
+
title: "Fern",
|
|
144
|
+
line: "A garden planner",
|
|
145
|
+
cover: "steward/cover.png",
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test("a title over 60 characters, a line over 140 and a control character are refused", () => {
|
|
150
|
+
expect(readFailure(declaration({ box: { listing: { title: "x".repeat(61) } } })).code).toBe("declaration-invalid");
|
|
151
|
+
expect(readFailure(declaration({ box: { listing: { line: "x".repeat(141) } } })).code).toBe("declaration-invalid");
|
|
152
|
+
expect(readFailure(declaration({ box: { listing: { title: "two\nlines" } } })).code).toBe("declaration-invalid");
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
describe("plantable (#3146)", () => {
|
|
157
|
+
test("exactly one member's box block declares services", () => {
|
|
158
|
+
expect(plantability(parse(declaration()))).toEqual({ plantable: true, box: "steward", reason: null });
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test("an infra workspace with a factory and no box services reads and checks cleanly, and isn't plantable (#3174)", async () => {
|
|
162
|
+
const doc = declaration({
|
|
163
|
+
members: [
|
|
164
|
+
{ name: "estate", dir: "estate", kind: "other", because: "terraform" },
|
|
165
|
+
{ name: "ops", dir: "ops", kind: "other", because: "the steward", box: { factory: { builds: ["estate"], check: { run: "terraform plan", kind: "plan" }, publish: { repo: "acme/estate" } } } },
|
|
166
|
+
],
|
|
167
|
+
});
|
|
168
|
+
const d = parse(doc);
|
|
169
|
+
expect(plantability(d)).toMatchObject({ plantable: false, box: null, reason: { code: "box-none" } });
|
|
170
|
+
const root = repo({ "chant.workspace.json": JSON.stringify(doc), "estate/main.tf": "", "ops/README.md": "" });
|
|
171
|
+
const { diagnostics } = await runDeclarationChecks(root);
|
|
172
|
+
expect(diagnostics.filter((x) => x.severity === "error")).toEqual([]);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test("a records-only workspace isn't plantable, and two boxes with services aren't either", () => {
|
|
176
|
+
expect(plantability(parse({ name: "notes", schema: 1, members: [] }))).toMatchObject({ plantable: false, reason: { code: "box-none" } });
|
|
177
|
+
const two = declaration({
|
|
178
|
+
members: [
|
|
179
|
+
{ name: "a", dir: "a", kind: "other", because: "a", box: { services: SERVICES } },
|
|
180
|
+
{ name: "b", dir: "b", kind: "other", because: "b", box: { services: SERVICES } },
|
|
181
|
+
],
|
|
182
|
+
});
|
|
183
|
+
expect(plantability(parse(two))).toMatchObject({ plantable: false, box: null, reason: { code: "box-several", message: expect.stringContaining("a, b") } });
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
describe("protected paths in writeScope (#3146)", () => {
|
|
188
|
+
const scope = {
|
|
189
|
+
agent: {
|
|
190
|
+
protected: ["ops", "decisions/**", { path: "chant.workspace.json", except: ["diagrams"] }],
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
const d = parse(declaration({ writeScope: scope, agents: [{ name: "builder", member: "studio" }] }));
|
|
194
|
+
const writer = resolveWriter(d, emptyPolicy(null), { agent: "builder" });
|
|
195
|
+
|
|
196
|
+
test("read in file order, with except empty for a glob", () => {
|
|
197
|
+
expect(d.writeScope!.agent!.protected).toEqual([
|
|
198
|
+
{ path: "ops", except: [] },
|
|
199
|
+
{ path: "decisions/**", except: [] },
|
|
200
|
+
{ path: "chant.workspace.json", except: ["diagrams"] },
|
|
201
|
+
]);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
test("an entry covers the files it matches and everything under a directory it matches", () => {
|
|
205
|
+
expect(protectedEntry(d.writeScope!.agent!.protected, "ops/factory/guard.mjs")?.path).toBe("ops");
|
|
206
|
+
expect(protectedEntry(d.writeScope!.agent!.protected, "decisions/ws-001.md")?.path).toBe("decisions/**");
|
|
207
|
+
expect(protectedEntry(d.writeScope!.agent!.protected, "opsy.md")).toBeNull();
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
test("a write to a protected path is out of scope, even in the session's own member", () => {
|
|
211
|
+
expect(judgePath(d, writer, "src/server.mjs")).toEqual({ ok: true });
|
|
212
|
+
expect(judgePath(d, writer, "ops/factory/guard.mjs")).toMatchObject({ ok: false, code: "write-scope-protected", message: expect.stringContaining("writeScope.agent.protected lists ops") });
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
test("except lets a JSON file change only in the keys it names", () => {
|
|
216
|
+
const before = JSON.stringify({ name: "studio", diagrams: [] });
|
|
217
|
+
const onlyDiagrams = JSON.stringify({ name: "studio", diagrams: [{ name: "flow" }] });
|
|
218
|
+
const alsoName = JSON.stringify({ name: "other", diagrams: [{ name: "flow" }] });
|
|
219
|
+
expect(onlyKeysChanged(before, onlyDiagrams, ["diagrams"])).toBe(true);
|
|
220
|
+
expect(onlyKeysChanged(before, alsoName, ["diagrams"])).toBe(false);
|
|
221
|
+
expect(onlyKeysChanged(null, onlyDiagrams, ["diagrams"])).toBe(false);
|
|
222
|
+
expect(onlyKeysChanged("not json", onlyDiagrams, ["diagrams"])).toBe(false);
|
|
223
|
+
expect(judgePath(d, writer, "chant.workspace.json", { before: () => before, after: () => onlyDiagrams })).toEqual({ ok: true });
|
|
224
|
+
expect(judgePath(d, writer, "chant.workspace.json", { before: () => before, after: () => alsoName })).toMatchObject({
|
|
225
|
+
ok: false,
|
|
226
|
+
code: "write-scope-protected",
|
|
227
|
+
message: expect.stringContaining("outside what its except allows (diagrams)"),
|
|
228
|
+
});
|
|
229
|
+
// Without the change in hand, an except entry can't be satisfied.
|
|
230
|
+
expect(judgePath(d, writer, "chant.workspace.json")).toMatchObject({ ok: false, code: "write-scope-protected" });
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
describe("the read contract: status, graph, agent and check --changes (#3146)", () => {
|
|
235
|
+
const status = contract(statusSchema);
|
|
236
|
+
const graph = contract(graphSchema);
|
|
237
|
+
const agent = contract(agentSchema);
|
|
238
|
+
const changes = contract(changesSchema);
|
|
239
|
+
const cover = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 1, 2, 3]);
|
|
240
|
+
const doc = declaration({
|
|
241
|
+
box: { services: SERVICES, factory: FACTORY, listing: { title: "Studio", line: "Where boxes are planted", cover: "steward/cover.png" } },
|
|
242
|
+
writeScope: { agent: { protected: ["ops", { path: "chant.workspace.json", except: ["diagrams"] }] } },
|
|
243
|
+
agents: [{ name: "builder", member: "studio" }],
|
|
244
|
+
});
|
|
245
|
+
let root: string;
|
|
246
|
+
|
|
247
|
+
beforeAll(() => {
|
|
248
|
+
root = repo({ "chant.workspace.json": `${JSON.stringify(doc, null, 2)}\n`, "steward/README.md": "the steward\n", "ops/guard.mjs": "export {};\n", "server.mjs": "export {};\n" });
|
|
249
|
+
writeFileSync(`${root}/steward/cover.png`, cover);
|
|
250
|
+
git(root, "add", "-A");
|
|
251
|
+
git(root, "commit", "-q", "-m", "the workspace");
|
|
252
|
+
git(root, "branch", "-M", "main");
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
test("status --json prints the factory, the listing with the cover's hash, and plantable", async () => {
|
|
256
|
+
const out = await workspaceStatus({ cwd: root, env: "prod" });
|
|
257
|
+
status.expectValid(out);
|
|
258
|
+
if ("error" in out) throw new Error(out.error.message);
|
|
259
|
+
expect(out.plantable).toEqual({ plantable: true, box: "steward", reason: null });
|
|
260
|
+
const box = out.members.find((m) => m.name === "steward")!.box!;
|
|
261
|
+
expect(box.factory).toEqual({
|
|
262
|
+
builds: ["studio"],
|
|
263
|
+
check: { run: "npm run --silent check && npm test --silent", kind: "test" },
|
|
264
|
+
checks: "checks",
|
|
265
|
+
builders: "steward",
|
|
266
|
+
tiers: [],
|
|
267
|
+
builderFor: { studio: {} },
|
|
268
|
+
publish: { forge: "github", repo: "arugula-salad/studio", base: null, branchPrefix: "box/", head: null },
|
|
269
|
+
});
|
|
270
|
+
expect(box.listing).toEqual({
|
|
271
|
+
published: true,
|
|
272
|
+
title: "Studio",
|
|
273
|
+
line: "Where boxes are planted",
|
|
274
|
+
cover: { path: "steward/cover.png", sha256: createHash("sha256").update(cover).digest("hex") },
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
test("graph --json prints them too, at a revision with --at", async () => {
|
|
279
|
+
const head = git(root, "rev-parse", "HEAD");
|
|
280
|
+
for (const at of [undefined, head]) {
|
|
281
|
+
const { doc: out } = await workspaceGraph({ cwd: root, at });
|
|
282
|
+
graph.expectValid(out);
|
|
283
|
+
if ("error" in out) throw new Error(out.error.message);
|
|
284
|
+
expect(out.plantable).toMatchObject({ plantable: true, box: "steward" });
|
|
285
|
+
const byName = Object.fromEntries(out.members.map((m) => [m.name, m.box]));
|
|
286
|
+
expect(byName.studio).toBeNull();
|
|
287
|
+
expect(byName.steward?.factory?.builds).toEqual(["studio"]);
|
|
288
|
+
expect(byName.steward?.listing?.cover?.sha256).toBe(createHash("sha256").update(cover).digest("hex"));
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
test("workspace agent lists the protected paths", async () => {
|
|
293
|
+
const out = await agentSession({ cwd: root, name: "builder" });
|
|
294
|
+
agent.expectValid(out);
|
|
295
|
+
if ("error" in out) throw new Error(out.error.message);
|
|
296
|
+
expect(out.scope.protected).toEqual([
|
|
297
|
+
{ path: "ops", except: [] },
|
|
298
|
+
{ path: "chant.workspace.json", except: ["diagrams"] },
|
|
299
|
+
]);
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
test("check --changes reports a write to a protected path, and lets an excepted key change", async () => {
|
|
303
|
+
git(root, "checkout", "-q", "-b", "work");
|
|
304
|
+
const trailer = "\n\nChant-Agent: builder";
|
|
305
|
+
writeFiles(root, { "server.mjs": "export const port = 1;\n" });
|
|
306
|
+
const ok = commitAll(root, `app: a port${trailer}`);
|
|
307
|
+
writeFiles(root, { "chant.workspace.json": `${JSON.stringify({ ...doc, diagrams: [] }, null, 2)}\n` });
|
|
308
|
+
const excepted = commitAll(root, `a diagram${trailer}`);
|
|
309
|
+
writeFiles(root, { "ops/guard.mjs": "export const off = true;\n" });
|
|
310
|
+
const guard = commitAll(root, `the steward${trailer}`);
|
|
311
|
+
writeFiles(root, { "chant.workspace.json": `${JSON.stringify({ ...doc, name: "renamed", diagrams: [] }, null, 2)}\n` });
|
|
312
|
+
const renamed = commitAll(root, `rename${trailer}`);
|
|
313
|
+
const { doc: out } = (await checkChanges({ cwd: root, range: "main..work" })) as { doc: Exclude<ChangesDocument, { error: unknown }> };
|
|
314
|
+
changes.expectValid(out);
|
|
315
|
+
const found = out.scope!.findings.map((f) => [f.commit, f.code, f.path]);
|
|
316
|
+
expect(found).toEqual([
|
|
317
|
+
[guard, "write-scope-protected", "ops/guard.mjs"],
|
|
318
|
+
[renamed, "write-scope-protected", "chant.workspace.json"],
|
|
319
|
+
]);
|
|
320
|
+
expect(found.map(([c]) => c)).not.toContain(ok);
|
|
321
|
+
expect(found.map(([c]) => c)).not.toContain(excepted);
|
|
322
|
+
});
|
|
323
|
+
});
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The factory and listing on a box block, and whether a workspace is
|
|
3
|
+
* plantable (#3146, ws-077), as `chant workspace status --json` and
|
|
4
|
+
* `chant workspace graph --json` print them.
|
|
5
|
+
*
|
|
6
|
+
* Every field here is opt-in (#3174): a workspace with no box, or a box with
|
|
7
|
+
* no `factory` or `listing`, reads as `null` for each, and plantability is a
|
|
8
|
+
* fact about the declaration, never a check that fails. A records-only
|
|
9
|
+
* workspace and an infra workspace with a factory and no box services both
|
|
10
|
+
* read and check cleanly; they just aren't plantable.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { createHash } from "node:crypto";
|
|
14
|
+
import type { BoxFactory, BoxListing, Declaration, FactoryCheckKind, FactoryTier } from "./declaration";
|
|
15
|
+
import type { ReasonCode } from "./reason-codes";
|
|
16
|
+
import type { WorkspaceTree } from "./tree";
|
|
17
|
+
|
|
18
|
+
/** Why a workspace isn't plantable. Closed. */
|
|
19
|
+
export const PLANTABLE_REASON_CODES = ["box-none", "box-several"] as const satisfies readonly ReasonCode[];
|
|
20
|
+
export type PlantableReasonCode = (typeof PLANTABLE_REASON_CODES)[number];
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Whether a host such as a studio's planter can plant the workspace as one
|
|
24
|
+
* box: exactly one member's box block declares services. `box` names that
|
|
25
|
+
* member, and is null when the workspace isn't plantable.
|
|
26
|
+
*/
|
|
27
|
+
export interface Plantable {
|
|
28
|
+
plantable: boolean;
|
|
29
|
+
box: string | null;
|
|
30
|
+
reason: { code: PlantableReasonCode; message: string } | null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** A box's factory as the read contract prints it: every field present, defaults filled in. */
|
|
34
|
+
export interface FactoryView {
|
|
35
|
+
builds: string[];
|
|
36
|
+
check: { run: string; kind: FactoryCheckKind } | null;
|
|
37
|
+
checks: string | null;
|
|
38
|
+
builders: string | null;
|
|
39
|
+
/** Which builder agent builds at which tier, as declared (#3152, ws-094); empty when none is. */
|
|
40
|
+
tiers: FactoryTier[];
|
|
41
|
+
/**
|
|
42
|
+
* The builder for each member the factory builds, by tier (#3152): the
|
|
43
|
+
* entry for the tier that names the member's kind, else the tier's entry
|
|
44
|
+
* with no kinds. A tier with no entry for the member is left out, so a
|
|
45
|
+
* reader resolves a work item's tier with one lookup, without studio.
|
|
46
|
+
*/
|
|
47
|
+
builderFor: Record<string, Record<string, { agent: string; session: string | null }>>;
|
|
48
|
+
publish: { forge: "github"; repo: string; base: string | null; branchPrefix: string; head: string | null } | null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** A box's listing as the read contract prints it, with the cover's hash when the file is there. */
|
|
52
|
+
export interface ListingView {
|
|
53
|
+
published: boolean;
|
|
54
|
+
title: string;
|
|
55
|
+
line: string;
|
|
56
|
+
/** The cover file from the workspace root and the sha256 of its bytes, null when the file can't be read; null when none is declared. */
|
|
57
|
+
cover: { path: string; sha256: string | null } | null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Whether the declaration is plantable (#3146): exactly one member's box block declares services. */
|
|
61
|
+
export function plantability(declaration: Declaration): Plantable {
|
|
62
|
+
const boxes = declaration.members.filter((m) => (m.box?.services.length ?? 0) > 0);
|
|
63
|
+
if (boxes.length === 1) return { plantable: true, box: boxes[0].name, reason: null };
|
|
64
|
+
if (boxes.length === 0) {
|
|
65
|
+
return { plantable: false, box: null, reason: { code: "box-none", message: "no member's box block declares services, so there is no box to plant" } };
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
plantable: false,
|
|
69
|
+
box: null,
|
|
70
|
+
reason: { code: "box-several", message: `members ${boxes.map((m) => m.name).join(", ")} each declare box services, and a planted workspace runs one box` },
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** A box's factory as the read contract prints it. `members` gives each built member's kind, for `builderFor`. */
|
|
75
|
+
export function factoryView(f: BoxFactory | null, members: readonly { name: string; kind: string }[] = []): FactoryView | null {
|
|
76
|
+
if (f === null) return null;
|
|
77
|
+
return {
|
|
78
|
+
builds: [...f.builds],
|
|
79
|
+
check: f.check === null ? null : { ...f.check },
|
|
80
|
+
checks: f.checks,
|
|
81
|
+
builders: f.builders,
|
|
82
|
+
tiers: f.tiers.map((t) => ({ ...t, kinds: t.kinds === null ? null : [...t.kinds] })),
|
|
83
|
+
builderFor: builderTable(f, members),
|
|
84
|
+
publish: f.publish === null ? null : { ...f.publish },
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** The builder table (#3152): for each built member, each tier's agent, by the member's kind first and the tier's default second. */
|
|
89
|
+
export function builderTable(f: BoxFactory, members: readonly { name: string; kind: string }[]): FactoryView["builderFor"] {
|
|
90
|
+
const tiers = [...new Set(f.tiers.map((t) => t.tier))];
|
|
91
|
+
const out: FactoryView["builderFor"] = {};
|
|
92
|
+
for (const name of f.builds) {
|
|
93
|
+
const kind = members.find((m) => m.name === name)?.kind;
|
|
94
|
+
const row: Record<string, { agent: string; session: string | null }> = {};
|
|
95
|
+
for (const tier of tiers) {
|
|
96
|
+
const entry =
|
|
97
|
+
f.tiers.find((t) => t.tier === tier && kind !== undefined && t.kinds?.includes(kind)) ?? f.tiers.find((t) => t.tier === tier && t.kinds === null);
|
|
98
|
+
if (entry) row[tier] = { agent: entry.agent, session: entry.session };
|
|
99
|
+
}
|
|
100
|
+
out[name] = row;
|
|
101
|
+
}
|
|
102
|
+
return out;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** The listing, hashing the cover through `read` (bytes, or null when the file can't be read). */
|
|
106
|
+
export function listingView(l: BoxListing | null, read: (path: string) => Uint8Array | null): ListingView | null {
|
|
107
|
+
if (l === null) return null;
|
|
108
|
+
let cover: ListingView["cover"] = null;
|
|
109
|
+
if (l.cover !== null) {
|
|
110
|
+
const bytes = read(l.cover);
|
|
111
|
+
cover = { path: l.cover, sha256: bytes === null ? null : createHash("sha256").update(bytes).digest("hex") };
|
|
112
|
+
}
|
|
113
|
+
return { published: l.published, title: l.title, line: l.line, cover };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** A reader of a file's bytes in `tree` for {@link listingView}: null when the file can't be read. */
|
|
117
|
+
export function treeBytes(tree: WorkspaceTree): (path: string) => Uint8Array | null {
|
|
118
|
+
return (path) => {
|
|
119
|
+
try {
|
|
120
|
+
if (tree.stat(path) !== "file") return null;
|
|
121
|
+
return tree.bytes ? tree.bytes(path) : new TextEncoder().encode(tree.read(path));
|
|
122
|
+
} catch {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** The box fields the graph prints on a member (#3146): its factory and listing, or null when the member's box declares neither. */
|
|
129
|
+
export function graphBox(
|
|
130
|
+
box: { factory: BoxFactory | null; listing: BoxListing | null } | null,
|
|
131
|
+
tree: WorkspaceTree,
|
|
132
|
+
members: readonly { name: string; kind: string }[] = [],
|
|
133
|
+
): { factory: FactoryView | null; listing: ListingView | null } | null {
|
|
134
|
+
if (box === null || (box.factory === null && box.listing === null)) return null;
|
|
135
|
+
return { factory: factoryView(box.factory, members), listing: listingView(box.listing, treeBytes(tree)) };
|
|
136
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://intentius.io/chant/schemas/workspace/box-listing-write/v1/box-listing-write.schema.json",
|
|
4
|
+
"title": "chant workspace box listing set output",
|
|
5
|
+
"description": "What `chant workspace box listing set <member> [--from <file|->] [--cover <image>]` prints (#3308): the box's listing before and after, the files the write changed, and the cover it copied, or the reason it wrote nothing. The write changes only members[i].box.listing in the declaration, in place, keeping the file's formatting and comments, and the cover file it copies. It never commits. Readers ignore fields they do not know; a field is only ever added within a version. The error codes are a closed list, each in the one closed list of `reason-codes.ts`. Contract version 1 of this document is written by chant 0.103.0 and newer.",
|
|
6
|
+
"oneOf": [
|
|
7
|
+
{
|
|
8
|
+
"$ref": "#/$defs/result"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"$ref": "#/$defs/failure"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"$defs": {
|
|
15
|
+
"result": {
|
|
16
|
+
"description": "The listing was written, or would be with --dry-run, or already held what was given (changed false). Exit code 0.",
|
|
17
|
+
"type": "object",
|
|
18
|
+
"required": ["$schema", "contract", "chant", "member", "declaration", "paths", "changed", "dryRun", "previous", "listing", "cover"],
|
|
19
|
+
"properties": {
|
|
20
|
+
"$schema": {
|
|
21
|
+
"const": "https://intentius.io/chant/schemas/workspace/box-listing-write/v1/box-listing-write.schema.json"
|
|
22
|
+
},
|
|
23
|
+
"contract": {
|
|
24
|
+
"const": 1
|
|
25
|
+
},
|
|
26
|
+
"chant": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"description": "The chant that wrote it."
|
|
29
|
+
},
|
|
30
|
+
"member": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"description": "The member whose box block holds the listing."
|
|
33
|
+
},
|
|
34
|
+
"declaration": {
|
|
35
|
+
"type": "object",
|
|
36
|
+
"required": ["path", "sha256"],
|
|
37
|
+
"properties": {
|
|
38
|
+
"path": {
|
|
39
|
+
"type": "string",
|
|
40
|
+
"description": "The declaration file, relative to the repository root (the working directory outside git), with / separators."
|
|
41
|
+
},
|
|
42
|
+
"sha256": {
|
|
43
|
+
"type": "string",
|
|
44
|
+
"pattern": "^[0-9a-f]{64}$",
|
|
45
|
+
"description": "The sha256 of the declaration's bytes after the write, or as they would be with --dry-run."
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"paths": {
|
|
50
|
+
"type": "array",
|
|
51
|
+
"items": {
|
|
52
|
+
"type": "string"
|
|
53
|
+
},
|
|
54
|
+
"description": "Every file the write changed, or would change with --dry-run, relative to the repository root: the cover it copied, then the declaration. Empty when the listing and cover already held what was given."
|
|
55
|
+
},
|
|
56
|
+
"changed": {
|
|
57
|
+
"type": "boolean",
|
|
58
|
+
"description": "Whether any file changed: paths is not empty."
|
|
59
|
+
},
|
|
60
|
+
"dryRun": {
|
|
61
|
+
"type": "boolean",
|
|
62
|
+
"description": "True when --dry-run was given and nothing was written."
|
|
63
|
+
},
|
|
64
|
+
"previous": {
|
|
65
|
+
"description": "The listing before the write, as chant workspace status --json prints it, or null when the box declared none.",
|
|
66
|
+
"oneOf": [
|
|
67
|
+
{
|
|
68
|
+
"type": "null"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"$ref": "#/$defs/listing"
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
"listing": {
|
|
76
|
+
"$ref": "#/$defs/listing",
|
|
77
|
+
"description": "The listing after the write, as chant workspace status --json prints it, defaults filled in and the cover hashed."
|
|
78
|
+
},
|
|
79
|
+
"cover": {
|
|
80
|
+
"description": "The image --cover copied in, or null without --cover.",
|
|
81
|
+
"oneOf": [
|
|
82
|
+
{
|
|
83
|
+
"type": "null"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"type": "object",
|
|
87
|
+
"required": ["path", "sha256", "bytes", "type", "replaced"],
|
|
88
|
+
"properties": {
|
|
89
|
+
"path": {
|
|
90
|
+
"type": "string",
|
|
91
|
+
"description": "Where it was copied, from the workspace root: --cover-path, else the listing's cover when its extension fits, else <member dir>/listing/cover.<png|jpg|webp>."
|
|
92
|
+
},
|
|
93
|
+
"sha256": {
|
|
94
|
+
"type": "string",
|
|
95
|
+
"pattern": "^[0-9a-f]{64}$"
|
|
96
|
+
},
|
|
97
|
+
"bytes": {
|
|
98
|
+
"type": "integer",
|
|
99
|
+
"minimum": 0
|
|
100
|
+
},
|
|
101
|
+
"type": {
|
|
102
|
+
"enum": ["image/png", "image/jpeg", "image/webp"]
|
|
103
|
+
},
|
|
104
|
+
"replaced": {
|
|
105
|
+
"type": ["string", "null"],
|
|
106
|
+
"description": "The cover the listing named before, from the workspace root, when it was another file. That file is left in place; the caller removes it in the same commit if nothing else uses it."
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
"listing": {
|
|
115
|
+
"type": "object",
|
|
116
|
+
"required": ["published", "title", "line", "cover"],
|
|
117
|
+
"properties": {
|
|
118
|
+
"published": {
|
|
119
|
+
"type": "boolean"
|
|
120
|
+
},
|
|
121
|
+
"title": {
|
|
122
|
+
"type": "string"
|
|
123
|
+
},
|
|
124
|
+
"line": {
|
|
125
|
+
"type": "string"
|
|
126
|
+
},
|
|
127
|
+
"cover": {
|
|
128
|
+
"oneOf": [
|
|
129
|
+
{
|
|
130
|
+
"type": "null"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"type": "object",
|
|
134
|
+
"required": ["path", "sha256"],
|
|
135
|
+
"properties": {
|
|
136
|
+
"path": {
|
|
137
|
+
"type": "string",
|
|
138
|
+
"description": "From the workspace root."
|
|
139
|
+
},
|
|
140
|
+
"sha256": {
|
|
141
|
+
"type": ["string", "null"],
|
|
142
|
+
"pattern": "^[0-9a-f]{64}$"
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
"failure": {
|
|
151
|
+
"type": "object",
|
|
152
|
+
"description": "Nothing was written. Exit code 1.",
|
|
153
|
+
"required": ["$schema", "contract", "chant", "member", "error"],
|
|
154
|
+
"properties": {
|
|
155
|
+
"$schema": {
|
|
156
|
+
"const": "https://intentius.io/chant/schemas/workspace/box-listing-write/v1/box-listing-write.schema.json"
|
|
157
|
+
},
|
|
158
|
+
"contract": {
|
|
159
|
+
"const": 1
|
|
160
|
+
},
|
|
161
|
+
"chant": {
|
|
162
|
+
"type": "string"
|
|
163
|
+
},
|
|
164
|
+
"member": {
|
|
165
|
+
"type": ["string", "null"]
|
|
166
|
+
},
|
|
167
|
+
"error": {
|
|
168
|
+
"type": "object",
|
|
169
|
+
"required": ["code", "message"],
|
|
170
|
+
"properties": {
|
|
171
|
+
"code": {
|
|
172
|
+
"enum": [
|
|
173
|
+
"declaration-missing",
|
|
174
|
+
"declaration-ambiguous",
|
|
175
|
+
"declaration-unparseable",
|
|
176
|
+
"declaration-invalid",
|
|
177
|
+
"placement-invalid",
|
|
178
|
+
"reader-too-old",
|
|
179
|
+
"root-chant-required",
|
|
180
|
+
"not-a-git-repository",
|
|
181
|
+
"revision-unknown",
|
|
182
|
+
"write-usage-invalid",
|
|
183
|
+
"write-input-invalid",
|
|
184
|
+
"listing-member-unknown",
|
|
185
|
+
"listing-box-missing",
|
|
186
|
+
"listing-cover-invalid",
|
|
187
|
+
"write-scope-member",
|
|
188
|
+
"write-scope-protected",
|
|
189
|
+
"write-scope-class-unknown",
|
|
190
|
+
"agent-unknown",
|
|
191
|
+
"principal-unidentified",
|
|
192
|
+
"write-lock-timeout",
|
|
193
|
+
"write-lock-not-held"
|
|
194
|
+
]
|
|
195
|
+
},
|
|
196
|
+
"message": {
|
|
197
|
+
"type": "string"
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|